Tom Ray, ray@udel.edu ray@santafe.edu ray@hip.atr.co.jp
(the bulk of the code)
Joseph F. Hart, jhart@hip.atr.co.jp (general programming, Amiga support)
Matt Jones, mjones@condor.psych.ucsb.edu (Mac support)
Agnes Charrel, agnes@sophis.fr, (tping code for network version)
Tsukasa Kimezawa, kim@hip.atr.co.jp (socket code for network version)
Kurt Thearling, KThearling@exapps.com (CM5 adaptation, parallel creatures)
Dan Pirone, cocteau@echannel.com (frontend, crossover)
Tom Uffner, email@unknown (rework of genebanker & assembler)
If you purchased this program on disk, thank you for your support. If you obtained the source code through the net or friends, we invite you to contribute an amount that represents the program's worth to you. You may make a check in US dollars payable to Virtual Life, and mail the check to one of the two listed below.
This is the license agreement:
The source code, documentation, and executables can be freely distributed
The source code and documentation is copyrighted, all rights reserved. The source code, documentation, and the executable files may be freely copied and distributed without fees (contributions welcome), subject to the following restrictions:
The following provisions also apply:
Please contact Tom Ray (full address below) if you have questions or would like an exception to any of the above restrictions.
If you make changes to the code, or have suggestions for changes, let us know! If we use your suggestion, you will receive full credit of course.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Tom Ray
Zoology Department
University of Oklahoma
Norman, Oklahoma 73019
or
Santa Fe Institute
1399 Hyde Park Road
Santa Fe, NM 87501
ray@santafe.edu (email)
505-984-8800 (Phone)
505-982-0565 (Fax)
or
ATR Human Information Processing Laboratories
2-2 Hikaridai
Seika-cho Soraku-gun
Kyoto 619-02 Japan
ray@hip.atr.co.jp (email)
(81)-7749-5-1063 (Phone)
(81)-7749-5-1008 (Fax)
The C source code creates a virtual computer and its operating system, whose architecture has been designed in such a way that the executable machine codes are evolvable. This means that the machine code can be mutated (by flipping bits at random) or recombined (by swapping segments of code between algorithms), and the resulting code remains functional enough of the time for natural (or presumably artificial) selection to be able to improve the code over time.
Along with the C source code which generates the virtual computer, we provide several programs written in the assembler code of the virtual computer. Some of these were written by humans and do nothing more than make copies of themselves in the RAM of the virtual computer. The others evolved from the ancestral programs, and are included to illustrate the power of natural selection.
The virtual machine is an emulation of a MIMD (multiple instruction stream, multiple data stream) shared memory computer. This is a massively parallel computer in which each processor is capable of executing a sequence of operations distinct from the other processors. The parallelism is only emulated by time slicing, but there really are numerous virtual CPUs. One or more CPU will be created and assigned to each ``creature'' (self-replicating algorithm) living in the RAM of the virtual computer. The RAM of the virtual computer is known as the ``soup''.
The operating system of the virtual computer provides memory management and timesharing services. It also provides control for a variety of factors that affect the course of evolution: three kinds of mutation rates, disturbances, the allocation of CPU time to each creature, the size of the soup, the spatial distribution of creatures, etc. In addition, the operating system provides a very elaborate observational system that keeps a record of births and deaths, sequences the code of every creature, and maintains a genebank of successful genomes. The operating system also provides facilities for automating the ecological analysis, that is, for recording the kinds of interactions taking place between creatures.
The version of the software currently being distributed is considered to be a research grade implementation. This means two things: 1) It is under very rapid development, and may not be completely bug free. 2) We have chosen to go with modifiability and modularity over speed of execution.
If you find bugs in the code, please report them to us. By the time you find them and report them, we may have eliminated them, and would be able to provide you with a fixed version. If not, we will be able to fix the bug, and would like to make the fix available to other users.
We have chosen modifiability over speed primarily because we know that the original version of the virtual computer was very poorly designed, except with respect to the features that make it evolvable. Specifically, consider that one third of the original instruction set is taken up by pushing and popping from the stack; there are only two inter-register moves, ax to bx and cx to dx; dx isn't used for anything (in the initial version, dx was used to set the template size, but that has been abandoned); there are no moves between CPU registers and RAM; there is no I/O; and there is no way of addressing a data segment.
In August 1991, 100% of the original virtual CPU code was replaced, with new code that does exactly the same thing. However, the new code is written in a generalized way, a meta-virtual computer, that makes it trivial to alter the machine architecture. With the new implementation of the virtual computer, it is possible for anyone to painlessly swap in their favorite CPU architecture and instruction set, and their innovation will be seamlessly embedded within the heart of the elaborate observational software. Knowing how bad the original design was, there was a temptation to fix it when the virtual computer was reworked, but the original implementation was retained for historical reasons. In spite of its shortcomings, life proliferated in the environment that it created. Things should get interesting as we improve the architecture. The new organization of the code should make that easy.
In August of 1992, the modifications of the previous August bore fruit as three new instruction sets were implemented. These are documented in some detail below, and in general, eliminate most of the problems discussed above.
In early 1994, attempts to create numerous additional new instruction sets revealed that the method of defining instruction sets was still too stiff, so the code used for decoding the instructions was rewritten yet again, providing a much more flexible method of instruction set definition.
The bulk of the code and documentation was written by Tom Ray, whose address is listed at the end of this file. Substantial contributions have been made by: Dan Pirone, cocteau@santafe.edu, was involved in the Tierra project from the Fall of 1990 through 1992, and wrote the user interface. Tom Uffner, tom@genie.slhs.udel.edu, reworked the genebanker and assembler/disassembler in the Fall of 1991. Marc Cygnus, cygnus@udel.edu, developed the ALmond monitor, a separate piece of software that displays activity in a running Tierra (see below). Kurt Thearling has been involved in the port to the CM5, and the development of multi-cellular implementations. Since July 1996, Joe Hart has be programming full-time on the Tierra project.
The behavior of this software is described in the publications which are available on the Tierra home page at:
http://www.hip.atr.co.jp/~ray/pubs/
The Tierra Simulator has been widely reported in the media. These publications are listed on the Tierra home page at: http://www.hip.atr.co.jp/~ray/pubs/news/
step 1) You should have a directory containing the executables and source code and the subdirectories: td, gb0, gb1, gb2, gb3, and gb8. The td directory is where a record of births and deaths will be written. The gb directories contain the initial genomes used to innoculate the soup and the opcode maps. The genebanker will save new genomes to the gb directories. There is a gb directory for each of the four early instruction sets, and two new ones.
step 2) You must compile the assember/disassembler, arg, and the simulator, tierra. We include the two Turbo C V 2.0 project files: tierra.prj and arg.prj. If you are using a more recent version of the compiler, such as Borland C++, you must use the Borland project tool to create a binary project file. Just list the files listed in the two ascii project files that are provided. Compile these projects using the large memory model, make provisions for floating point operations, and link in the graphics library. Put the executables in the path.
step 3) You must assemble the initial genomes, as binaries are not portable. To do this, go into the gb0 directory and type:
arg c 0080.gen 80 0080aaa.tie
This will create the binary file 0080.gen which contains a creature that you can use to innoculate the soup, the ancestor 0080aaa. You can check to see if this worked by disassembling the genome, by typing:
arg x 0080.gen aaa
This will create the ascii file 0080aaa. Compare it to the original, 0080aaa.tie (it will not be exactly the same). Before you start a run, copy 0080.gen to 0080gen.vir, in order to have a virgin copy for use later when you start another run.
copy 0080.gen 0080gen.vir
You can do the same for each of the gb directories (gb0, gb1, gb2, gb3, and gb8). Be sure to assemble the genomes listed at the ends of the corresponding soup_in files (si0, si1, si2, si3, si8).
step 4) Go back to the source code directory and examine the file si0. This file contains all of the parameters that control the run. It is currently set up to innoculate the soup with one cell of genotype 0080aaa, and to run for 500 generations in a soup of 50,000 instructions. You will need a text editor if you want to modify this file. If you use a regular word processor, be sure that you write the file back out as a plain ASCII text file.
step 5) Run the simulator by typing:
tierra si0
step 6) When the run is over, if you want to start a new run, you should clean up the genebank, because the simulator will read in all genomes in the genebank at startup. The best way to do this is to use the batch files that are provided for this purpose: clr0.bat, clr1.bat, clr2.bat, clr3.bat, and clr8.bat. Since we are discussing a run of instruction set 0, use clr0.bat, by typing clr0 to the DOS prompt. The batch file will take care of the cleanup.
If you wish to use a cumulative genebank in successive runs, use the corresponding cumulative clear batch files: cclr0.bat, cclr1.bat, cclr2.bat, cclr3.bat, and cclr8.bat.
step 2) You must compile the assember/disassembler, arg, and the simulator, tierra. There is a Makefile included to perform the compilation. This Makefile needs to be edited to comment in the lines for your particular hardware. It has been tested on Sun 3, Sun 4, IBM RS6000, Silicon Graphics Personal Iris and Indigo, DEC DS5000, and NeXT. If you can use the Makefile, type: make, and follow instructions. If all goes well, the Makefile will take care of step 3 for you.
step 3) You must assemble the initial genome, as binaries are not portable. To do this, go into the gb0 directory and type:
../arg c 0080.gen 80 0080aaa.tie
This will create the binary file 0080.gen which contains a creature that you can use to innoculate the soup, the ancestor 0080aaa. You can check to see if this worked by disassembling the genome, by typing:
../arg x 0080.gen aaa
This will create the ascii file 0080aaa. Compare it to the original, 0080aaa.tie (they will not be exactly the same). Before you start a run, copy 0080.gen to 0080gen.vir, in order to have virgin copies for use later when you start another run.
cp 0080.gen 0080gen.vir
You can do the same for each of the gb directories (gb0, gb1, gb2, gb3, and gb8). Be sure to assemble the genomes listed at the ends of the corresponding soup_in files (si0, si1, si2, si3, si8).
step 4) Go back to the source code directory and examine the file si0. This file contains all of the parameters that control the run. It is currently set up to innoculate the soup with one cell of genotype 0080aaa, and to run for 500 generations in a soup of 50,000 instructions.
step 5) Run the simulator by typing: tierra si0 or: tierra si0 > /dev/null & (to run it in the background a Log file can be created by setting the soup_in variable Log = 1)
In order to run tierra in the background, you must compile it with:
#define FRONTEND STDIO
If you will run Tierra in the foreground, we recommend that you use:
#define FRONTEND BASIC
These definitions are made in the configur.h file.
step 6) When the run is over, if you want to start a new run, you should clean up the genebank. The best way to do this is to use the Unix script files that have been provided for this purpose (clr0, clr1, clr2, clr3, clr8). You must make the clr# files executable by changing their protection:
chmod +x clr0
Then all you have to do is type ``clr0'' to the prompt, and the shell script will take care of the cleanup.
If you wish to use a cumulative genebank in successive runs, use the cumulative clear files (cclr0, cclr1, cclr2, cclr3, cclr8). You must also make sure that they are executable:
chmod +x cclr0
This documentation was written by Tom Uffner.
Arg(1) USER COMMANDS Arg(1)
NAME
arg - genbank archive utility
SYNOPSIS
arg c|r[v12...9] afile size file1 [file2...]
arg x|t[v12...9] afile [gen1 [gen2...]]
DESCRIPTION
The arg utility is used to manipulate the genebank archives
that are used by tierra(1). It is used to assemble or dis-
sasemble tierra code, list the genomes contained in a file,
and also to convert between the old and new file formats.
The arg commands are:
c - create afile and add genomes in file1...filen
r - replace in afile (or add to end) genomes in
file1...filen
x - extract entire contents or specified genomes from
afile
t - list entire contents or specified genomes in afile
The optional modifiers are:
v - verbose output
1,2...9 - instruction set (defaults to Format: parameter
of ascii source or to INST = 1)
Where filen and afile are any legal filenames, genn is a 3
character genome label, and size is a decimal integer. (Note
that tierra(1) expects archives to have names consisting of
4 digits, and an extension of .gen, or .tmp.
FILES
GenebankPath/nnnn.gen permanantly saved genomes
GenebankPath/nnnn.tmp genomes from periodic saves
SEE ALSO
An Approach to the Synthesis of Life
tierra(1), ov(1X), beagle(1DOS), genio(3), arg(5)
BUGS
Genome extraction and internal search functions could be
faster, and will be in the next release.
Tierra, V 4.0 Last change: 8 September 1992 2
Please remember that this new form of arg needs the file opcode.map to be in the current working directory. Arg ALWAYS reads the file opcode.map for the mappings for assembling/disassembling genebank archives.
What makes the file cryptic, and also compact, is that columns are implied to be identical in successive records unless otherwise indicated. Only the first column, elapsed time since last record, must be printed on every line, and only the first record must have all three or four columns. Therefore, if there is a series of successive births, only the first birth record in the series will contain the b. Notice that at the beginning of the file, there will generally be many lines with just one column, because at the outset, all records are of births of the same size and genotype.
The record of births and deaths is read by the Beagle program, and converted into a variety of graphic displays: frequency distributions over time, phase diagrams of the interactions between pairs of sizes or genotypes, or diversity and related measures over time. The source code for reading and interpreting the record of births and deaths is in the bread.c module of the Beagle source code.
The genebanker keeps track of the frequency of each size class and each genotype in the soup. If a genotype exceeds one of the two genotype frequency thresholds, SavThrMem or SavThrPop, its assigned name will be made permanent, and it will be saved to disk in a .gen file. Genotypes are grouped into individual files on the basis of size. For example, all permanent genotypes of size 80 will be stored together in binary form in a file called 0080.gen.
When the simulator comes down, or when the state of the simulator is saved periodically during a run, all genotypes present in the soup which have not been assigned permanent names will be stored in files with a .tmp extension. For example, all temporary genotype names of size 45 would be stored in binary form in a file called 0045.tmp.
The parameter RamBankSiz places a limit on how many genotypes will be stored in RAM. If there are more than RamBankSiz genotypes in the RAM bank, if any of them have permanent genotype names but have gone extinct in the soup, they will be swapped out to disk into a .gen file. Genotypes without permanent names are deleted when they go extinct. If the number of living genotypes in the soup is greater than RamBankSiz, then the value of RamBankSiz is essentially ignored (actually it is treated as if the value were equal to the number of living genotypes). Living genotypes are never swapped out to disk, only extinct ones. Under DOS, the parameter RamBankSiz is of little importance, because it is raised if there are more living genotypes and if the simulator uses all 640K of RAM, RamBankSiz is lowered so that genotypes will be swapped out to avoid running out of memory. Under Unix, this parameter does determine how many genotypes will be held in the rambank, as long as there are not more than RamBankSiz living genotypes.
The binary genebank files can be examined with the assembler-disassembler arg (see the relevant documentation, section 5.2 above). Also, the Beagle Explorer program contains utilities for examing the structure of genomes. One tool condenses the code by pulling out all instructions using templates, which can reveal the pattern of control flow of the algorithm. Another function allows one genome to be used as a probe of another, to compare the similarities and differences between genomes, or to look for the presence of a certain sequence in a genome. A completely separate tool called probe will scan the genebank pulling out any genomes that meet a variety of criteria that the user may define.
tierra soup_out
That is all there is to it.
The STATS area consists of the top two lines of the screen. This area displays several important variables, whose values are updated after every birth:
InstExec = 75,529993 Cells = 387 Genotypes = 191 Sizes = 23 Extracted = 0080aad @ 8InstExec = 75,529993 tells us that the simulation has executed a total of 75,529,993 instructions. Cells = 387 tells us that there are presently 387 adult cells living in the soup. Genotypes = 191 tells us that there are presently 191 distinct genotypes of adult cells living in the soup. Sizes = 23 tells us that there are presently 23 distinct sizes of adult cells living in the soup. Extracted = 0080aad @ 8 tells us that the last genotype to cross one of the frequency thresholds (SavThrMem or SavThrPop) and get saved to disk and get a permanent name was a creature of size 80 with the name aad, which had a population of 8 adult cells when it crossed the threshold.
The PLAN area displays the values of several variables, whose values are updated every million instructions:
InstExeC = 75 Generations = 188 Thu Apr 30 11:49:46 1992
NumCells = 356 NumGenotypes = 178 NumSizes = 21
AvgSize = 76 NumGenDG = 171
AvgPop = 376 Births = 1007 Deaths = 1034
RateMut = 10966 RateMovMut = 1216 RateFlaw = 97280
MaxGenPop = 21 (0078aak) MaxGenMem = 21 (0078aak)
Speed = 23256
InstExeC = 75 tells us that this set of variables was written when the simulation had executed 75 million instructions. Generations = 188 tells us that the simulation had run for about 188 generations at this time. Thu Apr 30 11:49:46 1992 tells us the actual time and date that this data was printed.
NumCells = 356 tells us that there were 356 adult cells living in the soup. NumGenotypes = 178 tells us that there were 178 distinct genotypes of adult cells living in the soup. NumSizes = 21 tells us that there were 21 distinct sizes of adult cells living in the soup.
AvgSize = 76 tells us that during the last million instructions, the average size was 76. NumGenDG = 171 tells us that there are 171 genotypes that have received permanent names and been saved to disk as .gen files in the genebank directory gb.
AvgPop = 376 tells us that during the last million instructions, the population was 376 adult cells. Births = 1007 tells us that during the last million instructions, there were 1007 births. Deaths = 1034 tells us that during the last million instructions, there were 1034 deaths.
RateMut = 10966 tells us that the actual average background (cosmic ray) mutation rate for the upcoming million instructions will be one mutation per 10966/2 instructions exectued. RateMovMut = 1216 tells us that the actual average move mutation rate (copy error) for the upcoming million instructions will be one mutation for every 1216/2 instructions copied. RateFlaw = 97280 tells us that the actual average flaw rate for the upcoming million instructions will be one flaw for every 97280/2 instructions exectued. The reason that these numbers represent twice the average mutation rates is that they are used to set the range of a uniform random variate determining the interval between mutations.
MaxGenPop = 21 (0078aak) tells us that at this time, the genotype with the largest population is 0078aak, and that it has a population of 21 adult cells. MaxGenMem = 21 (0078aak) tells us that the genotype whose adult cells occupy the largest share of space in the soup is 0078aak, and that it has a population of 21 adult cells.
Speed = 23256 indicates that the virtual cpu is executing 23,256 instructions per second.
The MESSAGE area, for state changes, and Genebank data. This area serves many purposes - memory reallocation messages, Genebank information displays, large interface prompts (eg changing a soup_in variable ).
The ERROR area at the second to the last line of the screen. All simulation errors and exit conditions are passed through this area.
The HELP area at the last line of the screen. This area provides suggestions for keystroke navigation. Under DOS it will usually look like this:
Press any Key for menu ...
Under Unix it will generally look like this:
Press Interupt Key for menu ...
Under DOS, pressing any key will get you the menu, under Unix, pressing the interrupt key (usually Ctrl C) will get you the menu, described in the next section.
The frontend menu looks like this:
i-info v-var s-save S-shell q-save&quit Q-quit m-misc c-continue |->
These options allow for rapid IO from the simulation, in a user friendly format. The interface allows transition between any data display mode. The features are ativated by a single keypress ("Enter/Return" is usually not needed).
The options are:
i-info v-var s-save S-shell q-save&quit Q-quit m-misc c-continue |->
i-info: will display some information about creatures stored in the Genebank. See below for details.
v-var: allows you to examine or alter the value of any of the variables in the soup_in file at any point during a run.
s-save: will cause the state of the system to be saved at this point, and then continue the run.
S-shell: this causes you to exit to the DOS prompt, while the simulator remains in the RAM in suspended animation. You can now do anything that doesn't require a lot of memory. Be careful that if you change directories, you come back to the current directories before you exit from the shell. Also, be careful not to do anything that changes the graphics mode.
q-save&quit: will cause the state of the system to be saved at this point, and then exit from the run.
Q-quit: will exit immediately without saving the state of the system.
m-misc: pulls up the miscellaneous sub-menu
c-continue: continue the run.
If you press 'i' for info, from the main TIERRA menu, you are able to select one of the Genebank (GeneBnker = 1) data display modes:
INFO | p-plan s-size_histo g-gen_histo m-mem_histo z-size_query |->
The second line from the top of the screen will change, providing additional information on the operating system memory use, or the Tierrian memory use. At the bottom of the screen, a new list of GeneBank data display options are available. All of these modes will try to provide as much data as can fit on the screen. These modes are detailed below:
Hit the c key to continue (to get out of this level of the menu)
The options are:
p-plan s-size_histo g-gen_histo m-mem_histo z-size_query
If you press 'p' from the info menu you get the Plan Display mode:
Now in Plan Display mode, updated every million time steps
This provides the normal statistics every million virual time steps (this is also an easy way to clear the message area):
InstExeC = 75 Generations = 188 Thu Apr 30 11:49:46 1992
NumCells = 356 NumGenotypes = 178 NumSizes = 21
AvgSize = 76 NumGenDG = 171
AvgPop = 376 Births = 1007 Deaths = 1034
RateMut = 10966 RateMovMut = 1216 RateFlaw = 97280
MaxGenPop = 21 (0078aak) MaxGenMem = 21 (0078aak)
Speed = 23256
The meaning of this information is detailed above.
13 1 2 | * 18 3 9 | ** 19 3 4 | * 20 2 4 | * 21 1 3 | * 22 1 4 | * 27 3 5 | * 34 2 4 | * 35 1 4 | * 36 34 84 | **************** 37 70 198 | ************************************* 38 33 92 | ****************** 39 7 9 | ** 40 13 25 | ***** 44 1 2 | * 45 1 2 | * 46 2 2 | * 47 1 4 | * 49 1 2 | * 54 1 1 | * 56 2 3 | * 70 10 13 | *** 71 21 42 | ******** 72 24 42 | ******** 73 6 6 | ** 74 7 12 | *** 75 3 3 | * 77 2 2 | * 78 6 7 | ** 109 1 2 | *
In the above histogram, the left column of numbers is the size class, the middle column is the number of genotypes of that size class, and the right column is the number of living adult cells of that size class.
Size Memory use (size * freq.) 18 3 180 | * 19 3 76 | * 20 2 60 | * 21 1 63 | * 22 1 110 | * 27 3 162 | * 31 1 31 | * 33 1 33 | * 34 2 136 | * 35 1 105 | * 36 37 3096 | ***************** 37 69 7141 | ************************************* 38 34 3610 | ******************* 39 7 351 | ** 40 13 960 | ***** 41 1 41 | * 42 1 42 | * 43 1 43 | * 44 1 44 | * 45 1 90 | * 46 2 92 | * 47 1 235 | ** 48 1 48 | * 49 1 98 | * 50 1 50 | * 54 1 54 | * 56 2 168 | * 66 1 66 | * 71 22 42 | * 72 25 42 | *
In the above histogram, the left column of numbers is the size class, the middle column is the number of genotypes of that size class, and the right column is the amount of memory occupied by living adult cells of that size class.
Size Frequency
18aab 3 | ***
aac 6 | ******
27aab 2 | **
aad 3 | ***
35aaa 3 | ***
36aam 7 | *******
aat 39 | **************************************
abb 3 | ***
37abb 26 | *************************
abp 5 | *****
abt 6 | ******
acm 23 | **********************
acn 4 | ****
38abb 5 | *****
abc 3 | ***
40aaj 3 | ***
aal 2 | **
47aaa 5 | *****
49aaa 2 | **
56aac 2 | **
70aae 2 | **
aaf 2 | **
71aac 3 | ***
aaj 4 | ****
aat 3 | ***
aav 6 | ******
72aai 2 | **
aau 3 | ***
aax 4 | ****
74aac 4 | ****
In the above histogram, the left column of numbers is the size and genotype class, and the right column is the number of living adult cells of that genotype class.
Gene: # Mem Errs Move Bits aae 4 0 1 39 EX TC TP MF MT MB aaj 1 0 0 0 EX TC TP MF MT MB aak 1 0 0 0 EX TC TP MF MT MB aan 1 0 0 0 EX TC TP MF MT MB aap 1 0 0 0 EX TC TP MF MT MB aaq 1 0 0 0 EX TC TP MF MT MB aat 10 0 2 38 EXsofh TCsofh TPs MF MT MBsof aau 1 0 0 0 EX TC TP MF MT MB aaw 1 0 0 0 EX TC TP MF MT MB aax 2 0 0 0 EX TC TP MF MT MB aay 1 0 0 0 EX TC TP MF MT MB aba 1 0 0 0 EX TC TP MF MT MB abb 1 0 0 0 EX TC TP MF MT MB abc 1 0 0 0 EX TC TP MF MT MB abe 1 0 7 146 EX TC TP MF MT MB abi 61 3 2 38 EXsdofh TCsofh TPs MFsof MTsf MBsdofh abk 1 0 2 38 EX TC TP MF MT MB abl 1 0 0 0 EX TC TP MF MT MB abm 1 0 0 0 EX TC TP MF MT MB abw 17 1 2 38 EXsdofh TCsofh TPs MF MT MBsdofh aby 6 0 1 38 EXsdofh TCsof TPs MF MT MBsdofh acb 2 0 0 0 EX TC TP MF MT MB acd 1 0 0 0 EX TC TP MF MT MB ace 1 0 0 0 EX TC TP MF MT MB acf 1 0 0 0 EX TC TP MF MT MB acg 4 0 2 38 EX TC TP MF MT MB ach 13 0 2 38 EXsdofh TCsdofh TPs MFsdofh MTsdf MBsdofh aci 2 0 2 38 EX TC TP MF MT MB acj 2 0 0 0 EX TC TP MF MT MB
# = acutal count, populations of adult cells of this genotype Mem = is the percent of Soup, occupied by adult cells of this genotype Err = is the number of error flag commited, Move = number of instructions moved to daughter cell, Bits = Watch bits, defined in section: 7) Soup_in Parameters
0 values usually represent cases of insufficient data.
If you press 'v' for variable, from the main TIERRA menu, you will get the variable sub-menu, which looks like the following in unix:
VAR | a - alter variable e - examine variable
From this menu, you have the following options:
a - alter variable: if you press the 'a' key, you can name any variable in the soup_in file, and specify a new value for that variable. Be careful, there are some variables that should not be changed, such as SoupSize.
e - examine variable: if you press the 'e' key, you can examine the value of any variable in the soup_in file.
If you press 'm' for misc, from the main TIERRA menu, you will get the miscellaneous sub-menu, which looks like the following in unix:
MISC | H-Histo Logging I-Inject Gene M-Micro Toggle P-ALmonD Pause |->
and the following in DOS:
MISC | H-Histo Logging I-Inject Gene M-Micro Toggle |->
When this sub-menu is selected, some information is displayed at the top of the screen about what variables are #defined:
VER=4.10 PLOIDY=1 MICRO ALCOMM
This information relates to the way that Tierra was compiled. In this case this tells us that this is Version 4.10 of the Tierra program, that it is a haploid model (Ploidy = 1), and that the MICRO virtual debugger is enabled, and that the ALmond communications system is also enabled.
From this menu, you have the following options:
H-Histo Logging: if you press the H key, it will toggle the logging of any histograms you create to the tierra.log file.
I-Inject Gene: inject a genome of your choice from the genebank into the soup of the running simulator.
M-Micro Toggle: turn on the virtual debugger. The debugger has three states: delay, keypress, and off. In delay mode, the debugger will execute one Tierran instruction per second. In the keypress mode, the debugger will execute one Tierran instruction per keypress.
c-continue: exit from this sub-menu.
In keypress mode, there are some additional modes. Given that there is usually a population of cells in the soup, the virtual debugger will swap from cell to cell as each one gets its time slice. However, this can be disconcerting if one is trying to study the behavior of a particular cell. The debugger can be made to follow a single creature using the Track cell option as specified at the bottom of the screen in keypress mode:
MICRO | T-Track cell U-Track Cpu ESC-Main Menu n-Next step
If you hit the T key, you will go into Track cell mode, and the menu will change to:
MICRO | t-Untrack cell U-Track Cpu ESC-Main Menu n-Next step
Now hitting the t key will return to the mode that swaps between cells.
Version 4.1 and later of Tierra allows for the possibility that a single cell can have more than one processor. This introduces a similar problem in that the debugger will follow the time slicing pattern of the simulator, which involves a single instruction per processor within a cell. Again, this can make it difficult to follow the activity of a single processor. The debugger can be made to follow a single processor within a cell using the Track Cpu option as specified at the bottom of the screen in keypress mode (see above). If you hit the U key, you will go into Track Cpu mode, and the menu will change to:
MICRO | t-Untrack cell u-Untrack Cpu ESC-Main Menu n-Next step
Please note that going into Track Cpu mode, automatically puts you into Track cell mode. You may exit the Track Cpu mode by hitting the u key, and the menu will change to:
MICRO | t-Untrack cell U-Track Cpu ESC-Main Menu n-Next step
Note that exiting Track Cpu mode does not cause you to exit Track cell mode. If you wish to exit the Track cell mode, you must hit the t key.
If you wish to start debugging from the very beginning of a run, you will want to start the simulator fresh with the menu activated, so that you can start the debugger before the seed creature(s) has started to run. This is done by giving two arguments when starting Tierra, one must be the name of the soup_in file, the second is a dummy argument. So for example, you should type:
tierra si0 junk
The debugger display in keypress mode looks like:
InstExec = 11,346072 Cells = 679 Genotypes = 274 Sizes = 26
VER=4.0 INST=1 PLOIDY=1 MICRO
MICRO STEP Mode = keypress
Cell 1: 55 0045aaa @ 12595 Slice= 19 Stack[ 12628]
IP [ 12572]( -23 ) = 0x01 nop1 [ 12639]
AX [ 30236] [ 12595]
BX [ 12632] [ 45] <
CX [ 7] [ 0]
DX [ 4] [ 0]
Flag = 0 [ 0]
Daughter @ 30199 + 45 [ 0]
[ 0]
[ 0]
0 of 1 Cpus
MICRO | T-Track cell U-Track Cpu ESC-Main Menu n-Next step
The various components of the display are documented in the following:
Cell 1: 55 0045aaa @ 12595 Slice= 19
Each creature has associated with it, a cell structure. The cell structures are organized in a two dimensional array. Cell 1: 55 tells us that the structure for the currently active creature is at location 1,55 in the cells array.
The currently active creature is 0045aaa whose cell starts at address 12595 in the soup. This creature currently has 19 CPU cycles left in its time slice. Note that when the Slice counts down to zero, the slicer will swap in the next creature in the slicer queue, and the debugger will display the CPU of the next creature. Therefore when there are more than one creature in the soup, it is hard to follow the activity of a single creature, since the debugger will be swapped from creature to creature. This problem can be eliminated by activating the Track cell mode (see above).
Daughter @ 30199 + 45
The currently active creature has allocated a space of 45 instructions at address 30199 in the soup, which it presumably will use to make a daughter.
IP [ 12572]( -23 ) = 0x01 nop1
The instruction pointer (IP) of the currently active creature is presently located at the soup address 12572. Notice that this address is located 23 instruction BEFORE the start of its own cell. The number in parentheses (-23) is the offset of the IP from the start of the cell. As long as the IP is inside the cell, this offset will be displayed without a sign. If the IP is outside of the cell, the offset will be displayed with a + or a - sign. The current offset of -23 means that the instruction pointer of this creature is executing the code of some other creature. In fact 0045aaa is a parasite. The instruction currently being executed is represented in the soup by the hex value 0x01. The assembler mnemonic of this instruction is nop1, it is a no-operation.
AX [ 30236] BX [ 12632] CX [ 7] DX [ 4]
The four CPU registers of the currently active creature contain the values indicated above. Probably, the AX value is the address where the creature is writing in its daughter cell, the BX value is the address that it is copying from in its own cell, the CX value is the number of instructions of the genome remaining to be copied, and the DX value is the size of the last template used.
Flag = 0
This shows the status of the flag register. This can be used to recognize when an instruction has failed, generating an error condition.
Stack[ 12628]
[ 12639]
[ 12595]
[ 45] <
[ 0]
[ 0]
[ 0]
[ 0]
[ 0]
[ 0]
The stack of the currently active creature contains the values indicated above. The stack pointer points at the location indicated by the < sign (the top of the stack). The values on the stack probably include the address of the instruction pointer (12628) which was pushed on the stack when the parasite called the copy procedure of its host, the address of the end of the creature (12639), the address of the beginning of the creature (12595), and the size of the creature (45).
0 of 1 Cpus
Given that version 4.1 allows each cell to have more than one CPU, this message tells us which CPU we are currently observing. The CPUs are numbered starting from 0. In this case, the cell has only one CPU.
If an attempt at injection fails, you will see an error message like:
Tierra InjectFromBank() unable to open genome file gb0/0033.gen
Tierra ERROR Press any key to continue
at the bottom of the screen. If the injection is successful, you will see a message like:
Injection of 0080aaa done
at the top of the screen.
There is a function Inject(), in the genebank.c module, which takes a pointer to a genome as an argument. This function can be used to inject genomes from any source. An interesting use of this function would be to facilitate migration of genomes between simulations running on separate machines, creating an archipelago (this is the basis of the new CM5 port, and the new network version of Tierra).
TIERRA: LOG = on, Histogram Logging = off
seed = 1573093196
sizeof(Instruction) = 1
sizeof(TCell) = 172
sizeof(MemFr) = 16
60000 bytes allocated for soup
16512 bytes allocated for cells
12800 bytes allocated for MemFr
tsetup: arrays allocated without error
skipping 30000 instructions
GetNewSoup: loading 0080aaa into cell 0,2
InstExeC = 0 Generations = 0 Wed May 17 16:54:27 1995
NumCells = 1 NumGenotypes = 1 NumSizes = 1
AvgSize = 80 NumGenDG = 1
RateMut = 6382 RateMovMut = 1280 RateFlaw = 51200
tsetup: soup gotten
Press Interrupt Key for Menu ...
extract: 0080aaa @ 268 v
extract: 0080aac @ 11
InstExeC = 1 Generations = 3 Wed May 17 16:55:05 1995
NumCells = 377 NumGenotypes = 140 NumSizes = 9
AvgSize = 79 NumGenDG = 2
AvgPop = 289 Births = 988 Deaths = 612
Speed = 26316
MaxGenPop = 202 (0080aaa) MaxGenMem = 202 (0080aaa)
RateMut = 15211 RateMovMut = 1264 RateFlaw = 80000
InstExeC = 2 Generations = 5 Wed May 17 16:55:42 1995
NumCells = 376 NumGenotypes = 123 NumSizes = 11
AvgSize = 80 NumGenDG = 2
AvgPop = 374 Births = 880 Deaths = 881
Speed = 27027
MaxGenPop = 198 (0080aaa) MaxGenMem = 198 (0080aaa)
RateMut = 18105 RateMovMut = 1280 RateFlaw = 72640
InstExeC = 3 Generations = 8 Wed May 17 16:56:20 1995
NumCells = 376 NumGenotypes = 132 NumSizes = 20
AvgSize = 79 NumGenDG = 2
AvgPop = 369 Births = 1006 Deaths = 1006
Speed = 26316
MaxGenPop = 164 (0080aaa) MaxGenMem = 164 (0080aaa)
RateMut = 15447 RateMovMut = 1264 RateFlaw = 63616
extract: 0080acx @ 10
InstExeC = 4 Generations = 10 Wed May 17 16:56:58 1995
NumCells = 363 NumGenotypes = 137 NumSizes = 14
AvgSize = 80 NumGenDG = 3
AvgPop = 369 Births = 852 Deaths = 865
Speed = 26316
MaxGenPop = 134 (0080aaa) MaxGenMem = 134 (0080aaa)
RateMut = 18305 RateMovMut = 1280 RateFlaw = 74496
The meaning of each different kind of information is described below:
TIERRA: LOG = on, Histogram Logging = off
If the soup_in variable ``Log'' is non-zero, most of the information shown in the standard output listing above will be written to the file ``tierra.log'' on disk. Histogram Logging = off indicates that histograms viewed through the menu system will not be saved to the log. This option can be toggled so that static histograms are saved to the log.
sizeof(Instruction) = 1 sizeof(TCell) = 172 sizeof(MemFr) = 16
The size in bytes of each of the main structures, of which the system will allocate large arrays at startup.
60000 bytes allocated for soup 16512 bytes allocated for cells 12800 bytes allocated for MemFr
The total number of bytes used for each of the three main arrays of structures.
tsetup: arrays allocated without error
Statement indicating that the arrays were allocated without error.
skipping 30000 instructions
The soup_in file specified to place the seed creature in the middle of the 60,000 bytes of memory in the soup.
seed = 1573093196
A record of the seed of the random number generator used in this run. This can be used to repeat the run if desired.
GetNewSoup: loading 0080aaa into cell 0,2
A statement indicating that the system is innoculating the soup with a creature of size 80. There will be a comparable line for every creature used in innoculating the soup at startup. The first creature goes into cell 2 of array 0, because cells 0 and 1 are used for other purposes.
InstExeC = 0 Generations = 0 Wed May 17 16:54:27 1995
NumCells = 1 NumGenotypes = 1 NumSizes = 1
AvgSize = 80 NumGenDG = 1
RateMut = 6382 RateMovMut = 1280 RateFlaw = 51200
tsetup: soup gotten
These lines indicate the starting conditions of several variables which will be explained below.
extract: 0080aaa @ 268 v
This line indicates that the genotype 0080aaa crossed one of the frequency thresholds set in the soup_in file, SavThrMem or SavThrPop, and that there were 268 adult creatures of this genotype in the soup when this was noted. However, no creatures are extracted until the reaper is activated when the soup becomes full. This means that 0080aaa was not actually extracted at the time that it crossed a threshold, but actually much later, when it had a relatively large population. The v after 268 indicates that this was a ``virtual extraction'', which means that the genome was not actually saved to disk, since it already has been saved to disk. Anytime a permanent genotype goes extinct, then reappears and crosses a threshold, it will experience a virtual extraction, which just means that the crossing of the threshold will be reported as an extract in standard out and in the tierra.log file (this information can be put to good use by the tieout tool: tieout tierra.log ie ex)
extract: 0080aac @ 11
This is a real extraction, as indicated by the absence of a v after the 11. This genotype, 0080aac, crossed the threshold frequency with a population of 11 adult creatures, its name was made permanent, and its genome was saved to disk.
InstExeC = 1 Generations = 3 Wed May 17 16:55:05 1995
NumCells = 377 NumGenotypes = 140 NumSizes = 9
AvgSize = 79 NumGenDG = 2
AvgPop = 289 Births = 988 Deaths = 612
Speed = 26316
MaxGenPop = 202 (0080aaa) MaxGenMem = 202 (0080aaa)
RateMut = 15211 RateMovMut = 1264 RateFlaw = 80000
A statement of this form is printed after every million instructions executed by the system. See the plan() function in the bookeep.c module for more details on this.
InstExeC = 1 Generations = 3 Wed May 17 16:55:05 1995
InstExeC = 1 tells us that one million instructions have been executed in this run. Generations = 3 tells us that roughly three generations of creatures have passed so far during this run. Wed May 17 16:55:05 1995 tells us the time and date of this record.
NumCells = 377 NumGenotypes = 140 NumSizes = 9
NumCells = 377 tells us that there were 377 adult cells (and a roughly equal number of daughter cells) at this point in the run. NumGenotypes = 140 tells us that there were 140 distinct adult genotypes (code sequences) living in the soup at the time of this record. NumSizes = 9 tells us that there were nine distinct adult genome sizes (creature code lengths) living in the soup at this time.
AvgSize = 79 NumGenDG = 2
AvgSize = 79 tells us that the average size of all the adult creatures living in the soup at this time was 79 instructions. NumGenDG = 2 tells us that there are two genotypes that has received permanent names and been saved to disk as .gen files in the genebank directory gb.
AvgPop = 289 Births = 988 Deaths = 612
AvgPop = 289 tells us that during the last million instructions the average population was 289 adult cells. Births = 988 tells us that during the last million instructions, there were 988 births. Deaths = 612 tells us that during the last million instructions, there were 612 deaths.
MaxGenPop = 202 (0080aaa) MaxGenMem = 202 (0080aaa)
MaxGenPop = 202 (0080aaa) tells us that at this time, the genotype with the largest population is 80aaa, and that it has a population of 202 adult cells. MaxGenMem = 202 (0080aaa) tells us that the genotype whose adult cells occupy the largest share of space in the soup is 80aaa, and that it has a population of 202 adult cells.
RateMut = 15211 RateMovMut = 1264 RateFlaw = 80000
RateMut = 15211 tells us that the actual average background (cosmic ray) mutation rate for the upcoming million instructions will be one mutation per 15211/2 instructions exectued. RateMovMut = 1264 tells us that the actual average move mutation rate (copy error) for the upcoming million instructions will be one mutation for every 1264/2 instructions copied. RateFlaw = 80000 tells us that the actual average flaw rate for the upcoming million instructions will be one flaw for every 80000/2 instructions exectued. The reason that these numbers represent twice the average mutation rates is that they are used to set the range of a uniform random variate determining the interval between mutations.
When Tierra is running in the foreground it is possible to interrupt it on either DOS or UNIX, usually by typing Ctrl C (^C). When you do this you will get a brief message listing your options, which looks something like this:
^C
==========================================================
TIERRA: Main Menu
VER=4.20 PLOIDY=1 MICRO
---------------------------------------------------------
InstExe.m = 4 InstExec.i = 397467 NumCells = 370
NumGenotypes = 138 NumSizes = 20
---------------------------------------------------------
Key Function
i Information on simulation
v Change or examine a soup_in variable
m Misc. commands
S Execute a system Shell
s Save the soup
q Save the soup & quit
Q Quit/Abort simulation
c To Continue simulation
---------------------------------------------------------
i-info v-var s-save S-shell q-save&quit Q-quit m-misc c-continue |->
Unix only: If ALCOMM has been defined at compile time, VPORT is the value of the socket for ALmond data communication.
You must now choose one of the options by typing one of the corresponding letters: ivSsqQc. When you type the letter, the simulator will either prompt you for more input or do the requested operation.
The options are:
i-info v-var s-save S-shell q-save&quit Q-quit c-continue |->
i-info: will display some information about creatures stored in the Genebank. See below for details.
v-var: allows you to alter or examine the value of any of the variables in the soup_in file at any point during a run. These options are discussed above in the description of the BASIC frontend.
s-save soup: will cause the state of the system to be saved at this point, and then continue the run.
S-Shell: this causes you to exit to the DOS prompt, while the simulator remains in the RAM in suspended animation. You can now do anything that doesn't require a lot of memory. Be careful that if you change directories, you come back to the current directories before you exit from the shell. Also, be careful not to do anything that changes the graphics mode.
q-save&quit: will cause the state of the system to be saved at this point, and then exit from the run.
Q-quit: will exit immediately without saving the state of the system.
c-continue: continue the run.
i-info: Choosing this option produces a sub-menu:
---------------------------------------------------------
s Spectrum of all Size Classes
m Spectrum of Size Classes, by memory use
g Spectrum of Size Classes, by geneotype
z Break down of a specific Size Class
Any other key to main menu ...
---------------------------------------------------------
These options are documented under the BASIC frontend above.
Log = 1 0 = no log file, 1 = write log file
is set to a non-zero value, a file named tierra.log will be written to the current directory. This file contains in abbreviated form, much the same information that is contained in the Standard Output frontend. An example of the output to this file follows:
ie0 gn0 Wed May 17 17:27:06 1995 nc1 ng1 ns1 as80 dg1 rm6382 mm1280 rf51200 ie1 gn3 Wed May 17 17:27:44 1995 nc387 ng141 ns11 as79 dg1 bi1044 de658 ap289 mp211 @ 0080aaa mg211 @ 0080aaa sp38 rm14287 mm1264 rf75200 ie2 gn5 Wed May 17 17:28:20 1995 nc368 ng128 ns14 as79 dg1 bi847 de866 ap371 mp199 @ 0080aaa mg199 @ 0080aaa sp36 rm18232 mm1264 rf74688 ex = 0080aab @ 10 ex = 0080aao @ 10 ie3 gn8 Wed May 17 17:28:57 1995 nc376 ng119 ns11 as78 dg3 bi861 de853 ap376 mp179 @ 0080aaa mg179 @ 0080aaa sp37 rm18226 mm1248 rf74624 ex = 0080abr @ 10 ie4 gn10 Wed May 17 17:29:34 1995 nc380 ng117 ns12 as78 dg4 bi892 de888 ap372 mp164 @ 0080aaa mg164 @ 0080aaa sp37 rm17387 mm1248 rf71872 ex = 0045aaa @ 14
Because this file is of essentially the same form as the standard output, only the abbreviations will be documented here. Refer to the documentation of the Standard Output to interpret the meaning of this file.
ie = InstExeC; gn = Generations; nc = NumCells; ng = NumGenotypes; ns = NumSizes; as = AvgSize; dg = NumGenDG; bi = Births; de = Deaths; ap = AvgPop; mp = MaxGenPop; mg = MaxGenMem; sp = Speed rm = RateMut; mm = RateMovMut; rf = RateFlaw; ex = extract
The distribution includes the following files:
announce.XX - previous announcements about Tierra releases and other Tierra news.
arg.c - the main module for the assembler/disassembler, originally written by Tom Uffner. This program converts ascii assembler files into binary files which can be executed by the Tierran virtual computer.
arg.prj - the Turbo C V 2.0 project file for compiling the assember/disassembler. If you are using a more recent Borland compiler, you must use the Borland tool to build the binary project file. Include the modules listed in this ascii version of the file.
arg_inc.c - a file used to include some of the files used in compiling the assembler (arg). They are included in this way because arg_inc.c defines ARG, which alters the included modules to be compatible with arg rather than tierra.
alcomm.doc - some comments on the socket communications mechanisms used by the almond monitor.
arginst.h - a file containing some variable used by the assembler.
beagle.doc - documentation for the Beagle Explorer program, a DOS based tool for examining the results of running Tierra, after the fact.
bookeep.c - source code for bookeeping routines, which keep track of how many of what kind of creatures are in the soup, and other stuff like that.
cclr0, cclr1, cclr2, cclr3, cclr0.bat, cclr1.bat, cclr2.bat, cclr3.bat - Unix shell scripts, and DOS batch files for cleaning up an old run in preparation for a new run with a cumulative genebank (or you can just use it to remove files generated by a run, to get you disk space back). You must change the protection on the unix files to make them executable: chmod +x cclr0 There is a different file for each instruction set.
clr0, clr1, clr2, clr3, clr0.bat, clr1.bat, clr2.bat, clr3.bat - Unix shell scripts and DOS batch files for cleaning up an old run in preparation for a new run (or you can just use it to remove files generated by a run, to get you disk space back). You must change the protection on the unix files to make them executable: chmod +x clr0 There is a different file for each instruction set.
configur.h - a file for configuring Tierra. You probably won't need to touch this unless you get into advanced stuff.
create.tex, create.ps - This is the text of a manuscript which has been published in French translation in the September 1992 issue of a popular Swiss magazine named LeTemps.
declare.h - all global variables are declared in this file, except those whose values are set by soup_in. Those globals are declared in soup_in.h. declare.h is included by tierra.c which contains the main function.
decode.c - the decode functions interpret the executable code of the creatures, and map it onto the executable functions contained in the instruct.c module.
diskbank.c - some functions that deal with writing to disk.
extern.h - all global variables are delcared as extern in this file, and this file is included by all *.c files except tierra.c which includes delcare.h instead.
frontend.c - functions for handling input/output for Tierra. This stuff was written by Dan Pirone. This module contains basic data reporting functions, and includes one of the following: tstdio.c - low level IO for standard IO, simple, and good for debugging. tcurses.c - advanced IO for unix, based on "standard" curses calls, Please see the manual pages on curses for the nitty gritty details. tturbo.c - advanced IO for the Turbo C / DOS environment. On machines with EGA or VGA harware, 43/50 lines modes are used.
genio.c - functions for input/output of creatures. This stuff is also used by arg.c, the assembler/disassembler. This module has benefited from a lot of work by Tom Uffner.
instruct.c - this module contains generalized executable functions. These generalized functions are mapped to specific functions by the parsing functions in the parse.c module.
license.h - a file stating the terms of the license agreement, which is include in all the source code modules.
Makefile, MakeAlmond, MakeCM5 - the make files, for compiling tierra and arg under Unix. MakeAlmond compiles Tierra for use with ALmond, and MakeCM5 compiles to run Tierra on the CM5.
memalloc.c - functions for handling memory allocation in the soup, the stuff that ``cell membranes'' are made of.
memtree.c - additional memory allocation routines, written by Chris Stephenson of the IBM T. J. Watson Research Center.
mlayer.doc - some comments on the ALmond tool.
multi_cell.ps, multi_cell.ps.gz - a manuscript describing some initial experiments with evolving multi-cellular digital organisms.
OV_README.txt - some documentation on the overview (ALmond) tool.
PhysicaD.ps, PhysicaD.tex - a manuscript describing the results of three studies with Tierra: a comparison of the patterns of evolution in four instruction sets, the relationship between evolution and entropy, and the evolution of complexity.
portable.c - functions for portability between operating systems.
portable.h - definitions for portability between operating systems and architectures.
prototyp.h - all functions in Tierra are prototyped here.
queues.c - queue management functions for the slicer and reaper queues.
quickstart - the quickstart section of this document, yanked out and made as a separate file, for those who don't read the doc files.
rambank.c - functions for managing the genebank. This module has benefited from a lot of work by Tom Uffner.
reserves.tex - a document describing a proposal to create a network-wide biodiversity reserve for digital organisms.
slicers.c - interchangeable slicer functions. This file contains some experiments in the allocation of CPU time to creatures. This is an interesting thing to play with.
si0, si1, si2, si3 - the ascii files read by Tierra on startup, which contains all the global parameters that determine the environment. There is a different file for each instruction set.
soup_in.h - this file defines the default values of all the soup_in variables, and defines the instruction set by mapping the assember mnemonics to the opcodes, decode functions, and executables.
tcurses.c - see under frontend.c above.
tcolors.cfg - an ascii file that maps the colors of the Tierra display in DOS. This makes it easy to remap the colors. This is useful for odd displays such as LCD where the colors do not map nicely.
thoughts.ps, thoughts.tex - This is the text of a thought experiment. It was written before the Tierra program started running. After Tierra ran, this manuscript was slightly edited, but it has not been altered since February 2, 1990. This manuscript shows the thought processes that led to the development of the Tierra program.
tieout.c - a separate tool for observing the contents of the tierra.log file documented in tieout.doc.
tieout.doc - documentation of the tieout tool.
tieout.exe - the DOS distribution also includes the executable version of the tieout tool, so that it does not have to be compiled. See tieout.doc.
tierra.c - this file contains the main function, and the central code driving the virtual computer.
tierra.doc - this file, on line documentation.
tierra.exe - the DOS distribution includes the executable version of the Tierra program, so that it does not have to be compiled.
tierra.h - this file contains all the structure definitions. It is a good source of documentation for anyone trying to understand the code.
tierra.prj - the Turbo C V 2.0 project file for compiling Tierra. If you are using a more recent Borland compiler, you must use the Borland tool to build the binary project file. Include the modules listed in this ascii version of the file.
tierra.tex - This is the text of a manuscript detailing the Tierra program and the early results from its use. This manuscript is published as a working paper of the Santa Fe Institute.
tmonitor.c - this file contains support calls for the ALmond tool.
trand.c - random number generation routines from Numerical Recipes in C.
tsetup.c - routines called when Tierra starts up and comes down. Tom Uffner has put some work into this module as well.
ttools.c - routins used in generating the histograms displayed by the frontend.
Zen.ps, Zen.tex - a manuscript describing a way of thinking about using natural evolution to create artificial life.
gb0: - a subdirectory containing the genomes of the creatures saved during a run of instruction set 0.
gb0/0080aaa.tie - the ancestor, written by a human, mother of all other creatures.
gb0/0073aaa.tie - a new ancestor, written by a human, like 0080aaa, but with some junk code removed.
gb0/0022aaa.tie - the smallest non-parasitic self-replicating creature to evolve.
gb0/0045aaa.tie - the archtypical parasite.
gb0/0046aaa.tie - a symbiont with 0064aaa. These two were created by hand, by splitting 0080aaa into two parts.
gb0/0064aaa.tie - a symbiont with 0046aaa. These two were created by hand, by splitting 0080aaa into two parts.
gb0/0072aaa.tie - a phenomenal example of optimization through evolution, involving the unrolling of the copy loop.
At the time of this writing, only a single run, of a billion instructions, has been analyzed at the level of detail to reveal the specifics of the ecological arms race that took place. That information is presented in the manuscripts cited above. This run can be seen on the video, available from Media Magic, P.O. Box 507, Nicasio, CA 94946. Some of the major players in that run are listed below, and included in the software distribution, in the chronological order of their appearance:
gb0/0079aab.tie - this creature dominated the soup at the time that a major optimization took place, resulting in 0069aaa and its relatives.
gb0/0069aaa.tie - this fully self-replicating (non-parasitic) creature appeared at a time that the dominant self-replicating size class was 79. Thus this creature was a hopeful monster. It managed to shave 10 instructions off of the genome in a single genetic change. Actually this creature claims that its immediate ancestor (parental genotype) was 0085aal. If this is true, then it actually shaved 16 instructions off its size in a single genetic event. Unfortunately, 0085aal was not preserved in the fossil record.
gb0/0069aab.tie - this host creature co-dominates the soup for a time, with the parasite 0031aaa.
gb0/0031aaa.tie - this parasite co-dominates the soup for a time, with the host 0069aab.
gb0/0070aaw.tie - while 0069aab and 0031aaa co-dominate the soup, this creature, which is the first hyper-parasite, surges up. It and its relatives drive the parasites to extinction.
gb0/0061aag.tie - this hyper-parasites dominates at the time that the first social creatures appear.
gb0/0061aai.tie - this is the first social hyper-parasite to surge up. It is social by virtue of using a template in its tail to jump back to its head. This only works when it occurs in close aggregations of same kind creatures.
gb0/0061aab.tie - this is the second social hyper-parasite to surge up. It operates on the basis of a completely different social mechanism from 0061aai. In this creature the basis of cooperation is that the template used to search for its tail, does not match to the tail template. However, it two of these creatures abut in memory, the union of the tail template of one with the head template of the next, forms the template that is used to identify the tail. This algorithm also only works when the creatures occur in aggregations. However, this mechanism is more fragile than that used by 0061aai. For 0061aab, the two cooperating creatures must exactly abut. For 0061aai, the two cooperating creatures may have some space between them. Therefore it is not surprising that the social mechanism of 0061aai is the one prevailed.
gb0/0061aaa.tie - this is the social hyper-parasite that dominated at the time that cheaters invaded.
gb0/0027aab.tie - this is the dominant cheater that invaded against the social hyper-parasites.
gb0/0080.gen - the DOS distribution also includes the assembled binary version of the 0080aaa.tie file, so that Tierra can be run without having to assemble the genome file first.
gb0/arg.exe - the DOS distribution includes the executable version of the assembler/disassembler.
gb0/opcode.map - a file read by Tierra, Beagle, and arg upon startup. This file determines the correspondence between opcodes and the associated machine instructions. This is a simple way to play with the definition of the physics and chemistry of the simulator.
gb0/opcode.vir - a virginal copy of opcode.map. You may use the rnd_inst tool to create new opcode maps, or you may create them by hand. You will have to name the new versions opcode.map in order to assemble the genomes based on the new mapping. You can keep opcode.vir in reserve.
gb0/probe.doc - documentation of the probe tool.
gb0/probe.c - a separate tool for observing the genebank, documented in probe.doc.
gb0/probe.exe - the DOS distribution includes the executable version of the probe program, so that it does not have to be compiled.
gb0/rnd_inst.c - source code of the run_inst tool.
gb0/rnd_inst.doc - documentation of the run_inst tool.
gb0/rnd_inst.exe - the DOS distribution includes the executable version of the rnd_inst program, so that it does not have to be compiled.
gb1: - a subdirectory containing the genomes of the creatures written for use with instruction set 1.
gb1/0005aaa.tie - non-replicating program written to test get().
gb1/0010aaa.tie - non-replicating program written to test put.
gb1/0011aaa.tie - non-replicating program written to test get with template.
gb1/0013aaa.tie - non-replicating program to test put with template.
gb1/0016aaa.tie - non-replicating program to test put.
gb1/0060aaa.tie - a parasite hand-made from the ancestor.
gb1/0095aaa.tie - the ancestor for use in instruction set 1.
gb1/opcode.map - the opcode map for use in instruction set 1.
gb1/opcode.vir - a virginal copy of the opcode map for use in instruction set 1.
gb2: - a subdirectory containing the genomes of the creatures written for use with instruction set 2.
gb2/0050aaa.tie - a parasite hand-made from the ancestor.
gb2/0093aaa.tie - the ancestor for use in instruction set 2.
gb2/opcode.map - the opcode map for use in instruction set 2.
gb2/opcode.vir - a virginal copy of the opcode map for use in instruction set 2.
gb3: - a subdirectory containing the genomes of the creatures written for use with instruction set 3.
gb3/0082aaa.tie - the ancestor for use in instruction set 3.
gb3/opcode.map - the opcode map for use in instruction set 3.
gb3/opcode.vir - a virginal copy of the opcode map for use in instruction set 3.
td: - a subdirectory where a complete record of births and deaths will be written.
td/break.1 - a file containing a record of births and deaths. A dummy file is provided to hold the space.
td/diverse.c - a separate tool for observing the diversity of genotypes and size classes in a run, documented in diverse.doc.
td/diverse.doc - documentation of the diversity tool.
td/diverse.exe - the DOS distribution also includes the executable version of the diversity index tool, so that it does not have to be compiled. See diverse.doc.
td/fragment.c - a separate tool for peparing fragments of a run for observation by the beagle tool, documented in beagle.doc.
td/fragment.exe - the DOS distribution also includes the executable version of the fragment tool. See beagle.doc.
td/run_info.c - a separate tool for peparing the output of a run for observation by the beagle tool, documented in beagle.doc.
td/run_info.exe - the DOS distribution also includes the executable version of the run_info tool. See beagle.doc.
/* begin soup_in file */
# tierra core: 17-5-95 INST == 0
# observational parameters:
BrkupSiz = 1024 size of output file in K, named break.1, break.2 ...
CumGeneBnk = 1 Use cumulative gene files, or overwrite
debug = 0 0 = off, 1 = on, printf statements for debugging
DiskBank = 1 turn disk-genebanker on and off
DiskOut = 1 output data to disk (1 = on, 0 = off)
GeneBnker = 1 turn genebanker on and off
GenebankPath = gb0/ path for genebanker output
hangup = 0 0 = exit on error, 1 = hangup on error for debugging
Log = 1 0 = no log file, 1 = write log file
MaxFreeBlocks = 800 initial number of structures for memory allocation
OutPath = td/ path for data output
SaveFreq = 10 frequency of saving core_out, soup_out and list
SavRenewMem = 0 free and renew dynamic memory after saving to disk
SavMinNum = 10 minimum number of individuals to save genotype
SavThrMem = .02 threshold memory occupancy to save genotype
SavThrPop = .02 threshold population proportion to save genotype
WatchExe = 1 mark executed instructions in genome in genebank
WatchMov = 1 set mov bits in genome in genebank
WatchTem = 1 set template bits in genome in genebank
#NET
# LocalPort = 8001 Port number for local node
# map_fn = MapFile mapfile for Internet
# Nice = 19 Nice value for cpu
# MonPort = 9001 Monitor tool port number
# environmental variables:
alive = 990000 how many generations will we run
DistFreq = -.3 frequency of disturbance, factor of recovery time
DistProp = .2 proportion of population affected by distrubance
DivSameGen = 0 cells must produce offspring of same genotype, to stop evolution
DivSameSiz = 0 cells must produce offspring of same size, to stop size change
DropDead = 5 stop system if no reproduction in the last x million instructions
EjectRate = 50 rate at which random ejections from soup occur
GenPerBkgMut = 16 mutation rate control by generations ("cosmic ray")
GenPerFlaw = 32 flaw control by generations
GenPerMovMut = 8 mutation rate control by generations (copy mutation)
IMapFile = opcode.map map of opcodes to instructions, file in GenebankPath
JmpSouTra = 0. source track switches per average size
JumpTrackProb = .2 probability of switching track during a jump of the IP
MalMode = 1 0 = first fit, 1 = better fit, 2 = random preference,
# 3 = near mother's address, 4 = near bx address
# 5 = near top of stack address, 6 = suggested address (parse dependant)
MalReapTol = 1 0 = reap by queue, 1 = reap oldest creature within MalTol
MalSamSiz = 0 force memory alloc to be same size as parent (stop evolution)
MalTol = 20 multiple of avgsize to search for free block
MateProb = 0.0 probability of mating at each mal
MateSearchL = 5 multiple of avgsize to search 0 = no limit
MateSizeEp = 2 size epsilon for potential mate
MateXoverProp = 1.0 proportion of gene to secect for crossover point
MaxCpuPerCell = 16 maximum number of CPUs allowed per cell
MaxIOBufSiz = 8 maximum size for IOS buffer
MaxMalMult = 3 multiple of cell size allowed for mal()
MaxPutBufSiz = 4 maximum size for put IO buffer
MaxGetBufSiz = 4 maximum size for get IO buffer
MemModeFree = 0 read, write, execute protection for free memory
MemModeMine = 0 rwx protection for memory owned by a creature
MemModeProt = 2 rwx protection for memory owned by another creature
# rwx protect mem: 1 bit = execute, 2 bit = write, 4 bit = read
MinCellSize = 12 minimum size for cells
MinTemplSize = 1 minimum size for templates
MovPropThrDiv = .7 minimum proportion of daughter cell filled by mov
new_soup = 1 1 = this a new soup, 0 = restarting an old run
NumCells = 6 number of creatures and gaps used to inoculate new soup
PhotonPow = 1.5 power for photon match slice size
PhotonWidth = 8 amount by which photons slide to find best fit
PhotonWord = chlorophill word used to define photon
PutLimit = 10 distance for intercellular communication, mult of avg creat siz
ReapRndProp = .3 top prop of reaper que to reap from
SearchLimit = 5 distance for template matching, mult of avg creat siz
seed = 0 seed for random number generator, 0 uses time to set seed
SizDepSlice = 0 set slice size by size of creature
SlicePow = 1 set power for slice size, use when SizDepSlice = 1
SliceSize = 25 slice size when SizDepSlice = 0
SliceStyle = 2 choose style of determining slice size
SlicFixFrac = 0 fixed fraction of slice size
SlicRanFrac = 2 random fraction of slice size
SoupSize = 60000 size of soup in instructions
space 10000
0080aaa
space 10000
0045aaa
space 10000
0080aaa
/* end soup_in file */
The ordering of parameters is not important, except that the creatures used to innoculate the soup must be listed at the end of the file, with no blank lines between the creatures (if there is more than one). Parameters that are not listed in the soup_in or soup_out files, default to the values set in the soup_in.h file. The parameter names must begin at the first character of the line (no spaces or other characters may appear at the beginning of the line before the parameter name).
The meaning of each of these parameters is explained below:
# tierra core: 14-12-93 INST == 0
# observational parameters:
These lines are comments. The code that reads the soup_in and soup_out files skips all blank lines, and all lines beginning with the # character. The input parameters have been divided into two groups, the ``observational parameters'' and the ``environmental variables''. The observational parameters are listed first, and they do not affect the course of events in the run. They only affect what kind of information we extract, and how and where it is stored.
BrkupSiz = 1024 size of output file in K, named break.1, break.2 ...
If this value is set to zero (0) the record of births and deaths will be written to a single file named tierra.run. However, if BrkupSiz has a non-zero value, birth and death records will be written to a series of files with the names break.1, break.2, etc. Each of these files will have the size specified, in K (1024 bytes). The value 1024 indicates that the break files will each be one megabytes in size. The output file(s) will be in the path specified by OutPath (see below). See also DiskOut. Please note that these files can get quite large.
CumGeneBnk = 1 0 = start new genebank, 1 = use cumulative genebank
This parameter gives us the option of starting a fresh genebank, or of working with a cumulative genebank. If you are planning to compare the results of a series of runs, you should consider using a cumulative genebank. With a cumulative genebank, if the identical genotypes appear in successive runs, they will have identical names.
debug = 0 0 = off, 1 = on, printf statements for debugging
This is used during code development, to turn on and off print statements for debugging purposes.
DiskBank = 1 turn disk-genebanker on and off
It is optional to save successful genomes to disk. This parameter determines if genomes are saved to disk.
DiskOut = 1 output data to disk (1 = on, 0 = off)
If this parameter is set to zero (0), no birth and death records will be saved. Any other value will cause birth and death records to be saved to a file whose name is discussed under BrkupSiz above, in the path discussed under OutPath below.
GeneBnker = 1 turn genebanker on and off
The parameter turns the genebanker on and off. The value zero turns the genebanker off, any other value turns it on. With the genebanker off, the record of births and deaths will contain the sizes of the creatures, but not their genotypes. Also no genomes will be saved in the genebank. When the genebanker is turned on, the record of births and deaths will contain a three letter unique name for each genotype, as well as the size of the creatures. Also, any genome whose frequency exceeds the thresholds SavThrMem and SavThrPop (see below) will be saved to the genebank, in the path indicated by GenebankPath (see below).
GenebankPath = gb0/ path for genebanker output
This is a string variable which describes the path to the genebank where the genomes will be saved. The path name should be terminated by a forward slash.
hangup = 0 0 = exit on error, 1 = hangup on error for debugging
If an error occurs which is serious enough to bring down the system, having hangup set to 1 will prevent the program from exiting. In this case, the program will hang in a simple loop so that it remains active for debugging purposes. Set this parameter only if you are running the simulator under a debugger.
Log = 1 0 = no log file, 1 = write log file
If Log is non zero, a disk file called tierra.log will be written mirroring all major simulation states. If disk space is a problem, please set Log = 0. This can be changed at any point in the run.
MaxFreeBlocks = 700 initial number of structures for memory allocation
There is an array of structures used for the virtual memory allocator. This parameter sets the initial size of the allocated array, at startup.
OutPath = td/ path for data output
The record of births and deaths will be written to files in a directory specified by OutPath. See BrkupSiz above for a discussion of the name of the file(s) containing the birth and death records.
SaveFreq = 100 frequency of saving core_out, soup_out and list
Every SaveFreq million instructions, the complete state of the virtual machine is saved. This is a useful feature for long runs, so that the system can be restarted if it is interrupted for some reason.
SavRenewMem = 0 free and renew dynamic memory after saving to disk
When this variable is set to 1, at the time of SaveFreq, all allocated memory is freed after being written to disk. Then the allocated memory is reallocated and the data is read in from disk. The objective of this is to eliminate memory fragmentation. However, this is a new variable and still needs some debugging. It has bad interactions with some other variables. It is advised not to set this variable to 1 for now.
SavMinNum = 10 minimum number of individuals to save genotype
A genotype will not be given a permanent name and saved to disk in a .gen file unless it has a population of SavMinNum or more adult individuals.
SavThrMem = .02 threshold memory occupancy to save genotype SavThrPop = .02 threshold population proportion to save genotype
These two variables affect the rate at which genomes are assigned permanent names and saved to disk. In a soup of 60,000 instructions (SoupSize = 60000), thresholds of .05 will save about one genome per two million instructions, thresholds of .04 will save about one genome per million instructions, thresholds of .03 will save about 1.2 genomes per million instructions, thresholds of .02 will save about three genome per million instructions. On DOS systems, care should be taken to avoid saving too many genomes as they will clog the memory and bring the system down (See KNOWN BUGS below).
SavThrMem = .04 threshold memory occupancy to save genotype
If a particular genotype fills SavThrMem of the total space available in the soup, it will be assigned a permanent unique name, and saved to disk. Note that an adjustment is made because only adult cells are counted, and embryos generally fill half the soup. Therefore adult cells of a particular genotype need only occupy SavThrMem * 0.5 of the space to be saved.
SavThrPop = .04 threshold population proportion to save genotype
If a particular genotype amounts to SavThrPop of the total population of (adult) cells in the soup, it will be assigned a permanent unique name, and saved to disk.
WatchExe = 0 mark executed instructions in genome in genebank WatchMov = 0 set mov bits in genome in genebank WatchTem = 0 set template bits in genome in genebank
WARNING: setting any of these three watch parameters will engage CPU intensive observational software that will substantially slow down any simulation. Engage these tools only if you plan to use the data that they generate.
WatchExe = 0 mark executed instructions in genome in genebank
If the genebank is on, setting this parameter to a non-zero value will turn on a watch of which instructions are being executed in each permanent genotype (this helps to distinguish junk code from code that is executed), and also, who is executing whose instructions. There is a bit field in the GList structure (bit definitions are defined in the tierra.h module) that keeps track of whether a creature executes its own instructions, those of another creature, if another creature executes this creatures instructions, etc:
bit 2 EXs = executes own instructions (self)
bit 3 EXd = executes daughter's instructions
bit 4 EXo = executes other cell's instructions
bit 5 EXf = executes instructions in free memory
bit 6 EXh = own instructions are executed by other creature (host)
WatchMov = 0 set mov bits in genome in genebank
If the genebank is on, setting this parameter to a non-zero value will turn on a watch of who moves whose instructions and where. This information is recorded in the bit field in GList structure:
bit 17 MFs = moves instruction from self
bit 18 MFd = moves instruction from daughter
bit 19 MFo = moves instruction from other cell
bit 20 MFf = moves instruction from free memory
bit 21 MFh = own instructions are moved by other creature (host)
bit 22 MTs = moves instruction to self
bit 23 MTd = moves instruction to daughter
bit 24 MTo = moves instruction to other cell
bit 25 MTf = moves instruction to free memory
bit 26 MTh = is written on by another creature (host)
bit 27 MBs = executing other creature's code, moves inst from self
bit 28 MBd = executing other creature's code, moves inst from daughter
bit 29 MBo = executing other creature's code, moves inst from other cell
bit 30 MBf = executing other creature's code, moves inst from free memory
bit 31 MBh = other creature uses another CPU to move your instructions
WatchTem = 0 set template bits in genome in genebank
If the genebank is on, setting this parameter to a non-zero value will turn on a watch of whose templates are matched by whom. This information is recorded in the bit field in the GList structure:
bit 7 TCs = matches template complement of self
bit 8 TCd = matches template complement of daughter
bit 9 TCo = matches template complement of other
bit 10 TCf = matches template complement of free memory
bit 11 TCh = own template complement is matched by other creature (host)
bit 12 TPs = uses template pattern of self
bit 13 TPd = uses template pattern of daughter
bit 14 TPo = uses template pattern of other
bit 15 TPf = uses template pattern of free memory
bit 16 TPh = own template pattern is used by other creature (host)
# LocalPort = 8001 Port number for local node # map_fn = MapFile mapfile for Internet # Nice = 19 Nice value for cpu # MonPort = 9001 Monitor tool port number
These varibles are only for the network version.
# environmental variables:
This is a comment indicating the beginning of the environmental parameters. These parameters affect the course of evolution and ecology of the run.
alive = 500 how many generations will we run
This tells the simulator how long to run, in generations.
DistFreq = -.3 frequency of disturbance, factor of recovery time
The frequency of disturbance, as a factor of recovery time. This and the next option control the pattern of disturbance. If you do not want the system to be disturbed, set DistFreq to a negative value. If DistFreq has a non-negative value, when the soup fills up the reaper will be invoked to kill cells until it has freed a proportion DistProp of the soup. The system will then keep track of the time it takes for the creatures to recover from the disturbance by filling the soup again. Let's call this recovery time: rtime. The next disturbance will occur: (rtime X DistFreq) after recovery is complete. Therefore, if DistFreq = 0, each disturbance will occur immediately after recovery is complete. If DistFreq = 1, the time between disturbances will be twice the recovery time, that is, the soup will remain full for a period equal to the recovery time, before another disturbance hits. Using this parameter (positive values) will probably create problems in conjuction with memory allocation modes that specify the address where the daughter will be placed.
DistProp = .2 proportion of population affected by distrubance
The proportion of the soup that is freed of cells by each disturbance. The disturbance occurs by invoking the reaper to kill cells until the total amount of free memory is greater than or equal to: (DistProp X SoupSize). Note that cells are not killed at random, they are killed off the top of the reaper queue, except as modified by the ReapRndProp variable.
DivSameGen = 0 must produce offspring of same genotype, to stop evolution
This causes attempts at cell division to abort if the offspring is of a genotype different from the parent. This can be used when the mutation rates are set to zero, to prevent sex from causing evolution.
DivSameSiz = 0 cells must produce offspring of same size, to stop size change
Like DivSameGen, but cell division aborts only if the offspring is of a different size than the parent. Changes in genotype are not prevented, only changes in size are prevented.
DropDead = 5 stop system if no reproduction in the last x million instructions
Sometimes the soup dies, such as when mutation rates are too high. This parameter watches the time elapsed since the last cell division, and brings the system down if it is greater than DropDead million instructions.
EjectRate = 50 rate at which random ejections from soup occur
Controls the rate at which creatures being born into the soup are ejected from the soup. The value 50 means one in fifty creatures. In a single processor implementation, ejection means death. However, on a parallel machine like the CM5, or in a networked implementation, ejection means migration to a soup on another processor.
GenPerBkgMut = 16 mutation rate control by generations ("cosmic ray")
Control of the background mutation rate ("cosmic ray"). The value 16 indicates that in each generation, roughly one in sixteen cells will be hit by a mutation. These mutations occur completely at random, and also affect free space where there are no cells. If the value of GenPerBkgMut were 0.5, it would mean that in each generation, each cell would be hit by roughly two mutations.
GenPerFlaw = 64 flaw control by generations
Control of the flaw rate. The value 64 means that in each generation, roughly one in sixty-four individuals will experience a flaw. Flaws cause instructions to produce results that are in error by plus or minus one, in some sense. If the value of GenPerFlaw were 0.5, it would mean that in each generation, each cell would be hit by roughly two flaws. This parameter has a profound effect on the rate at which creatures shrink in size under selection for small size.
GenPerMovMut = 8 mutation rate control by generations (copy mutation)
Control of the move mutation rate (copy mutation). The value 8 indicates that in each generation, roughly one in eight cells will be hit by a mutation. These mutations only affect copies of instructions made during replication (by the double indirect mov instruction). When an instruction is affected by a mutation, one of its five bits is selected at random and flipped. If the value of GenPerMovMut were 0.5, it would mean that in each generation, each cell would be hit by roughly two move mutations.
IMapFile = opcode.map map of opcodes to instructions, file in GenebankPath
Names the file containing the Instruction Set Map. The simulator will look for this file in the GenebankPath. Please remember to only use genebank files created with compatible map files. This is facilitated by having each different opcode.map file in a separate genebank directory.
JmpSouTra = 0. source track switches per average size JumpTrackProb = .2 probability of switching track during a jump of the IP
These are experimental parameters that have been introduced to control track expression in diploid (or higher) implementation. Each CPU has a source and destination track defined, four use with the move instructions. The movii instruction copies from the source track to the destination track. The source track will be randomly changed at the rate defined by the JmpSouTra variable. Each CPU also has an execute track defined. This will also change at random during any jump of the instruciton pointer, at a probability determined by the JumpTrackProb variable.
MalMode = 1 0 = first fit, 1 = better fit, 2 = random preference, # 3 = near mother's address, 4 = near bx address # 5 = near top of stack address, 6 = suggested address (parse dependant) MalReapTol = 1 0 = reap by queue, 1 = reap oldest creature within MalTol MalTol = 20 multiple of avgsize to search for free block
Memory allocation control:
Chris Stephenson of the IBM T. J. Watson Research Center (cjs@yktem.vnet.ibm.com) has contributed a new memory allocator to Tierra, based on a cartesian tree scheme that he developed. The new allocator is more efficient than the old and provides a variety of options for controlling where offspring are placed. Free blocks are maintained in a two dimensional binary tree, in which daughter blocks can not be larger than their parents, and blocks are ordered from left to right according to their position in memory.
MalMode = 1 0 = first fit, 1 = better fit, 2 = random preference, # 3 = near mother's address, 4 = near bx address # 5 = near top of stack address, 6 = suggested address (decode dependant)
This variable provides seven options for controlling where offspring are placed in the soup.
0 = first fit: this is the method used in versions of Tierra before V4.0. In this method, free blocks are checked starting with the leftmost block in memory, and the first block large enough to accomodate the request us used.
1 = better fit: this method starts from the root of the tree, and if the free block is larger than the request, it moves to the daughter free block that is closest to the size of the request, this provides a better fit of the request to the free block, but not necessarily the best fit.
2 = random preference: blocks of memory are allocated at positions selected at random from the soup.
3 = near mother's address: blocks of memory will be placed near the creature making the request (daughters will be placed near mothers), within the specified tolerance (see MalReapTol and MalTol).
4 = near dx address: blocks of memory will be placed near the address specified in the dx register, within the specified tolerance (see MalReapTol and MalTol).
5 = near top of stack address: blocks of memory will be placed near the address specified at the top of the stack, within the specified tolerance (see MalReapTol and MalTol).
6 = suggested address (decode dependant): this is effectively like modes 4 and 5, except that the source of the requested address is variable, and will be decided by the decode code. In other words, the target address could be specified by the value in any register.
MalReapTol = 1 0 = reap by queue, 1 = reap oldest creature within MalTol
When a position and tolerance is specified for the daughter cell, the reaper will probably have to free memory in that area to service the request. If the reaper kills strictly by the reaper queue, without regard to location, it may kill many cells before killing in the vicinity of the request. This creates situations in which it is difficult for populations to grow, because the reaper kills much more than is necessary. To resolve this problem, an option is added in which the reaper still uses the queue, but it only kills cells that fall within the tolerance region of the requested location. The variable MalReapTol turns this option on.
MalSamSiz = 0 force memory alloc to be same size as parent (stop evolution)
Setting this variable to 1 will cause all memory allocations by creature to be the same size as the creature. This contributes to preventing evolution.
MalTol = 20 multiple of avgsize to search for free block
This determines a region of tolerance within which a request for a specific location of memory can be serviced. It is specified as a multiple of the average creature size.
MateProb = 0.2 probability of mating at each mal MateSearchL = 5 multiple of avgsize to search 0 = no limit MateSizeEp = 2 size epsilon for potential mate MateXoverProp = 1.0 proportion of gene to secect for crossover point
Haploid Sex (aka crosover):
Haploid sex has been implemented in mimicry of Walter Tackett's (tackett@ipld01.hac.com) implementation in his private version of Tierra. This form of sex is more in the spirit of the genetic algorithm that Tierra, in that the creatures don't have any choice in the matter, they are forced to have sex at god's whim. However, it does have the virtue of creating something like a biological species, in that individuals close in size exchange genes creating an evolving gene pool.
The Tierran reproduction mechanism of repeatedly copying data from an offset in the mother cell to an offset (presumably) in a daughter cell, can be modified to easily allow ``crossover'' of genetic data. Crossover seems to provide a means of increasing the rate of evolution. It can be thought of as a higher mutation rate which can ``favor good genes''. This affect will be made clear by euclidating how haploid crossover ``sex'' is done in the Tierran model.
At the time a creature allocates a block of memory for a daughter (mal), Tierra decides if this creature will mate, using the soup_in variable MateProb (0.0 = no mating at all, 100.0 = creatures will try to mate 100% of the time). If the creature is not selected for mating, Tierra continues as normal until the next time this creature executes a memory allocate. If this creature does mate, a point in the creatures genome, selected randomly from the proportion MateXoverProp of the genome size, is chosen as the ``cross over'' point. Also whether we use the first part, or the last part of the genome is also chosen (chances are 1 in 2 for each "half"). No further actions are taken until the creature begins moving data (presumably from herself, to the daughter cell).
At the time that the creature first copies an instruction of its genome to a new location (presumably in the daughter cell) using the moviab instruction, a mate is chosen. The mate is chosen at this point because the chances of the mate dying before the cross over is complete are smaller now than at the time of the memory allocation. A potential mate must be similar in size to the creature trying to mate (creature's size +/- MateSizeEp), and may not be of the exact same genotype (eg. 0080aaa can't mate with another 0080aaa, there would be no point in the operation). The search radius from the creature to the mate is determinied by MateSearchL. MateSearchL is multiplied by the Average Creature Size to determine the number of bytes to search. NOTE - in release 3.13, only FORWARD ( towards higher addresses ) in done. This will become bidirectional in future releases. Even if a creature is selected for mating a the time of execution of the mal instruction, it may not actually mate, because it may not be able to find a mate of a different genotype, in the correct size range, and within the search radius.
If we have chosen to contribute our first section to the daughter, our mate will contribute the second section. In that case, the copying of the genome will proceed normally until we reach the crossover point. After that, each time we execute the moviab instruction, we will copy an instruction from the genome of our mate rather than from our genome. The creature is ``unaware'' of this process. For the sake of clarity an example is given:
Example A - Mate contributes second half :
creature ( 10 bytes long ) & mate ( 9 bytes long ) [ step 0 ] mal - selects Xover point of 5, second half [ step 1 ] move bytes at offset 0-4 from self [ step 2 ] move byte at offset 5-9 from mate [ step 3 ] move byte after last byte of mate ( 10th byte )
Example B - Mate contributes first half :
creature ( 10 bytes long ) & mate ( 11 bytes long ) [ step 0 ] mal - selects Xover point of 5, first half [ step 1 ] move bytes at offset 0-4 from mate [ step 2 ] move byte at offset 5-10 from self
MaxCpuPerCell = 16 maximum number of CPUs allowed per cell
Beginning with version 4.1, it is possible for individual cells to have more than one CPU, to allow parallelism. The maximum number of CPUs that a single cell may have is determined by this variable.
MaxMalMult = 3 multiple of cell size allowed for mal()
When a cell attempts to allocate a second block of memory (presumably to copy its genome into), this parameter is checked. If the amount of memory requested is greater than MaxMalMult times the size of the mother cell, the request will fail. This prevents mutants from requesting the entire soup, which would invoke the reaper to cause a massive kill off.
MemModeFree = 0 read, write, execute protection for free memory MemModeMine = 0 rwx protection for memory owned by a creature MemModeProt = 2 rwx protection for memory owned by another creature
From the point of view of a particular creature, memory is divided into three classes: owned by a creature, owned by another creature, not owned by any creature. Each of these three classes of memory may have a unique read, write, execute memory protection for the creature in question. 1 bit = execute, 2 bit = write, 4 bit = read So:
execute write read 0 Y Y Y 1 N Y Y 2 Y N Y 3 N N Y 4 Y Y N 5 N Y N 6 Y N N 7 N N N
Be aware that each of the three forms of memory protection is turned on at compile time by the appropriate definitions:
#define READPROT /* define to implement read protection of soup */ #define WRITEPROT /* define to implement write protection of soup */ #define EXECPROT /* define to implement execute protection of soup */
The version distributed on disk only has write protection turned on. To implement the other forms of protection you will need to comment in the appropriate line in the configur.h file, and recompile. Once the relevant form of protection is defined at compile time, the MemModexxxx variables still determines how it is actually used. We do this because each form of memory protection is costly of CPU time, and write protection is the only one likely to be used.
MemModeFree = 0 read, write, execute protection for free memory
When memory is free, not owned by any creature, it will have this protection. 0 means that the creature can read, write, or execute the free memory.
MemModeMine = 0 rwx protection for memory owned by a creature
This determines how the creature may use the memory that it owns. 0 means that the creature can read, write, or execute its own memory.
MemModeProt = 2 rwx protection for memory owned by another creature
When memory is owned by a creature other than the one that is currently executing, it will have this protection. 2 means that write privelage is protected, so only the owner can write on the memory. The creature that is currently executing will not be able to write on this memory.
MinCellSize = 8 minimum size for cells
When a cell attempts to divide, this parameter is checked. If the daughter cell would be smaller than MinCellSize instructions, divide will fail. The reason this is needed is that with no lower limit, there is a tendency for some mutants to spawn large numbers of very small cells.
MinTemplSize = 1 minimum size for templates
When an instruction (like jump) attempts to use a template, this parameter is checked. If the actual template is smaller than MinTemplSize instructions, the instruction will fail. This is a matter of taste.
MovPropThrDiv = .7 minimum proportion of daughter cell filled by mov
When a cell attempts to divide, this parameter is checked. If the mother cell has moved less than MovPropThrDiv times the mother cell size, of instructions into the daughter cell, cell division will abort. A value of .7 means that the mother must at least fill the daughter 70% with instructions (though all these instructions could have been moved to the same spot in the daughter cell). The reason this parameter exists is that without it, mutants will attempt to spew out large numbers of empty cells.
new_soup = 1 1 = this a new soup, 0 = restarting an old run
This value is checked on startup, to determine if this is a new soup, or if this is restarting an old run where it left off. When the system comes down, all soup_in parameter (and many other global variables) are saved in a file called soup_out. The value of new_soup is set to 0 in soup_out. In order to restart an old run, just use soup_out as the input file rather than soup_in. This is done by using soup_out as a command line parameter at startup: tierra soup_out
NumCells = 3 number of creatures and gaps used to inoculate new soup
This parameter is checked at startup, and the system will look for a list of NumCells creatures at the end of the soup_in file. The value 3 indicates that the soup will initially be innoculated by three cells. However, NumCells also counts gaps that are placed between cells (without gaps, all cells are packed together at the bottom of the soup at startup). Notice that after the list of parameters in the soup_in file, there is a blank line, followed by a list of genotypes. The system will read the first NumCells genotypes from the list, and place them in the soup in the same order that they occur in the list.
PhotonPow = 1.5 power for photon match slice size
If SliceStyle (see below) is set to the value 1, then the allocation of CPU cycles to creatures is based on a photon - chlorophyll metaphor. Imagine that photons are raining down on the soup at random. The cell hit by the photon gets a time slice that is proportional to the goodness of fit between the pattern of instructions that are hit, and an arbitrary pattern (defined by PhotonWord, see below).
The template of instructions defined by PhotonWord is laid over the sequence of instructions at the site hit by the photon. The number of instructions that match between the two is used to determine the slice size. However, the number of matching instructions is raised to the power PhotonPow, to calculate the slice size.
PhotonWidth = 8 amount by which photons slide to find best fit
When a photon hits the soup, it slides a distance PhotonWidth, counting the number of matching characters at each position, and the slice size will be equal to the number of characters in the best match (raised to the power PhotonPow, see above). If PhotonWidth equals 8, the center of the template will start 4 instructions to the left of the site hit by the photon, and slide to 4 instructions to the right of the site hit.
PhotonWord = chlorophill word used to define photon
This string determines the arbitrary pattern that absorbs the photon. It uses a base 32 numbering system: the digits 0-9 followed by the characters a-v. The characters w, x, y and z are not allowed (that is why chlorophyll is misspelled). The string may be any length up to 79 characters.
PutLimit = 10 distance for intercellular communication, mult of avg creat siz
The put/get instructions allow messages to be passed between cells. In one mode, the addressing of the target cell is based on complementary template matching. The distance that is searched to find complementary templates is determined by this variable.
ReapRndProp = .3 top prop of reaper que to reap fr