home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1890 / ORIGIN next >
Encoding:
Text File  |  1990-12-28  |  22.4 KB  |  403 lines

  1. >> Commentary by dbell
  2. >> This is the original article included with the xlife 2.0 sources in
  3. >> which Dean Hickerson described how his life search program works.
  4. >> Note: His mail address is no longer valid (and he doesn't have one).
  5. >> Also, the 25 bit period 3 spaceship referred to below is the following:
  6. >> .............**
  7. >> .**...*...*....*
  8. >> *......**..****
  9. >> .***.**.*.**
  10. >> .....*.**
  11. >>
  12. Return-path: <HUL@PSUVM.PSU.EDU>
  13. X-Andrew-Authenticated-as: 0;andrew.cmu.edu;Network-Mail
  14. Received: from po3.andrew.cmu.edu via trymail
  15.           ID </afs/andrew.cmu.edu/usr14/jb7m/Mailbox/0Zft7HK00UkT8HJU8F>;
  16.           Sat, 13 Jan 90 15:38:45 -0500 (EST)
  17. Message-ID: <Added.AZft7Em00UkTQHJU5q@andrew.cmu.edu>
  18. Received: from PSUVM.PSU.EDU by po3.andrew.cmu.edu (5.54/3.15) id <AA04945> for jb7m+; Sat, 13 Jan 90 15:38:10 EST
  19. Received: from PSUVM.BITNET by PSUVM.PSU.EDU (IBM VM SMTP R1.2.1MX) with BSMTP id 0991; Sat, 13 Jan 90 15:38:55 EST
  20. Received: by PSUVM (Mailer R2.03B) id 3407; Sat, 13 Jan 90 15:38:54 EST
  21. Date:    Sat, 13 Jan 90 15:38 EST
  22. From: "Dean Hickerson" <HUL@PSUVM.PSU.EDU>
  23. Subject: Search program
  24. To: jb7m+@andrew.cmu.edu
  25.  
  26. >  A number of time you have said that the patterns you were sending had been
  27. >  found by a search program. I was wondering if you would mind sending me a
  28. >  copy of it too look at.
  29.  
  30. The program is written in 6502 assembly language and Applesoft BASIC and
  31. runs on an Apple IIe.  Unless you have a compatible machine, the program
  32. itself probably wouldn't help you much.  But here's a fairly detailed
  33. description of how it works.  I encourage you (or anyone else) to write a
  34. similar program for a faster machine; I'm sure there are things waiting to
  35. be found that my Apple is slow to find.
  36.  
  37. If you really want to see the program itself, let me know and I'll try to
  38. find a way to send it.  (It's not easy, because of incompatible operating
  39. systems and file structures.)
  40. ========================================================================
  41. General description of the Life search program  (9/6/89)
  42.  
  43.      This is a general description of the program and some discussion of
  44. its behaviour.  A much more detailed description follows.
  45.  
  46.      I tell the program the desired congruence period T of an object, a
  47. rectangle in which generations 0 to T must fit, and an isometry relating
  48. gen. 0 to gen. T.  The program creates a 3D array in which each cell is
  49. either on, off, or unknown; initially everything's unknown except for any
  50. initial conditions which I specify.  It then picks an unknown cell, chooses
  51. a value for it, and examines the consequences of its choice, working both
  52. forward and backward.  If it runs out of consequences, it picks another
  53. unknown cell and continues.  If it finds a contradiction, it backs up to
  54. its most recent choice, reverses it, marks it as a conclusion rather than a
  55. choice, and continues. Eventually it either runs out of unknown cells and
  56. reports that it's found something, or tries to back up past its first
  57. choice and reports that the object doesn't exist.  (Or it would if I let it
  58. run forever; more often I stop it after a while.)  I can have it display
  59. the array at any time; sometimes I can figure out something interesting
  60. from its partial results.  E.g. I built the 25 bit c/3 spaceship from parts
  61. it had found in previous searches; the program found it about an hour
  62. later.
  63.  
  64.    One problem I sometimes have is that the program finds things with
  65. periods smaller than I want, like 1.  So I usually specify the value of
  66. some particular cell in enough phases to force it to have the desired
  67. period.  (Of course I may miss something interesting that way.)  Another
  68. problem is that after the program finds something which is smaller than the
  69. specified rectangle, it then finds the same thing with various stable
  70. objects around the unoccupied edges.  So I back it up 'by hand' far enough
  71. to get to something new.
  72.  
  73.    I haven't really settled on the best order in which to select unknown
  74. cells.  I usually work in a rectangle which is wide but not very tall and
  75. proceed up the columns from left to right, either just in gen. 0 or doing
  76. all phases for each position before moving to the next.  I've tried some
  77. searches starting at the center of a square and spiralling
  78. outward, but the program tends to bog down when it's far from the center: a
  79. bad choice for a cell may not be detected until the spiral comes back
  80. around to it, so it will try many possibilities for the intervening cells
  81. of the spiral before it changes the bad cell.  Probably I should use a
  82. self-adjusting search order; when a problem is detected, the program should
  83. move nearby cells closer to the front of the search list.  My first
  84. implementation of this actually made the program slower, since cells which
  85. got moved to the front of the list stayed near there even when they were no
  86. longer a problem.  I have an idea for a better way to do it, but I haven't
  87. had time to implement it yet.
  88.  
  89.    Another thing I'm still experimenting with is how to decide whether to
  90. turn an unknown cell on or off.  If I'm going to let the search run to
  91. completion it doesn't matter; both choices will be tried eventually.  But
  92. for incomplete searches some heuristics might help.  Usually I choose 'off'
  93. first, in the hope that an object of small population will be found.
  94. Another good choice is to make a location have the same value at time t as
  95. at other, already assigned, times; this tends to lead to billiard tables.
  96.  
  97.    The program is most effective when the period is small; the forward and
  98. backward conclusions tend to wrap around the ends of time and meet, leading
  99. to more conclusions or contradictions.  For large periods, that doesn't
  100. happen much, so the program doesn't detect its bad choices soon enough to
  101. accomplish much.  The p5 fumarole and one other p5 are the only things
  102. I've found so far with a congruence period greater than 4.
  103. ----------------------------------------------------------------------
  104.  
  105. Detailed description of the Life search program  (9/24/89)
  106.  
  107.      The program consists of two parts, an assembly language part which
  108. does the searching and a BASIC program which handles initialization,
  109. interpreting commands from the user, and display.  I'll talk mostly about
  110. the assembly language portion.
  111.  
  112.      Three constants describe the size of the space being searched:
  113.  
  114.           TP = time period, length of time until pattern is to reappear;
  115.           XM = width of rectangle to be searched;
  116.           YM = height of rectangle to be searched.
  117.  
  118. The set of pairs (X,Y) with 0<=X<XM and 0<=Y<YM will be called "the
  119. rectangle".
  120.  
  121.      There are 12 constants which describe how generation 0 is related to
  122. generation TP:  A, B, C, D, E, F, A', B', C', D', E', F'.  The cell with
  123. coordinates (X, Y) in generation 0 is mapped to the cell with coordinates
  124. (AX+BY+C, DX+EY+F) in generation TP.  The cell with coordinates (X, Y) in
  125. generation TP is mapped to the cell (A'X+B'Y+C', D'X+E'Y+F') in generation
  126. 0.  The values of A thru F are specified by the user; the others are given
  127. by:
  128.     A' =  E/Z,   B' = -B/Z,   C' = (BF-CE)/Z,
  129.     D' = -D/Z,   E' =  A/Z,   F' = (CD-AF)/Z,
  130. where   Z = AE-BD = 1 or -1.  The mappings are supposed to be isometries,
  131. not general invertible linear maps, so there are severe restrictions on A,
  132. B, D, and E which I won't bother to write down.  (There is also a boolean
  133. variable, USEMAP, which is normally true.  If it is false, then the
  134. mappings are ignored, so the program can be used to search for predecessors
  135. of whatever the user puts in generation TP.)
  136.  
  137.      The current information about generations 0 to TP is kept in a 3
  138. dimensional array CELL, with dimensions 0 to TP, 0 to XM-1, and 0 to YM-1.
  139. Each entry can have one of 3 values, 0=off, 1=on, or UNK=unknown.  (I use a
  140. whole byte for each entry, with UNK=$10.  (Here and later, a dollar sign
  141. indicates that a number is in base 16.)  This makes the computation of the
  142. neighborhood easy: just add the values of the 8 neighbors; the high nybble
  143. is the number of unknown neighbors, and the low nybble is the number which
  144. are on.) Initially the edges (all elements with X=0 or XM-1 or Y=0 or YM-1)
  145. are turned off, as are the cells in generation 0 which map outside the
  146. rectangle in generation TP and vice versa; everything else is initially
  147. unknown.  After this initialization, some user-specified cells may be
  148. turned on or off, by calling PROCEED (described later).
  149.  
  150.      In addition to CELL, one other large array is used, the setting list.
  151. This is a list of quintuples (T, X, Y, VALUE, FREE) where 0<=T=TP, 0<=X<XM,
  152. 0<=Y<YM, VALUE=0 or 1, and FREE=true or false.  Whenever an element of CELL
  153. is changed from UNK to 0 or 1, an entry is added to the list.  FREE is true
  154. if the change is a free choice, false if it's forced by some previous
  155. choice.  There are 3 pointers into the list:
  156.           STNG   points to the beginning;
  157.           NWSTNG points to the end; new entries are put here;
  158.           NXSTNG points to the next setting whose consequences are to
  159.                  be examined.
  160.  
  161.      There are also two tables which are used to describe the Life
  162. transition rules.  Conceptually, an index into either table consists of a
  163. cell value (0, 1, or UNK) and 3 numbers which add up to 8, telling how many
  164. neighbors are 0, 1, and UNK; there are 135 (=3*45) possible indices.  In
  165. practice, I use a one byte 'neighborhood descriptor' to encode this, so
  166. each table is 256 bytes long, but only partially used.  To compute the
  167. neighborhood descriptor of a cell, add up the 8 neighbors.  If the AND of
  168. the sum and $88 is zero, then the neighborhood descriptor is twice the sum
  169. plus the cell.  If the AND is nonzero, the descriptor is the sum plus twice
  170. the cell plus $11.
  171.  
  172.      The first table is called TRANSIT and tells what the cell should be in
  173. the next generation.  E.g. neighborhood descriptor $25 means that the
  174. cell is 1, 5 of its neighbors are 0, 2 are 1, and 1 is unknown,
  175. TRANSIT[$25] = 1.  Of course, most entries in TRANSIT are UNK, 73 to be
  176. exact.  (And 57 are 0 and 5 are 1.)
  177.  
  178.      The second table is called IMPLIC and contains information about
  179. implications in the other direction.  If we know the neighborhood
  180. descriptor and the value of the cell in the next generation, we may be able
  181. to conclude that some unknown cells in this generation must be 0 or 1.
  182. Such conclusions exist only if the corresponding entry is UNK, so there are
  183. only 73 entries in IMPLIC.   There are 8 possible implications, each is
  184. given by one bit in the IMPLIC entry:
  185.  
  186.      Bit       Meaning
  187.      $80       If new cell is 0 then current cell should be 0.
  188.      $40       If new cell is 0 then current cell should be 1.
  189.      $20       If new cell is 1 then current cell should be 0.
  190.      $10       If new cell is 1 then current cell should be 1.
  191.      $08       If new cell is 0 then all unknown neighbors should be 0.
  192.      $04       If new cell is 0 then all unknown neighbors should be 1.
  193.      $02       If new cell is 1 then all unknown neighbors should be 0.
  194.      $01       If new cell is 1 then all unknown neighbors should be 1.
  195.  
  196. (In Life, bits $40 and $20 are never set, but they may occur for other
  197. transition rules.)  For example, bit $80 is set iff the current cell is
  198. unknown, exactly 2 of its neighbors are 1, and at most 1 of its neighbors
  199. is unknown, i.e. for neighborhood descriptors $14 and $34.
  200.  
  201.      The two tables were created by a BASIC program and are now loaded from
  202. disk as part of the initialization.
  203.  
  204.      The basic operation of the program is as follows: Suppose that CELL is
  205. fully consistent; i.e. every cell is consistent with its 9 parents and no
  206. currently unknown cells have their values forced.  (That is, forced
  207. directly, either by their parents or their children.)  In this situation,
  208. NXSTNG = NWSTNG.
  209.  
  210. Step 0:  ('Pick an unknown cell')  If there are no unknown cells left,
  211. report that an object has been found, let the user display it, save it on
  212. disk, print it, or whatever; then go to step 2.  Otherwise, pick an unknown
  213. cell and a value for it.  Change it in CELL and add an entry to the setting
  214. list with FREE=true, updating NWSTNG.  Go to step 1.
  215.  
  216. Step 1:  ('Examine consequences')  If NXSTNG = NWSTNG, then CELL is fully
  217. consistent; go to step 0.  Otherwise, get the values of T, X, Y, and VALUE
  218. pointed to by NXSTNG and increment NXSTNG.  The fact that CELL[T,X,Y] =
  219. VALUE may directly force some currently unknown cells to be 0 or 1; for
  220. each of these, set its value in CELL and add an entry to the setting list
  221. with FREE=false, incrementing NWSTNG.  Then go to step 1.  We may also
  222. detect a contradiction at this point; in that case go to step 2.  (The
  223. forcing in this step is of 4 types:  If T=0 or TP, the mapped cell in
  224. generation TP or 0 is forced.  Some of the parents of (T,X,Y) may be
  225. forced.  Some of the children of (T,X,Y) may be forced.  And some cells may
  226. be forced by additional constraints such as symmetry.)
  227.  
  228. Step 2:  ('Back up'.  At this point, either a contradiction has been
  229. detected or we've found an object and wish to look for more.)  If NWSTNG =
  230. STNG, report that no more objects of the desired type exist and quit.
  231. Otherwise, decrement NWSTNG and get the values of T, X, Y, VALUE, and FREE
  232. pointed to by it.  If FREE = false, set CELL[T,X,Y] to UNK and go to step
  233. 2.  If FREE = true, then either we've found that this free choice led to a
  234. contradiction or we've already found all objects in which the choice was
  235. valid.  So change CELL[T,X,Y] to 1-VALUE, change FREE to false, set NXSTNG
  236. to NWSTNG, increment NWSTNG, and go to step 1.
  237.  
  238.      As described here, part of step 0 involves returning control to the
  239. BASIC part of the program.  But on my system it's not convenient to have a
  240. machine language routine call a BASIC routine, so I've rearranged things
  241. slightly.
  242.  
  243.      I'll now describe the machine language routines. Unless otherwise
  244. indicated, the parameters T, X, Y, VALUE, and FREE are assumed to
  245. satisfy  0<=T<=TP,  0<=X<XM,  0<=Y<YM,  VALUE = 0, 1, or UNK,  FREE = true
  246. or false.
  247.  
  248.      Many of these routines sometimes detect an error; they report this to
  249. the calling routine by setting the carry bit and storing a value in the
  250. variable ERRCODE to tell which error occurred.  (Calling these 'errors' is
  251. misleading, since they can occur during the normal course of events and
  252. some are even desirable.  But 'exceptional conditions' is too long, so I'll
  253. continue to call them errors.)
  254.  
  255. LOOKUP(T,X,Y):  Return the address and value of CELL[T,X,Y]. (This routine
  256. gets called more often than any other, so should be fast.  I actually
  257. implemented it as an assembly language macro rather than as a subroutine.
  258. The duplicated code made the program a bit larger, but also made it about
  259. 10% faster.  I also have faster versions for the special cases in which the
  260. cell being looked up is adjacent to the one previously looked up. This
  261. speeds up the neighborhood calculation in GETNBHD.)
  262.  
  263. MAP(X,Y):  Return the coordinates of the cell in generation TP
  264. corresponding to the cell (0,X,Y).  Report an 'out of bounds' error if the
  265. mapped coordinates are not in the rectangle.
  266.  
  267. INVMAP(X,Y):  Return the coordinates of the cell in generation 0
  268. corresponding to the cell (TP,X,Y). Report an 'out of bounds' error if the
  269. mapped coordinates are not in the rectangle.
  270.  
  271. NWSET(T,X,Y,VALUE,FREE):  Store a quintuple at NWSTNG and increment NWSTNG.
  272.  
  273. SETCELL(T,X,Y,VALUE,FREE):  (Should not be called with VALUE = UNK.)  Look
  274. up CELL[T,X,Y].  If it equals VALUE, do nothing.  If it equals 1-VALUE,
  275. report an 'inconsistency' error.  If it is unknown, set it to VALUE and
  276. call NWSET to add the quintuple to the setting list.
  277.  
  278. GETNBHD(T,X,Y):  (Should not be called with T=0.)  Return the neighborhood
  279. descriptor for (T-1,X,Y); i.e. describing the parents of (T,X,Y).  Note: If
  280. (X,Y) is on the boundary of the rectangle, then GETNBHD assumes that the
  281. neighbors which are outside are 0.  There are some situations in which it
  282. would be better to assume they are UNK.
  283.  
  284. CONSISFY(T,X,Y):  (Should not be called with T=0.  X and Y may be out of
  285. bounds, in which case the routine does nothing.)  Make (T,X,Y) fully
  286. consistent with its parents.  Specifically:  Compute the neighborhood
  287. descriptor of (T-1,X,Y), and look it up in TRANSIT and IMPLIC.  If the
  288. entry in TRANSIT is 0 or 1 and the value of CELL[T,X,Y] is 1 or 0,
  289. respectively, report an 'inconsistency' error.  Otherwise call SETCELL
  290. (with FREE=false) for any of (T,X,Y) or its parents which are currently
  291. unknown but are forced to be 0 or 1.
  292.  
  293. CONSIS10(T,X,Y):  Call CONSISFY for (T,X,Y) (provided that T>0) and for
  294. each of its 9 children (provided that T<TP).  Report any 'inconsistency'
  295. error found by CONSISFY.
  296.  
  297. APPLYMAP(T,X,Y,VALUE):  (Should not be called with VALUE = UNK.)  If USEMAP
  298. = false, do nothing.  Otherwise, if T = 0 or TP, call MAP or INVMAP.  If
  299. the mapped cell is out of bounds, do nothing.  Otherwise, call SETCELL for
  300. the mapped cell and VALUE, with FREE=false.  Report any 'inconsistency'
  301. error found by SETCELL.
  302.  
  303. SYMM(T,X,Y,VALUE):  (Should not be called with VALUE = UNK.) This routine
  304. deals with symmetry, billiard tablicity, and other restrictions desired by
  305. the user.  Separate versions of it exist for different situations.  Each
  306. one looks at T, X, Y, and VALUE, decides if any other cells are forced, and
  307. calls SETCELL for them, reporting any 'inconsistency' errors.  (Suppose for
  308. example that we want a pattern to have 90 degree rotational symmetry.  Then
  309. SYMM could compute the coordinates of the cell obtained by rotating (X,Y)
  310. 90 degrees about the center of symmetry and call SETCELL for it.  It is not
  311. necessary to do the same for the 180 and 270 degree
  312. rotations; the higher levels of the program will take care of that.)
  313.  
  314. EXAMNEXT:  If NXSTNG = NWSTNG, report a 'full consistency achieved' error.
  315. Otherwise, get the values of T, X, Y, and VALUE pointed to by NXSTNG, and
  316. increment NXSTNG. Call APPLYMAP, SYMM, and CONSIS10, reporting any errors
  317. found by them.  (If one of the routines gives an error, it's not necessary
  318. to call the others.)
  319.  
  320. PROCEED(T,X,Y,VALUE,FREE):  Call SETCELL, reporting an 'inconsistency'
  321. error if it finds one.  Otherwise, call EXAMNEXT repeatedly.  Eventually,
  322. it will report either an inconsistency or full consistency.  In the first
  323. case, report it.  In the second case, return without reporting an error.
  324. This routine is called whenever we either make a free choice for a cell or
  325. have backed up to a free choice and now want to try the other value there;
  326. it finds all the (direct or indirect) conclusions (or a contradiction) from
  327. the choice.  It can also be called from the BASIC program to initialize
  328. certain cells.  (Note: After BASIC has done such initialization, it can set
  329. NXSTNG and NWSTNG equal to STNG in order to save space; since we don't want
  330. to back up over the initialized cells, we don't need to remember them in
  331. the setting list.)
  332.  
  333. BACKUP:  Undo all settings from NWSTNG back to (and including) the most
  334. recent free choice, changing their values in CELL back to UNK.  If we back
  335. up all the way to STNG, report an 'object does not exist' error. Otherwise,
  336. make NWSTNG and NXSTNG point to the free choice and return the values of T,
  337. X, Y, and VALUE from it.  (This corresponds to repeated application of Step
  338. 2 in the program outline above.)
  339.  
  340. GO(T,X,Y,VALUE,FREE):  [I ran out of good descriptive subroutine names.]
  341. Call PROCEED(T,X,Y,VALUE,FREE).  If it returns without an error, then full
  342. consistency has been achieved; return without an error.  Otherwise call
  343. BACKUP, reporting an 'object does not exist' error if BACKUP finds one.
  344. Otherwise, call PROCEED(T,X,Y,1-VALUE,false).  Continue calling PROCEED and
  345. BACKUP alternately until either full consistency is achieved or an 'object
  346. does not exist' error occurs. (This corresponds to repeated application of
  347. Steps 1 and 2 above.)
  348.  
  349. GETUNK:  Select an unknown cell.  If none exist, report a no 'more unknown
  350. cells' error.  (This means that an object has been found.)  Otherwise,
  351. return the values of T, X, and Y.  I won't describe this routine in detail
  352. because I haven't determined the best way for it to make its choice.  We'd
  353. like to choose cells which are most likely to reveal any previous bad
  354. choices.  Choosing cells which are near recently chosen or forced cells is
  355. a good idea, but there's a danger that we'll get stuck in one region and
  356. not notice that something chosen long ago was bad.  Currently, I use a list
  357. of all cells set up by the BASIC program and just choose the first unknown
  358. one on the list.  But even assuming that we're going to do it that way,
  359. it's not clear how the list should be arranged.  Usually I proceed up the
  360. columns from left to right or down slope -1 diagonals from left to right.
  361.  
  362. CHOOSE(T,X,Y):  Return a value to be assigned to the currently unknown cell
  363. (T,X,Y), either 0 or 1.  Again, I don't know the best way to do this.  For
  364. a complete search, it doesn't matter; both choices will eventually be
  365. tried.  For a partial search, it does.  I usually choose 0 first, hoping
  366. that a small object will be found.  Sometimes I choose 1 to prevent the
  367. empty object from being found.  Sometimes I look for an already chosen
  368. value of CELL[T',X,Y], for T' not equal to T, and give CELL[T,X,Y] the same
  369. value, hoping that a billiard table will be found.  I can specify which of
  370. these methods will be used initially, and can change it in the middle of a
  371. search.
  372.  
  373. MAIN:   This is the top level machine language routine which is called from
  374. the BASIC program.  It searches until it either finds an object of the
  375. desired type, decides that there aren't any more, or is interrupted by the
  376. user.  Specifically, it does this:
  377.  
  378.      Step 0: Call GETUNK.  If it finds an unknown cell (T,X,Y), go to
  379.              step 1.  Otherwise, we've already found an object and want
  380.              to look for another one.  So call BACKUP.  If it gives an
  381.              'object does not exist' error, report it. Otherwise,
  382.              change VALUE to 1-VALUE, set FREE = false, and go to
  383.              step 2.
  384.  
  385.      Step 1: Call CHOOSE to select a VALUE for the unknown cell, set
  386.              FREE = true, and go to step 2.
  387.  
  388.      Step 2: Call GO(T,X,Y,VALUE,FREE).  If it gives an 'object does not
  389.              exist' error, report it.  Otherwise, check to see if the
  390.              user has typed a key.  If so, return.  (The user can then
  391.              display the current contents of CELL to observe the
  392.              progress of the search, and make some changes if desired.
  393.              Calling MAIN again will continue the search.) If no key
  394.              has been typed, go to step 3.
  395.  
  396.      Step 3: Call GETUNK.  If it finds an unknown cell (T,X,Y), go to
  397.              step 1.  Otherwise, report that an object has been found.
  398.  
  399.      In addition to MAIN, the user can also call PROCEED and BACKUP; these
  400. are sometimes useful for guiding a search in a promising direction.
  401. ===========================================================================
  402. END OF FILE
  403.