Brew is an environment for ‘Evolutionary Programming’.
It's an experiment raising an ‘Artificial Code Evolution’.
I wrote brew out of curiosity and for fun, enjoy...
Brew is homebrew by Robert Epprecht <epprecht@solnet.ch>.
This brew version runs best on *Linux text console*.
Please *do* use that, if you can.
Running brew outside Linux text console is not really supported,
though brew might run on it, if you're lucky.
--- The Detailed Node Listing ---
Introduction
What do I mean by 'evolutionary programming'?
Changing code
Biological analogy.
Getting started
Why FORTH
Brew user manual
Brews main display:
Individuals, nuclei and spots:
Controlling population:
Diversification and mutation:
Displaying statistics about cells and spots:
Advanced operation:
World wide settings and creation of new worlds:
Logging and writing the generated program code to files:
Recording evolutionary sessions:
Compile time configuration:
Miscellaneous:
Some brew basics
Classes of variables
Display modes
Using menus
Menu example
Brew main screen
Display menu
Configuring spot display
Step display menu
The different kinds of statistical data representations can be combined at the same time each one in his own screen area.
Color menu
Population control
Diversification menu
Mutation menu
Gene primitives
Floating point primitives:
Conditional structures:
Whole tested genomes can be used like new primitives:
Do something on nuc or spot subsets.
Extended conditions requiring parameters and a comparison:
Actions to be done on the defined subset:
Generic interface to act on a nuc subset:
Menu current genomes
Big Bang menu
Brews record and playback feature.
Programmers manual
Brews files overview
Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble ======== The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software–to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs ============================================= If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. ONE LINE TO GIVE THE PROGRAM'S NAME AND AN IDEA OF WHAT IT DOES. Copyright (C) 19YY NAME OF AUTHOR This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items–whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. SIGNATURE OF TY COON, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
'brew' is an interactive environment for experiments with an
‘artificial code evolution’ using the Forth language.
See Evolutionary programming.
The main intention is to supply a test environment to experiment with this fascinating programming technique, try out different approaches and to analyse the results.
Brew generates gene sequences of real Forth code and compiles successful genes at run time. It gives you lots of possibilities to watch the evolutionary process in real time, like scanning inner variables and displaying results as bar graphics or let its cells be located in a grid and show that on screen. Brew can write the generated code to files or generate detailed log files about many aspects of its inner working.
Brews recording capability allows reproducing interactive sessions and demonstrating them easily, or to run series of experiments with changed parameters.
Brew comes with its own pseudo graphical user interface which gives you access to just about every parameter and setting without learning a new syntax. This can be done interactively at any time of an evolutionary experiment and you can study the effects immediately.
Brew is extensible. Suggestions about missing features are welcome.
If you experiment with it, please let me know. I'm interested in
extending brew based on user feedback.
If you miss information about some topic in this manual mail me please. I will add more nodes on request.
Years ago I had a crazy idea:
Shouldn't it be possible to write a program that would generate program
units by creating numerous more or less random code snippets and optimise
them by a evolutionary process a bit similar to the darvinistic view of
biological evolution?
I imagined that the main program would start a number of small program items with random code and random variable values that were scored on success of solving a given task. If the score reached a certain level the program can reproduce and build another copy of itself. If the limit isn't reached within a certain time the item gets taken out of the play. So I imagined that successful code (and variable values) would increase rapidly, while bad variants would disappear.
The trick is to make the copies of the program snippets differ a bit from the original ones, changing code and variables, at least sometimes. So new genetic variants and mutations arise.
When the number of tried code snippets increases too much, the conditions are made harder automatically. The results must be better now to be considered a success. Couldn't that give a evolution a bit similar to the biological one?
I tried it out on a old slow Atari ST using Forth as language and was positively surprised and fascinated by the results.
Later on I rewrote the whole thing on more decent hardware under Linux. I learned through usenet discussions that the principle wasn't at all my own invention. Others had tried similar things long before me under names like ‘evolutionary programming’, ‘genetic programming’ or even ‘artificial life’ and others.
I prefer the term ‘evolutionary programming’ and call the process a ‘artificial code evolution’.
Let's take a very simple example:
In an experiment you would change a single parameter and get a single
result. You would like brew to figure out how to compute the result
from the input parameter. It could be an electronic device, with one
input and one output.
So you'd give a certain input to the device and measure its output. You provide the input (as read only variable) to the program and expect the code snippets to return their guess for the output in a certain variable. The input would get changed with each step.
Now the code snippets would get scored on their guess what the output could be. Eventually they might find out by accident to put the result of a computation based on the input in the variable where you expect the result. A kind of evolution might start giving better results after some time.
Of course you'd have to supply the hardware and software interface to the tested device if you'd actually want to do the experiment with brew. When testing brew I do not actually do the experiment, but give a random input parameter and supply the result formula to the scoring process. So the evolutionary process would have to find out a surviving strategy under this (unknown) scoring rule.
Let's assume the electronic device in our example is a very simple one. It would give an output that would be the sum of an offset and the input voltage multiplied by a gain:
output ^ * | * |* * <- offset *| ————–*-+—————> input * | * | * | * |
Maybe we would start the evolution with inputs very close to zero, drifting away in a random way.
One of the random code snippets might copy the content of a inner variable to the result variable. If the result happens to be somehow close to the offset of the device this will give a better score.
Brew takes two different approaches to optimise the result:
Inner variables, local to the code snippets get changed in a random way when the code reproduces. In our simple example the inherent selection process will lead to the variable in question getting closer and closer to the offset of the probed electronic device, as the cells with this value would get the highest score.
In a biological analogy I would compare such diversification to an individual having a bit longer legs or something. It's more like a variation then a real mutation.
Meanwhile the tested input voltage of our experiment would have drifted away from zero during our evolution. So the gain part of our hypothetical device gets more and more influence on the result over time.
In a certain rate brew does try out other random code to be executed by mutating it. It might try out multiplying the input by the content of another local variable and adding it to the offset. If this happens, the gain variable and the offset variable would optimise quickly by the mechanism described above.
In a biological analogy I would compare this to proper mutation, like an individual having another number of legs or growing wings instead.
Brew does generate gene sequences of real Forth code.
While results do happen sometimes to be as ideal as described above, this
is not always the case. Probably there would be much more code executed
that might not have any influence on the result. As we will see later,
we can score on code length too, and mutation can cut out random code
parts to strip it down to the essential parts.
Quite often the process will not find usable solutions at all, or give good, but very unexpected results ;-)
The concept of 'evolutionary programming' has many analogies to biological evolution.
The mechanism how brew tries to find a solution to a given task is very similar to the darvinistic approach on biological evolution. As we need words to think about something I do use a pseudo-biological vocabulary to describe what's happening. As simple as the basic concept may appear, things get much more complex as you proceed.
In this manual and in the source I do use terms like 'cell' 'genes' 'genome' 'reproduction' 'cell division' 'population' 'food' 'birth' 'living' and many others. I want to make clear that this is only an analogy, helping my limited mind to understand and communicate how things work.
I do not think in any way that brew is actually producing a kind of virtual life, though it might look sometimes as if it would.
This being said I can mention the fact, that some people do use terms like ‘Artificial Live’ differently and might actually use it in the context of brew.
Let me give you some biological terms and an explanation what they mean in the context of brew:
Brew is a highly customisable and very interactive program to try out ‘evolutionary programming’.
Brew has some special features. Let me just enumerate some:
In world mode brew is a kind of ‘Evolutionary Cellular Automata’. I think there's much potential in this combination.
tail -f
on these files and watch what's happening.
If you don't know Forth consider learning a bit. It's not difficult, just forget what you have learned about other computer languages first. Forth is different.
Download brew:
Get a current brew version from http://reppre51.home.solnet.ch/
Installation:
To install brew just unpack the files, say:
* tar -xvjf brew.tar.bz2
(if you have a xxx.tar.bz2 file).
(older tar versions might need ‘-xvIf’ instead of ‘-xvjf’).
* tar -xvzf brew.tgz
(if you have a xxx.tgz file)
then:
cd brew
I would unpack brew in brew users home directory.
Please do read README-SECURITY.
Forth:
You need a Forth system to run brew.
Basically you start brew by changing to the brew directory and
typing the name of your Forth system followed by ‘brew.fs’:
cd brew
FORTH brew.fs
where‘FORTH’ is the name of your Forth.
As brew needs a lot of dictionary space you have to start most Forth's with additional options. See the different Forth systems below for instructions.
Brew is developed and tested mainly on Gforth on Linux text console.
It's tested (less intensively) on some other Forth systems and seems to
run there. Please mail me if you want to adapt it to other systems.
How to get a Forth system and how to start brew:
Now you can try to start brew on a text console.
Brew will give you some usage hints, so just try it out.
You should be able to reach a context sensitive help from just about any place inside brew, by pressing <<F1>> or ?.
Most things in brew are text mode menus. Just move the cursor somewhere and press <<RETURN>> to select something and explore some of brews possibilities. So when in other types of user interfaces you would move the mouse and click on something, you do this in brew by moving the text cursor and press<<RETURN>>.
k will normally show you key bindings active in the context.
Quit brew with ‘QUIT brew’ in system menu (see System menu),
or by saying ‘goodbye’ (which might be on <<F12>>).
(see Menu function keys). My personal shortcut to quit brew is
pressing a couple of y.
Brew will clean up temporary files and give you a list of produced output files.
This brew version runs best on the Linux *text console*.
Running brew outside Linux text console is not really supported,
though you might eventually succeed to run it there. Whatever you
try, please do use a *fixed width* font, brews menu system depends
on that.
There is a simple console size setup helper configure-console.fs. Try that if there are display problems.
If you have problems with keys like <<RETURN>>
<<CURSOR-ARROWS>> <<FUNCTION-KEYS>>
<<PageUp>> <<Home>> try to run
make-ekey-map.fs. Brew will suggest that anyway if it
gets unknown key codes.
(see Console and key setup)
A good place to ask questions about Forth is comp.lang.forth on usenet.
You will find many active Forth experts there.
Gforth is a widely used Forth under the GPL. It is my main development platform and available for many different processor architectures. The goal of the Gforth Project is to develop a standard model for ANS Forth. Gforth comes with documentation in info format.
Chances are good, that your Linux includes Gforth, but I would recommend compiling it from source.
Get Gforth from:
http://www.complang.tuwien.ac.at/forth/gforth/
http://www.jwdt.com/~paysan/gforth.html
Join the Gforth mailing list, if you have questions about it.
To start brew change to the brew directory and say something like:
gforth --dictionary-size 10M brew.fs
Of course you can adapt dictionary-size to your needs. About 2M is the
minimum to run brew, the more the better. I use 120M and more ;-)
‘pfe’ the ‘Portable Forth Environment’ is a very nice Forth
implementation in C. You can download it from:
http://sourceforge.net/projects/pfe
start brew with:
cd brew/
pfe brew.fs
bigForth is another GPL'd (at least for Linux) Forth system. It is written by Bernd Paysan. Bigforth comes with interesting extensions (like MINOS) which are not used by brew however.
Get it from http://www.jwdt.com/~paysan/bigforth.html
There is a mailing list too.
You have to increase mem-size and dictionary-size to use brew on bigForth.
For a big comfortable system you could say
bigforth --mem-size 106M --dictionary-size 80M brew.fs
bigforth --mem-size 4M --dictionary-size 2M
would be about the minimum.
As you can see mem-size has to be bigger than the desired dictionary-size. Bernd Paysan, the author of bigForth advised me to take about 9/8 and add a few megabytes. Just try it out.
A very fast commercial Forth written by Marcel Hendrix mainly for NT, but running also under Linux.
See Marcel Hendrix's home-page for more adequate information.
http://home.iae.nl/users/mhx/
Brew on iForth is experimental at the moment,
a step more experimental than brew is anyway ;-)
Marcel Hendrix had informed me that some newer brew versions gave different results on iForth 2.0 than I'm getting on the systems I use here. These problems have disappeared now. Benchmarks do run now and give the same (evolutionary) results as on Gforth, pfe and bigFORTH, and Brew runs very fast on iForth 2.0.
But I still do have problems with brews menu system on iForth 2.0 on Linux. (I do not have NT to test on it).
We will try to fix that. So please check for a new brew version.
Press <<SPACE>> to start and stop the evolutionary process.
Watch it for a while, then just press some keys and see what happens...
Yes, please do me the favour and just give it a try before you
read on, I'll wait here for you...
Hope you'll find your way out somehow ;-)
Leave brew by pressing some Q or try <<F12>>.
You should be able to read the context sensitive documentation by pressing ? or (hopefully) <<F1>>.
People ask me why I do use such a strange language as FORTH and not C, C++ or Java. The reason is not because brew is such a crazy program that I just *had* to use some obscure minority language to write it, no, I have selected FORTH for a couple of reasons:
A quick note to Forth programmers:
Please note that I do use some terms different than they are used inside the Forth community, so that people coming from other computer languages might understand what I mean:
Brews main display:
Individuals, nuclei and spots:
Controlling population:
Diversification and mutation:
Displaying statistics about cells and spots:
Advanced operation:
World wide settings and creation of new worlds:
Logging and writing the generated program code to files:
Recording evolutionary sessions:
Compile time configuration:
Miscellaneous:
There are some basic things you should understand to work with brew:
In analogy to biology the Forth words executed by a cell are called ‘genes’.
Genes can get changed by the ‘mutation’ process. It is essential to understand that mutation will only build on predefined gene primitives. So if the manual talks about random code mutations this is a simplification. Genes can only do things that are possible to program with the given set of ‘gene primitives’. Like everything in brew the set of gene primitives and the probability of each primitive to get used by the mutation process can be configured at run time (or by configuration files) and saved. Of course you can change that during an evolution.
The set of gene primitives delivered with brew does not allow to call any system functions or extern programs. This is absolutely crucial for security reasons! If you introduce a new gene primitive you *must* take care that mutation cannot possibly build anything dangerous with it. The cells don't care what they do, they just try everything they can...
The possibilities given by the gene primitives are in fact quite restricted. The genes can access a set of variables, some of them are read only, some can be written. There are genes to read and (possibly) write these variables, genes for mathematical operations, comparisons and conditionals...
There are *no* gene primitives to do any kind of address arithmetics. This is essential not only for security reasons, but also for the stability of the program. If you program new gene primitives you must be aware of that.
The trick of evolutionary programming is to let copies of a genome be variants and not just clones of the mother genome, at least sometimes.
There are two distinct ways brew does variation of the mother cell:
In a biological analogy I would compare diversification to a child having
legs that differ a bit in length from those of the mother, while in the
case of mutation it would have another number of legs or grow wings instead.
Most of the gene sequences generated by mutation are absolutely useless. It would be a waste of memory to compile them all.
So new genomes must go through a so called ‘trial phase’ first.
If the genome survives a given number of generations it will be
compiled into the ‘gene pool’, but only a small fraction of the
mutated genomes pass this test successfully.
Genes on trial never get mutated, but the variables can get diversified as usual.
See Why Forth?, for some technical details.
The variables that the genes can see come in two distinct classes:
Hereditary variables inside the nuc and external world variables.
Nuc variables are local to the cell, world variables to the spot.
All of them come as integer and float variables, and have read-only
and read-write variants.
Another (orthogonal) distinction is between variables that get diversified (or at least can be) and those that are not.
Some of them (i.e. the cells ID) have no relation to the genes and can not be seen by the cell. They only have meaning for brew.
Others can be read or read and written by the cells genes.
As part of the nucleus these variables are hereditary, are copied
from the mother cell to their children. Some of these variables
can be diversified and will get optimised by selection of 'good'
values.
Read only world variables get often used as inputs of the task the cells are expected to do.
The number of variables of each class and subclass is compile time configurable, of course.
It helps understanding brew better if you know about the names of the different classes of variables. Look them up here:
All variables of a subclass have the same name witch a capital letter to distinguish each individual variable. Think of the capital letter as an index in an array. For nuc variables the letter follows the name, while it precedes in the case of world variables. So ‘organ-A’ and ‘organ-B’ are two nuc variables of the same kind, while ‘A-quality’ is a world variable.
Name: | class: | access: | diversified? | compile option
|
integer-A | global | read/only | maybe | global-integer-variables#
|
dfloat-A | global | read/only | maybe | global-dfloat-variables#
|
organ-A | nuc | read/write | maybe | nuc-organs#
|
parameter-A | nuc | read/only | maybe | nuc-parameters#
|
invisible-A | nuc | hidden | maybe | nuc-invisibles#
|
secret-A | nuc | hidden | no | nuc-secrets#
|
A-quality | world | read/write | maybe | spot-qualities#
|
A-property | world | read/only | maybe | spot-properties#
|
A-secret | world | hidden | maybe | spot-secrets#
|
All these different kinds of variables come either as integer or as floating point variables. The latter do have a ‘-f-’ in their name. So ‘f-organ-A’ would be the first read/write floating point nuc variable.
For special purposes there are hidden variables not visible to the (default) gene primitives. You might want to use them for some experiments that i.e. introduce new gene primitives using such variables, without giving the mutation process the ability to access them directly.
Please note:
The next brew version will *not* follow these naming rules any more.
Names will be more custom defined, related to the experiments setup.
Visibility and r/w status will be determined by gene availability only.
Brew can run in a number of different modes.
You must understand at least the first two:
run-mode-masks
to learn more about.
You can combine different modes if they are not exclusive. So you can be in record mode *and* in linear mode at the same time, but you cannot be in world mode and linear mode at the same time, and you can't record and playback simultaneously. Brew will not let you switch to impossible run mode combinations, so just try it out.
You switch run modes in the corresponding menus:
See System menu, for switching between world and linear mode.
See Record and Playback, for recording and playback.
Brew can display very different informations in a number of ways:
You can look how the cell cultures move in the virtual world while in world mode, or you can watch statistics as text summary or bar graphs in real time in step display.
Just look at some examples:
................... ******** ........ .** ... ********* . .... .................... *******. ...... ..**** .......********* ....... ................... ****** ........**** .......******** ........ .................... . . ****** ......***** .......*******........... ......................... ******** .... ..**** * ......... *** ........... ......................... *******. . . ******** ..........****............ .. .. ......... ....... ******** . ..******** ......... .* ............ . . . .... . ...... ******* ..********* ......... ...... ... . ... ...*..... ********.... ******* * ..........*....... ********* **..... ********..... ********* * .... .. ... . ** *********** ***************** .....********* ..... .... . *. **** ************** ***************** .....********* * ....... . .. ********* ******************************** .... ******** ......... . ******** ****************************** * ... ******** ........ ********* **************************** * . ..******** ....... *********** **************************** . ....***** * ....... . ************ **************************** .......******* ........ ************** ************** ************** .....* ****** * ....... *************** ** * ** ** * ************ .. ...****** * ...... ************ ** * * ************** ... ****** . .... *********** * * * ************ .. ****** ..... . ********** .... * ******* . ...**** ..... ******** * step: 636 cells: 42680 burden: 442 living: 1232
Each character symbolises a ‘cell’. You can select and edit them.
See World map interaction.
The bottom line displays some infos as text. You can configure
what infos will be displayed. Select the bottom line to do so.
See Display menu.
This display type gives you real time statistic informations using textual
representation and different kinds of quite primitive ASCII graphs.
It might need some time to get used to.
As primitive and simple the display might appear, it is surprising how
much detail information about the evolutionary process you can grasp from it,
once you got used to it...
e e e xx AAAAAAAAA A A AAAAAAAAAAA AAA A eAAAAAAAAAAAAAAAAAAAAAAAA xx xxxAAAAAxAxA xxxxxx AAAAAAAx AAAAAx x eexxxxeeeeeeexxxeeeeexxxxeeeeeexxxxeeeeexxxxeeeeeexxxxeeeeexxxxeeee xxx AAAA e ave energy x var living A ave organ-A * ** * * ** **** ** ** *** ***** ** ** ************* ** *** ************* ***********************.... . -380 scanning: energy vertical range: 72 1433 * * * **** ****** ** ******* . . ......***************...... . . . -395 scanning: organ-A -<zooming>| vertical range: 117 190 food min: 0 max: 1254 average: 259 step: 73 cells: 9479 living: 825 +burden: 41
See Brew main screen, common main screen capabilities.
See Step display interaction, to see what else you can do here.
See Display menu, for configuring display.
Brew has its own form of user interface. It's a kind of active text.
These text menus give you informations about current settings and at the same time they do let you change them. Furthermore it's also the interface to the built in online help system (see Online help).
You SELECT things on the screen by moving the cursor to it and press <RET>. This will SWITCH options, lets you CHANGE VALUES or takes you to SUB-MENUS. If the cursor is on a menu item that expects a numeric or a string value, you can just enter a new value without the need to press RET first.
If you select the menu title or press ? you can read the documentation about the menu.
Most menus also have key bindings, which are more convenient once you get used to them. (see Key bindings). Press k for key bindings.
To leave a menu press q.
As menus do nest, this will usually bring you back to the prior menu.
(Pressing q repeatedly will always bring you back to the main screen).
? gives context sensitive documentation.
Many brew menus have some built in 'intelligence'. Don't be surprised if things appear or disappear depending on your selections. Brew tries to present you only the information and selection possibilities relevant to a given situation. Sometimes menus give hints or warnings, or even reset your input (if you try to set something to an impossible value).
BTW: As I use the same menu system for some music applications the menu system can also take input from MIDI. This is not active in brew though.
Select actions of the function keys: F1 does: menus-menu shift-F1 does: noop F2 does: toggle-display-&-go shift-F2 does: noop F3 does: spot-scan-menu shift-F3 does: noop F4 does: nuc-scan-menu shift-F4 does: noop F5 does: noop shift-F5 does: noop F6 does: noop shift-F6 does: noop F7 does: noop shift-F7 does: noop F8 does: noop shift-F8 does: noop F9 does: do-FORTH F10 does: noop F11 does: toggle-anything F12 does: goodbye Select with <TAB>, cursor arrows and <RETURN>, leave with 'q' (or empty spot) (Often there are also key bindings to the first letter of a word. Press 'k')
This menu let's you configure function keys.
You can see it when you press K in brews main screen.
It's given as an example how a brew menu might look and work.
The first line is the menu title. It's coloured in brew.
Selecting it (or pressing ?) shows the documentation.
At the bottom you might see a few (coloured) lines giving you hints about the current menu and its usage. Selecting one of these lines ports you to menu usage documentation.
You can select items (including title and bottom lines) either by moving cursor and pressing <<RET>>, or by using key bindings (see Moving and selecting).
The following nodes show you how it might look when you try to see key bindings or actually configure the action of a function key.
Active keybindings: default: noop EXIT MENU ! do-FORTH ' describe-action-at-cursor 1 function-key-actions F1-xt choose from list and store 2 function-key-actions F2-xt choose from list and store 3 function-key-actions F3-xt choose from list and store 4 function-key-actions F4-xt choose from list and store 5 function-key-actions F5-xt choose from list and store 6 function-key-actions F6-xt choose from list and store 7 function-key-actions F7-xt choose from list and store 8 function-key-actions F8-xt choose from list and store 9 function-key-actions F9-xt choose from list and store ? context-help ` toggle-highlite-active k show-key-bindings q quit-menu EXIT MENU (all)
Brew tries to figure out what pressing a key would do in the current menu and to tell you in a somehow understandable language. Hope you can understand from the above that pressing 5 will let you configure function key <<F5>>, by letting you choose from a list of possible actions. The default entry shows what all the other keys would do (nothing but leave the menu, in this case). You can see common key bindings too (see Key bindings).
The default action shown in the title is the action of all undefined keys.
Select action for this function key noop show-key-bindings |feed-world| nuc-scan-menu spot-scan-menu menu-step-display menu-nuc-subsets menu-select-nucs menu-current-genomes food-menu menu-population-control diversification-menu color-menu mutation-menu big-bang-menu world-menu actual-pool-menu gene-pool-menu individuals-menu toggle-display-&-go Select with <TAB>, cursor arrows and <RETURN>, leave with 'q' (or empty spot) This menu is a scrolling one. <PageUp> <PageDown> <home> <end> <arrows>
Please note what the last line tells you here:
You do not see all the possible selections. The menu can scroll.
See Scrolling menus.
To select a menu item move cursor on it and press <<RET>>.
Move cursor with cursor arrays or jump to next selectable field with
<<TAB>>.
To leave a menu press q.
Most menus can also be left by selecting an empty spot or pressing an
undefined key.
In many cases the use of key bindings is a much more convenient way to work with brew. See next node.
Most brew menus have key bindings. Key bindings are very convenient if you get used to them. You can look them up in the manual for the different menus, or just try the first letter of a word. 'Dangerous' functions normally do not have key bindings, so you might just try.
Pressing k calls a function that tries to guess what the Forth code bound to a key might do. Brew tries to give you a understandable description what will happen when you press certain keys, but sometimes you might not be able to understand what it tries to tell you ;-)
There are a few common keybindings active in most menus:
Other frequently used key bindings:
The menu system has built in online help capabilities.
Not only that the menu text may give you informations on the meaning of the displayed settings, suggest things to do next or warn you from possible problems with the settings you required or display menu items to explicitly select help, but there is more under the hoods:
Some menus use colours to attract your attention.
These colours are configurable, of course.
You selected some value and are given the possibility to give a new one. In the current menu version you don't even have to press <<RET>>, just move the cursor on the menu item and enter the new value.
Why even talk about something so simple?
Well below the simple looking interface there is the whole power of the
Forth interpreter. So if you know some Forth you can use it here to
compute your input, get informations or whatever. The old value is on
stack and the value on top of stack will get stored to the right address
when you will press <<RET>>. The same applies for float values
(see Float input). Of course you must use float operators on them.
Example:
Let's say you selected 'organ-A' in the nuc menu to change its value.
You can say things like 2* organ-B @ +
if this seems to make sense in
the given context to set the new value. As many Forth's offer a history
functionality you might be able to get this input back when needed again,
most likely by pressing the cursor-up-key. This can be very convenient.
If you don't understand what I'm talking about here, just forget it.
Make your input the way you are used to.
Brew will understand you anyway ;-)
As not everybody is used to Forth float syntax brew tries to convert numeric strings to valid Forth float input where appropriate. So you can input strings like ‘10’, ‘2.5’, ‘-3.14159265’ and brew will try its best to guess what you actually meant to say...
Please note that this has its limitations:
As on integer input you can use the whole power of the Forth text interpreter on numeric float input (see Numeric input), and you don't have to press <<RET>> before entering numeric values any more.
At some places brew asks you to input numeric fractions. As with numeric input (see Numeric input) the whole power of the Forth command line hides behind the simple looking interface.
But brew does some more behind your back here. In certain cases it has the impudence to change your input, thinking that it knows better what you want then you did say it ;-)
I know that this is dangerous, but I like the results. Please tell me if you don't! Anyway, if you start your input with any of the characters ‘%’ ‘!’ ‘"’ or ‘'’ brew will not try to be clever.
Some examples:
Fraction before: | Input: | Result: | Comment:
|
1/2 | 0 | 0/1 | setting to zero
|
1/2 | 2* | 2/2 | multiply
|
1/2 | 2 * | 2/2 | multiply
|
1/2 | 2/ | 1/4 | divide
|
1/2 | 2 / | 1/4 | divide
|
1/2 | 2 7 | 2/7 | numeric normal
|
1/2 | 3/7 | 3/7 | numeric
|
1/2 | 4 / 7 | 4/7 | numeric
|
1/2 | % 2* | 1/4 | escaping
|
In many places you can select actions from a list.
Examples are setting display function or genome of a cell,
or determining function of 'look-at'.
The menu entry might look similar to the following line:
<look-at> function: show-genome-b
If you select the left half you will see a list of functions to choose from.
The menu title will give you a short description of what the selected item
will be used for. You can use the first letter of a item as key binding to
select the item (see Key bindings), at least if only one item starts with
that letter. Otherwise the last displayed item starting with that letter will
be selected.
Selecting the right entry you will see the *definition* of the selected item.
Sometimes there is an item (none)
(sometimes noop
) in the list of
selectable items. If you select it it means no selection.
Depending on the number of items you might not see all of them on a screen.
See Scrolling menus.
There's an advanced feature on key ':
On rare occasions you might want to select a word which is not included in the list. Press ', and write Forth code returning the execution token of the function you want (the xt must correspond to a *named* word). Please do not use this feature unless you know exactly, what you are doing. Note that here your input will *not* get recorded directly, so take care of that yourself, if you want.
The word will further get added to the list to make it convenient, if you want to re-select it later on.
Brew tries to make a menu fit on a screen, but sometimes this is just not possible. Imagine selecting from a list of items like functions or files, where you can not know how many lines there will be when the user invokes the menu. Brew solves the dilemma by making the region of the screen where the list get's displayed scrollable. So in a scrollable menu there will always only a part of the screen do scrolling (at least the title line will not).
If there is space to display a menu help line at screen bottom (and brew takes precautions to make that line available whenever possible) brew will tell you when a menu is a scrolling one and therefore not displaying all available choices by displaying the following line
This menu is a scrolling one. <PageUp> <PageDown> <home> <end> <arrows>
So you have the following special key bindings active to make the scrolling area (and only this one) of the menu scroll:
If you know Forth you might want to use its power inside a menu.
The key ! will give you the possibility to enter Forth words.
Your input will be interpreted when you press <<RET>> and brew
will wait until you press another key.
If you want to make more Forth input before returning to the menu,
press <<SPACE>>.
Please note that this is the exception of the rule that the effect of
any input that could possibly change something on brews state is
automatically reproduced by playing back the record file, as long as
recording was switched on while you did it. This version of brew does
not care at all about your Forth input regarding recording here.
Brew has an interface to port you to the relevant documentation node. You reach it by pressing ?, by selecting a menu title, or in default configuration by pressing <<F1>>.
Brew uses an extern reader to do this, so of course all key bindings are different while reading documentation.
Brew can use either the ‘info’ reader (preferred) or a text mode html browser (like ‘lynx’) to display the documentation. Make sure you have installed it. For html you have to produce or to download the html file separately.
See System menu, to switch between these documentation types, or to see the strings passed to the OS in case of problems. You will find hints how to change the default by selecting ‘reader’.
Brews main screen is the place to do things like start or stop the evolutionary process and watch things going. You decide what informations you are currently interested in and watch them evolving at real time. It can display different informations in very different ways. See Display menu, for configuring what to display.
The effect in terms of cells being generated and tested, genes getting mutated and optimised, will be the same (if you start from the very same conditions), but will look very different depending on the display mode brew is in.
Look at two examples how brew could look in spot and step display:
See Example world mode display, petri shell look world map.
See Example step display, real time statistics display.
See Display menu, choose what you want to see while brewing.
Pressing D or selecting the info line (last line of the screen)
ports you to ‘Display menu’ where you can configure display including
info line.
Depending on the display mode you have additional menu interfaces:
From brews main screen you reach many important other menu screens with capital letter key bindings. See Key bindings.
Brews menu list is on keys B and m.
See Menus menu.
...and then, ? goes to context sensitive documentation, as usual...
(and d has some demos).
Brew displays world maps when its main screen is in world mode, but also to show you special informations coded as colours. Foreground colour show nuc informations, background colours visualise spot data.
See Example world mode display, to see how it might look.
In a world map you can select individual cells or spots to examine and edit them:
See Nuc menu, if you press <<RETURN>> on a cell.
See Edit spot menu, if you select an empty spot.
Special key bindings:
Of course you have all the additional capabilities of brews main screen menu interface at your disposal if you see the world map in brews main screen.
In other maps you might find other menu interfaces too, press k to check for key bindings or <<TAB>> to locate additional selectable items.
When you have examined a nuc (see World map interaction) or selected an individual (see Individuals menu) brew will display ‘Clone nuc by selecting an empty spot’ on the info line. (This stays as long as brew thinks to know which nuc you are interested in).
While brew is in that mode you can set a clone of the nuc by moving to an empty spot and pressing <<RETURN>>. Of course you can select the clone and edit it, if you want. (In this case the edited version would be cloned if you select another empty spot).
You can even change to another world (see World list menu) and set clones of the selected nucs there.
See Example step display, to see how it might look.
Selecting the status line of a display item let's you choose the variable that gets displayed. You can only select variables of the same type.
In a scan display you can switch between automatic zooming or a fixed range display (see ASCII bar graphics).
If you select a column in a scan display you get access to information
about nucs or spots inside the value range of the selected bar. Brew
puts you into a ‘menu nuc subsets’ or a ‘menu spot subsets’
with conditions set for the value range and the variable in question.
From there you can look at the nucs, scan or even change them.
You can define a range of columns by pressing * on the range
borders inside a scan bar graphic. When the range is displayed press
<<RETURN>> to go to the corresponding subset menu.
See Menu nuc subsets.
Press D to do other configurations or select the ‘info line’. See Display menu.
If you press D in brews main screen you come to the Display menu.
Here you can configure what information brew should display while brewing.
Normally you will have either spot display or step (statistics) display on.
Toggle between the two by selecting ‘step OR spot’ or by pressing o,
as you would do in main screen.
Displaying information in real time is nice to watch but costs time, of course. So brew can be told to display the information you are interested in only all (say) 128 steps, which I call ‘snapshots’, or switch display off completely. Key t toggles between real time and snapshots display, like it does in main screen. Brew distinguishes between ‘step-snapshots’ and ‘spot-snapshots’ and offers you to choose between possible frequencies for the snapshots. The selected number is marked with ‘*’ on both sides.
Display menu let's you configure (only) the type of display switched on.
So switch it on in order to see the options. (Even the D key binding
will port you directly to step display configuration if brew is showing
step statistics).
If you insist on it, brew lets you even switch on both at the same time. It only makes sense on very rare occasions, and you will get a headache from it anyway...
While in real life we might have the impression of time moving continuously in one direction and myriads of different things seem to happen at the very same time, brew has a different concept of time.
If brew is displaying a map of its virtual world it renews its display char by char for each spot it is working on. This display mode is called ‘Spot display’. Additional information about the cell can be coded in the char displayed and its color while information about the spot can be given by background color. (As colouring is slow, it's off by default).
If brew is displaying statistical information it runs the whole world through one step, computes the information in question and displays it. This display mode is called ‘Step display’. The informations can be shown in different ways like simple ASCII graphs, ASCII bar graphs or as text and numbers, possibly all at the same time in different regions of the screen.
If spot display is switched on display menu lets you configure some spot display settings:
In spot display each cell shows up as a char. This char gives some information about the cell. The function what information gets coded in the char can be set individually in the nuc (see Nuc menu).
The simplest function always displays a fixed char, so this cell (and its offspring) would always show up as a 'X' or something. Other functions determine the char based on the state of inner variables, age, energy, generation, genome or such.
Usually you will want to set it to a special function called ‘<look-at>’ which can be switched to all the others at run time. So you can switch all the cells that have ‘<look-at>’ as their ‘show-me’ function to show their age or whatever you like at runtime. This can be done using key bindings (see Key bindings) from See Brew main screen, or from display menu See Configuring spot display.
(BTW: If you select the function from spot display you get the possibility to have a look at its definition. (see Selecting functions).)
You can choose among the following functions:
Configuring step display is more complex than spot display, so it has its own menu page. You will reach this page from display menu, or if step display (only) is on, from brew main screen by pressing D. Step display is always done after running the whole world through one time step. It displays some statistics in real time about the evolutionary step that just happened while brewing.
The different kinds of statistical data representations can be combined at the same time each one in his own screen area.
As primitive as these display types are, it's surprising how much information about the evolutionary process you can get if you watch them at real time and if you know what to look for ;-)
x x x x xx xx x xx x x x x x x xx xxx xx x x x x x x x x x x x x x x xxxx xxxx xxxxx xxxxx xx x x x x x xx xxx x $$$$$$$$$$$$$$$$$$ x $$$$$$$$$$$$$$$$$$ x $$$$$$$$$$$$$$$$$ x $$$$$$$$$$$$$$ $$$$$ $ var nuc-do-cost x var living
This type of graph is drawn continuously from left to right, one column
a step. I call this type ‘continuous display’.
The last line gives you the meaning of the used characters:
$ means how energy much a cell looses for each life step.
x shows how many 'cells' where living last step.
You can see population control at work in this example:
Population increases rapidly at the beginning until population control raises life costs. Then population size starts to oscillate (and would probably stabilise more or less after a short time).
Automatic zooming when the range is too small is indicated by colouring the char in question different than usual. Number and type of displayed variables, zoom factor, chars, colors and ranges are all configurable of course.
This type of statistical display can deal with a number of variables, but also with minimal, maximal and average values of variable groups in nucs or spots, or display the size of the current range of them.
You can track as many variables as you want in this graph at the same time, but you can only have *one* continuous display screen region.
This type of display shows distribution of variable or function values in a simple ASCII bar graph. The following example shows distribution of genome generations, that is for how many generations the genome has survived since last mutation:
* * * * * * * * * ** * * *** * ** ***** ** *** ******* * **** **** ********* *.. ..*.......*******. ...***** **********.. 0 scanning: genome-generation vertical range: 86 267
The name of the variable scanned is shown together with vertical and horizontal ranges in the last line.
Here genome-generation
gets scanned, horizontal range goes from
0 (left) to 267 (right) and vertical range is from zero to 86. Ranges
get zoomed in automatically if values fall out of displayed range. The
user get's notified in the middle of the bottom line if horizontal or
vertical zooming happens. Automatic zooming can be switched off, see below.
This type of display is used both when scanning variables from a menu or as real time display while brewing, when step display is on. In the latter case it is redrawn completely after each step, and you can display as many bar graphs on the screen as you want, but of course they will get too small if you define too many of them.
The menu interaction is very similar in both cases:
If you select a column in a scan display you get access to information about nucs or spots inside the value range of the selected bar. (You can define a range of columns by pressing * on the range borders inside a scan bar graphic. When the range is displayed press <<RETURN>> to go to the corresponding subset menu). Brew puts you into a ‘Menu nuc subsets’ or ‘Menu spot subsets’ respectively with conditions set for the value range and the variable in question. From here you can look at the nucs or spots, scan or even change them.
See Menu nuc subsets. While you have all the possibilities of the subset menus please note that your settings of conditions or actions are volatile and will disappear once you leave the menu (while they are persistent if you enter a subset menu the ordinary way).
The bottom line of a scan display can be used to switch between automatic zooming of the horizontal display range and fixed display range. Automatic zooming is practical but can make you quite nervous when you watch it in real time. Toggle between the two modes by selecting the center region of the line, where brew shows you when zooming happens. If brew displays a fixed range of a scan the border slices gather all values that are below or above displayed range. Set border values at left or right end. This implies automatically switching to fixed range display. Select ‘<fixed>’ in the middle of the status line to switch back to zoom mode.
You can also select the variable in question from the status line.
Text display shows minimal, average and maximal values of nuc or spot variables. Each variable is shown in one text line and updated in real time after each time step. You don't see much details, but then it uses only one line of screen area. So you can display at least some information about a few variables without using up much display space.
In the following example you see two nuc variables code-cost
,
energy
and one spot variable food
:
code-cost min: 400 max: 3799 average: 994 energy min: 500 max: 1328 average: 724 food min: 0 max: 1468 average: 233
Number and type of displayed variables is run time configurable like always.
You can combine above display types each one taking his own screen area.
This node assumes you know about the different types.
(see ASCII graphs see ASCII bar graphics see Text display)
You can have *one* continuous display (displaying several variables) and
as many scan displays (bar graphs) and text display lines as you want.
For technical reasons brew distinguishes between nuc-scan-display
or nuc-scan-func-dspl
and spot-scan-display
and between
nuc-text-display
and world-text-display
. Configuration
is the same though.
Continuous display configuration is more complex and has its own sub menu see Menu continuous display.
Step display menu lets you configure how many items of what kind you want to be displayed (continuous display counting as one) and how many lines of the screen each item should occupy.
The easiest way to add or remove an item is to select ‘add new item’ or ‘remove last item’. You will be guided through the configuration.
An entry for a displayed item might look like this:
nuc-scan-display scanning: energy lines: 12 v-range: 205
• The first item indicates the type of statistical display:
Name: | class: | type:
|
nuc-scan-display | nuc | value distribution bar graph
|
nuc-scan-func-dspl | nuc | function value bar graph
|
spot-scan-display | world | value distribution bar graph
|
nuc-text-display | nuc | minimum, maximum, average as text
|
world-text-display | world | minimum, maximum, average as text
|
continuous-display | both | value graph
|
• The second item is the variable (or function) name
• ‘lines’ configures how many screen lines this display item will take up.
• ‘v-range’ is the vertical range. No need to initialise it normally. Brew will take care about.
With o or by selecting ‘More infos’/‘Less infos’ respectively
you can toggle step display menu between two modes showing more or less infos.
While in the first mode an item occupies one line in the menu it occupies
up to three lines if more (less frequently used) info get's displayed:
nuc-scan-display scanning: energy lines: 12 v-range: 205 nuc-scan-display scanning: energy lines: 12 v-range: 205 zoom starts horiz: 1/5 vertic: 1/4 bg color: blue fg: default-color
Statistical bar graph display does automatic zooming:
If values fall outside displayed range horizontal or vertical scale will
be adapted to let all values fall inside. If too little of a range is
occupied brew will zoom up. The horizontal and vertical zoom start values
indicate how much of a range must be used (see Scale input). So if you
set horizontal zoom start value to 1/6 and the values would use less than
that amount of screen width brew zooms up to fill the screen. Zooming is
indicated in the bottom line like this:
500 scanning: energy -<zooming>| vertical range: 52 1366
The '-' and '|' left and right the word '<zooming>' indicate horizontal and vertical zooming. So in this example both took place.
• The third line defines background and foreground colors.
Configuring text display items is trivial, so its not covered here.
Configuring continuous display is done in its own sub menu.
See Menu continuous display.
If you see a green text similar to this one:
fill the screen (7 lines unused).
you can select it (or press f) to adapt item sizes to use the whole screen, or set the individual step display item sizes manually.
‘presets’ See Step display presets, for often used templates.
This menu configures so called ‘continuous display’.
This type of simple graph displays a coloured char for a certain value
after each time step. Let's say it would display average energy of all
living nucs. Then it would draw a char (let's say 'e') after each step
which would be higher up on the screen when more cells are living.
Please have a look at the example before reading this node
(see ASCII graphs).
The menu might look similar to this:
Setup continuous display: nuc-average energy * red low: 98 high: 160 nuc-max energy + red low: 0 high: 7006 get-variable living x white low: 0 high: 1920 spot-range A-quality A green low: 0 high: 1000 add new entry Zoom up scale: 2/1
Probably you can guess what this would do:
A-quality
over all spots
of the current world.You can select the type of the displayed value from the following list:
name: | kind: | value:
|
(none) | – | no selection
|
get-variable | various | variable value (see below)
|
nuc-min | nuc | minimum
|
nuc-max | nuc | maximum
|
nuc-range | nuc | range
|
nuc-average | nuc | average
|
spot-min | spot | minimum
|
spot-max | spot | maximum
|
spot-range | spot | range
|
spot-average | spot | average
|
Type ‘get-variable’ displays the value of a single global variable,
while the others display functions like average or range of groups of
variables of all living cells (nucs) or of all spots.
The single variables that ‘get-variable’ can treat are:
living how many cells currently alive newborn how many cells created in this step cloned cloned cells since start of evolution died how many cells died this step nuc-do-cost energy cost of one life step code-price energy cost of one code length unit selected number of selected cells
Defining char and color is trivial.
‘low’ and ‘high’ defines the display range. No need to initialise them normally. Brew will take care about.
‘Zoom up scale’ sets the zooming scale applied when a value falls out of range (see Scale input). Note that continuous display can only zoom up, but not in the other direction. It cannot know in advance how much or how little the value in question will change during next steps. So it just adapts scale such that the value does fall into display range, without resetting it later on. Of course you can always do that yourself by hand setting ‘low’ and ‘high’.
Use ‘add new entry’ to add a new entry.
Planed to give some often used display configurations.
Regardless whether you have step or spot display on you can display some values on the bottom line of brew main display. The bottom line is divided in a number of ‘display-slots’. So if you have five slots you can display up to five values.
Configurating info line is trivial:
1) Select number of slots first (you can change it later on).
2) Select the information you want for each slot from the following list:
noop no selection, nothing displayed .step display step number .cells display how many cells created since start of time .burden how much energy is needed for one life step .code-price energy price for a code length unit .living number of currently alive individuals .selected number of selected individuals .newborn newly born cells this step .died died cells this step .trial number of cells with genomes currently on trial .mutations number of mutations this step .compiled-genes successful genes compiled since start of time .mutation-max-items maximal ever generated code length .age-threshold maximal possible age (not very useful normally). .scoring show scoring (no taxes) of best scored individual. .score show best score after paying taxes. .hits count individuals that get scoring 0 (assuming scoring 0 means problem solved, somehow).
‘messages’
Sometimes brew uses the bottom line to give you messages it considers
important. These messages will override your settings for a number of
steps. They can be about memory shortage, population emergencies,
extremely long genes (which very likely are a consequence of unbalanced
gene pools) and such.
Brews world display can give more information by using colors.
So the color of the char symbolising a cell could code its age
while background color could show how much food is on this spot.
These things are configured in the color menu, which you reach
from brews main screen by pressing C.
Please note that spot display has to be on for this, for step display you can only switch colors on and off here. Other step display color settings are done where step display items are configured.
Nuc related data is always mapped to *foreground* colors, while spot related information will influence *background* color. It's quite logical, if you think about it for a moment.
Color menu starts with a row of color samples. If you select them, the
colors name gets displayed, which can help recognising them elsewhere.
Switching foreground and background colouring is done by selecting the corresponding entries, or (more convenient) by pressing f or b respectively. Please note that these key bindings are the same as in brews main screen.
Pressing capital F or B lets you select the function to code information to colors. As usual you can also have a look at the definition of the functions to choose (see Selecting functions).
Foreground colors can be set by the following nuc dependent functions:
black you won't see black on black ;-) red just fixed colors green brown blue magenta cyan white default-color white as foreground, black as background condition>fg-colour conditional colouring (see Conditional colouring). selected>fg-color selected cells get coloured age>color mapping age to color generation>color mapping generation to color genome>color genome determines color genome-generation>color generation of genome determines color code>color color shows code length scoring>color color coded raw scoring results score>color score respecting code length penalty trial>color cells on trial phase are shown coloured (see Trial phase). nuc-all-real>color color nucs with real floating point values only nuc-has-unreal>color color nucs with unreal floats (infinities, nan's) nuc-inf?>color color nucs with infinities of both signs nuc-neg-inf?>color color nucs with negative infinities nuc+inf?>color color nucs with positive infinities nuc-nan?>color color nucs with nan's
Background colors can be set by the following spot dependent functions:
black don't choose black on black ;-) red just fixed colors green brown blue magenta cyan white default-color black as background, white as foreground condition>bg-colour conditional colouring (see Conditional colouring). selected>bg-color EXCEPTION: selected NUC colors background scoring-hit>bg-color EXCEPTION: a NUC scoring zero colors background fcp>color watch memory allocation of the OS food>color show food color map A-quality>color and for all other spot qualities A-property>color same for all spot properties A-secret>color and for all spot secrets, if any spot-all-real>color colour spots without unreal float values spot-has-unreal>color colour spots having unreal float values spot-inf?>color colour spots with infinities of both signs spot-neg-inf?>color colour spots with negative infinities spot+inf?>color colour spots with positive infinities spot-nan?>color colour spots with NANs
In all cases where a value range should be mapped to colors we need a
scale to do the mapping. If the range of values is too big, the colors
will just wrap. So the same color does not necessarily mean a similar
value. You can set the different scales by hand, or select the menu
entries that try to set the scale such that either the whole color
range gets used, just the half range gets used, or only two colors.
The first case is good if the range is likely to stay equal or will
probably shrink. The other cases are for situations where the value
range is likely to grow some or grow much. Adapt color scales from
time to time (if you use them) not to get fooled by excessive color
wrapping.
Some useful key bindings in color menu:
See Scrolling menus.
Brew comes with pre-defined functions to code informations by colours. Sometimes you might want to define your own conditions. From ‘Color menu’ select ‘condition>fg-colour’ for nuc variables, respectively ‘condition>bg-colour’ for spot variables and then ‘EDIT’ to go to ‘Conditional colouring menu’.
See Extended conditions, to learn how to set up colour conditions.
You can also set colour conditions from ‘world maps’ by pressing c. Brew sets up colouring like it is used in the current map if you do so. (see World map interaction).
Brews super menu is just a list of all globally accessible menus.
You get there by pressing B or m from the main screen.
It's an interface meant for browsing all the options or when you don't know the key binding to go to a certain menu directly. I advice you strongly to get used to the key bindings though, as they are much more convenient. All menus have upper case key bindings in brews main screen. There are a few lower case ‘shortcut’ key bindings too, but there is always an uppercase binding, anyway.
Note that there are menus which you can not access directly neither from brews main screen nor from here. These menus deal with a individual instance of a group of things like spots, nucs, genomes and such. Brew can not know which instance you want to work on. You have to select it first in another place. Please read See Using menus.
You reach the individuals menu by pressing I from brews main screen.
This menu lets you select from a list of predefined individuals.
You can edit the selected individual as you wish and set it somewhere in your brew universe. This menu has its main function when you set up a new evolution. You can add new individuals to a biotope later on of course, if you decide to do so. (You might be surprised how difficult it is to do so successfully, when the other cells are already somehow optimised to the given conditions though).
Press i to select an individual from the list.
Press e to examine and edit it as you like.
If you return to the main screen now you can set clones of this individual by pressing <<RET>> on a spot. Brew displays ‘Clone nuc by selecting an empty spot’ at the bottom line to let you know. You could edit each clone again, of course. This possibility is lost as soon brew gets confused which individual you might mean. Just select and edit it again to continue then.
If you want to randomly sow a number of clones use the function presented in the menu (c). There is a variant which diversifies diversificable nuc variables of each sown clone (d), making them a bit different, which is usually a good idea to start an evolution. See Diversification menu, to configure variable diversification.
Please note that brew does try but not *insist* to sow as many cells as you tell it to. If a cell falls on a spot that is already occupied it will be lost, like a seed falling on infertile ground.
Of course you can select a first individual, set or sow it, select another one (or edit it differently) and set some more if you want to start with more than one species. Don't forget to make them look different so you can *see* what's happening with them.
This menu screen gives you detailed information about a individual cell
and let's you edit it. You reach this menu by selecting a nuc in brews
world map (world display) or from individuals menu. Editing a nuc changes
only this single cell of course.
Most of the menu items refer to variables local to the nuc. Brew let's you edit all of them (with very few exceptions), even if it thinks it's a bad idea. Changing some variables like the ID of the cell could confuse brew. So brew warns you by ringing the bell when you try to do so, but does not prevent you from doing it (except in some really dangerous cases).
Going through the menu from top to bottom:
cell-division
is implemented, so you don't have much
choice...
The number of nuc variables of each kind is configured at compile time. If there are more than fit on the screen the area where they are displayed will be scrolling (see Scrolling menus).
You will not want to examine or edit a single spot too frequently,
but here is a menu to do it anyway.
You reach this menu from brews main screen by pressing l on an empty spot. (Pressing <<RET>> will have the same effect most of the time). If the spot is occupied by a cell you can get here from the nuc menu by selecting ‘Spot’ therein.
You can see and edit either the different INTEGER or FLOAT spot variables.
See Variable names, for information about the different variable classes.
See Numeric input, how to use Forth power in input.
See Float input, let's you use everydays float syntax on input.
See Scrolling menus, scrolling menus.
This menu let's you see and edit global integer or float variables.
You get here from brews main screen by pressing V.
These variables are the simplest type of environment variables.
Normally you will give the genome read only access to them,
if you use them at all.
You can see and edit either the different INTEGER or FLOAT global variables. Key o toggles as usual.
To set them all to the same value, set the first one and select
‘set them all to this value’.
To configure diversification of global variables use the link to
See Diversification menu.
See Numeric input, how to use Forth power in input.
See Float input, to use everydays float syntax on input.
See Scrolling menus, scrolling menus.
The cells need ‘energy’ to survive and to reproduce.
They get energy by ‘eating’ ‘food’.
Population get's controlled by two means:
This menu is for food supply configuration.
You get here by pressing F in brew main screen.
Food portions are given once a evolutionary time step.
There are different ways to distribute food:
Evolution only will lead to useful results if there is some sort of life stress that controls which genomes will survive and which will not.
This menu let's you configure population control. You get here by pressing P in brews main screen.
This brew version has two different ways of doing it:
Brew stresses its little 'beings' by two means:
This menu is for configuration of automatic adaption of energy costs.
It's a mean automatic stress producer!
Separing costs for gene code length and life steps gives you a convenient way of controlling length of generated code.
Population control menu also deals with population emergencies.
Let me explain some technical terms first:
Configurating possibilities:
This more traditional way of population control works much more simple and much more drastic: The cells get scored after each life step. Only a fixed number of the fittest of them are kept, the others removed. Population is filled up with mutated variations of the elite. Cells are potentially immortal if they manage to stay in the elite.
This menu displays the list of individuals sorted by their score.
You get here from brews main screen by pressing E.
This brew versions only has a very simple informational menu here.
The possibility to see (or edit) each individuals genome is the only additional menu option given. Later brew versions will probably let you do more...
The trick of evolutionary programming is to let the 'children' of a code snippet you want to optimise be variations rather then exact copies of the original. This is not only true for gene code, which would be changed through ‘mutation’, but also for nuc intern (hereditary) variables, which are varied by ‘diversification’.
Later on I have found the diversification mechanism useful not only to optimise inner variable values, but also to set up *input* for some experiments. So I extended the possibilities of diversification on spot variables too.
Sometimes it's unnecessary complicated to have these input variables as local variables (to the spot or nuc), so I introduced a set of global variables, which can get diversified too, for convenience.
‘Diversification menu’ sets up the parameters for diversification.
You reach it by pressing m and then d from brews main screen.
The first line tells you if you are looking at NUC, SPOT or GLOBAL variables diversification. o cycles through them, like usual in such situations.
The mechanism work similar, but not equal:
Let me explain two technical terms which play a role in all cases:
See Scrolling menus.
Here you configure diversification of NUC variables:
Beside normal diversification you can configure rare big deviations too.
Upper screen half is for integer nuc variables, lower for floats.
They work very much alike. Please note that not only the diversified values,
but also the parameters for diversification are integers or floats themselves.
The rest of the menu lets you set the bits for the global diversification
mask for each nuc diversificable variable.
See Variable names, for info on these variables.
Only variables with global *and* individual switch on can get diversified at all.
The configuration of SPOT diversification is very similar to the one for nucs. It has less options though.
Please refer to See NUC diversification, for more infos.
Please don't forget that you must configure much smaller values here for a similar effect due to the differences in the inner working of spot and nuc diversification.
You can restrain spot diversification to inhabited spots. This might be worth considering for speed reasons, spot diversification will be done *very* often if you use it.
This feature is implemented as a convenience to allow an easy set up of some simple experiments.
The configuration of GLOBAL diversification is very similar to the one for nucs or spots.
Please refer to See NUC diversification, for more infos.
Here you configure options for the mutation process.
You reach it from brews main screen by pressing M.
At some places brew uses pools of functions with different relative probabilities to be (randomly) selected. Examples are the different types of mutations or gene pools. These ‘probability lists’ can be nested one into the other.
Example (mutation types):
mutation-types items: 6 Edit relative probabilities. 1000 top-level-insertion 1000 top-level-replacement 3000 snip-types * nested list * 2000 top-level-address-replacemnt 1000 top-level-token-replace 100 restart-from-scratch
The values given in the first column are relative probabilities to get selected by the random selection mechanism. This means that when a mutation type will be used the first two types will have the same relative probability to be chosen, while ‘snip-types’ will be three times as frequent and so on.
Note that ‘snip-types’ will recurse on the nested probability list when taken, to determine the final winner. Nesting levels are not limited.
You change relative probabilities by selecting the entry.
In the case of nested lists you select just like the other entries to determine the relative probability that (any) one entry of the nested list would be chosen. To descend one level and set the relative probabilities *within* the nested pool, select ‘* nested list *’.
The absolute size of the probability values has no influence only the relative size has meaning and only within the current nesting level.
Selecting the name of an item shows you its definition.
Depending the number of items this menu is likely to be a scrolling one (see Scrolling menus).
There are different mutation types (and sub-types).
Here you configure relative probabilities of each type to happen.
This menu let's you choose the gene pool to be used for mutation.
You get here from brews main screen by pressing G.
Currently only ‘gene-primitives’ is selectable.
This menu let's you edit the gene pool used for mutation.
You get here from brews main screen by pressing A.
Currently this is always ‘gene-primitives’.
Change the relative probabilities of the genes to be used by mutation.
See Probability lists.
See Scrolling menus.
This is slightly advanced info which might help you understand some brew internals better. If it confuses you, please skip it.
Brews mutation mechanism generates random Forth program code. It is *not* a requirement on the mutation process that the produced program snippets would do something useful. It is the duty of the evolutionary selection mechanism to take care of usefulness. But there are at least two requirements on the generated gene code that mutation *must* fulfil:
Correct use of the Forth data stack plays an important part in fulfilling these requirements. I'd consider it a possible security risk if the cells could read and write to arbitrary addresses and it would be disastrous regarding stability. So the mutation process *must* know about the type of stack data, at least about addresses. The usual Forth compiler does not do any type checking, assuming that the programmer is clever enough to do it right. Brews mutation process only does some very rudimentary type checking, just enough to assure stable and secure code and leaves the decision if the result does something useful to the evolutionary selection process. Brew knows about very few different types and uses one byte char symbols called ‘stack symbols’ to indicate them:
n
. Cell wide numeric value, not distinguishing between signed
and unsigned. (The technical term cell
is used in the Forth
sense here, indicating a storage unit, frequently 32 bits).
a
. Address that contains a numeric cell wide value as above.
Addresses can be read and written, but never can be the result of
address arithmetic operations. Addresses that are read only are never
passed as stack parameters, but read out immediately by the
corresponding gene primitive.
r
. Floating point value on the floating point stack.
A
. Address of a double-precision IEEE floating point value.
Brew always uses double-precision IEEE floating point format when
storing float values in memory for compatibility reasons.
C
. Flag being true
or false
.
Brew uses a notation for stack types that looks similar to the usual stack effect comments in Forth source code. Please note that there are subtle differences not only in the look (intentionally) but also in the meaning: While Forth stack comments try to convey some type information *and* individuality of the values, brews stack symbols only talk about (very few) basic types.
So Forth would sayswap ( x1 x2 -- x2 x1)
While brew wouldswap ( nn-nn )
or (depending on the types of the stack items) would possibly see it as a
different word likeswap(an) ( an-na)
.
Note that the last example would execute and compile the *same* code,
just a normal swap
. Only mutation would name it differently for
its purposes. This allows you to give other probabilities to the
different variations (or forbid some completely, if you want to),
which has proven to be a very valuable feature.
Note that brews stack symbols are always single letters without spaces in between, and there is one single - char to separate symbols before and after gene execution. This has technical reasons but is convenient, as the slightly different look should remind you of the slightly different meaning.
Mutation can only build genomes based on the so called ‘gene primitives’.
The gene primitives are given together with their stack type symbols here.
See Stack type symbols, for an explanation.
Floating point primitives:
Conditional structures:
Whole tested genomes can be used like new primitives:
+ ( nn-n )
. Addition.
- ( nn-n )
. Subtraction.
negate ( n-n )
. Negate.
* ( nn-n )
. Multiply.
?/ ( nn-n )
. Divide if divisor is not zero, else return zero.
This might look familiar to Forth programmers and very strange to other
readers... ;-)
(Consider learning some Forth basics and return to here later on...)
Forth makes heavy use of the so called ‘data stack’.
Brew uses some (but not all) of the possibilities Forth gives the programmer
to rearrange items on the stack.
There is a conceptional difference of how brew sees stack juggling and how Forth programmer usually do. Let's take a simple example:
swap
. This Forth word swaps the two topmost stack items.
So if you have '1' '2' on the stack before, you'd have '2' '1' after.
A Forth programmer might write this as follows:
swap ( x1 x2 -- x2 x1)
. This is a usual way of writing down
the stack effect of the word swap
that was described above
in plain English. Forth sees everything inside the parenthesis as
a comment, while it symbolises the stack effect for the Forth programmer.
Brews mutation has to know about stack effects of its genes to generate
something stable, secure and sometimes maybe even useful. Mutation does
not care about the actual stack values (the '1' '2' above) though, but
only about the *type* of them. So if you have two integers as x1 and x2
like in the example above brews mutation sees swap ( n1 n2 -- n2 n1)
as a noop regarding stack effect. If one of them is a address instead,
brews mutation mechanism sees that swap
as a completely different word,
even if it will compile the normal Forth word swap
in both cases.
See Stack type symbols.
dup ( n-nn)
. Duplicate the topmost stack item (integer).
dup(a) ( a-aa)
. Duplicate the topmost stack item (address).
This primitive is commented out by default. Uncomment to activate.
2dup ( nn-nnnn)
. Duplicate the topmost pair of stack items
(two integers).2dup(na) ( na-nana)
. Deactivated type variant.2dup(aa) ( aa-aaaa)
. Deactivated type variant.2dup(an) ( an-anan)
. Deactivated type variant.
drop ( n-)
. Forget topmost stack item (integer).drop(a-) ( a-)
. Forget topmost stack item (address).
nip ( nn-n)
. Forget second stack item.nip(aa-a) ( aa-a)
. Forget second stack item.nip(an-n) ( an-n)
. Forget second stack item.nip(na-a) ( na-a)
. Forget second stack item.
tuck ( nn-nnn)
.
Put a copy of the topmost stack item below the second one
(both integers).
tuck(aa-aaa) ( aa-aaa)
. Deactivated type variant.
tuck(na-ana) ( na-ana)
. Deactivated type variant.
tuck(an-nan) ( an-nan)
. Deactivated type variant.
swap ( nn-nn)
. Swap topmost two stack items (both integers).
swap(aa-aa) ( aa-aa)
. Deactivated type variant.
over ( nn-nnn)
. Put a copy of the second stack item over
the (former) topmost one (both integers).
over(an-ana) ( an-ana)
. Put a copy of the second stack item
(address) over the (former) topmost one (integer).
over(na-nan) ( na-nan)
. Deactivated type variant.
over(aa-aaa) ( aa-aaa)
. Deactivated type variant.
To get somehow readable gene code I don't like addresses lying around too
long on the stack, but want them resolved as soon as possible. That's
the main reason why I keep many type variants of the above primitives
deactivated by commenting them out in the source. You can always activate
them (but you might run into troubles with it...). You don't loose
much by leaving them switched off, as there is no address arithmetic
mutation can always get a copy of an address (variable) by choosing
its gene a second time.
As explained elsewhere genes cannot access arbitrary addresses for
security and stability reasons.
See Stack type symbols.
See Genes.
If there *is* an address on the stack you can be sure it is legitimate for the genome to read (and even write) its contents.
@ ( a-n)
. Read contents of address a
.
take ( a-n)
. A variant from the above gene, which I consider
to be interesting as a building block in problem solving. This gene
literally takes the value away from the address, as it reads its
contents and clears the memory location then. (So it's actually
reading *and* writing to the address, which is legitimate).
As explained elsewhere genes cannot access arbitrary addresses for
security and stability reasons.
See Stack type symbols.
See Genes.
If there *is* an address on the stack you can be sure it is legitimate for the genome to (read and) write to this address.
! ( na-)
. Store integer n
at address a
.
-! ( na-)
. Subtract integer n
from the value at address
a
and store the new value at the same address.
swap! ( an-)
. Store integer n
at address a
.!
with the parameters the other way round.
off ( a-)
. Clear memory contents at address a
.
Gene sequences doing things like adding the contents of an address to the same address will provoke integer overflow very quickly. The cells do not have any problems with overflow, they even seem to like it specially... Genomes find out all sort of tricks they can play with overfloating variables. But probably this is not what you want, and it is usually quite difficult to understand what's happening. So you might want to avoid overflow. I don't think there is a simple and clean possibility to do this. The trick used here is more like a quick dirty hack that does some good and does some harm. Just use or leave it as you want ;-)
The trick is to have some words equivalent to !
or +!
that
refuse to write too big values. There is a maximal value, that will not
be exceeded. Up to half that value you get as much as you want, then the
curve increases half as steep (so you still get some more if you ask for
more) until it reaches the maximum, where it stays. This is done by the
word some
.
!(some) ( na-)
.
Store some fraction of n
at address a
.
+!(some) ( na-)
.
Read value at address a
, add some of the value n
and store result as new value at address a
.
-!(some) ( na-)
. Like above, but *subtract* some.
swap!(some) ( an-)
. Like !(some)
, but parameters swapped.
take-some ( a-n)
. Takes some of the value away from address
a
preserving sign of the original value.
These genes access different classes of variables.
See Variable names, for more info.
There are (hereditary) variables of the nuc and (environmental) variables
of the spot. Each kind has a read/write and a read/only variant. In brew
the read/write variant puts its address on the stack, as usual in Forth,
while the read/only variant gives its value. Brew can write read/only
variables of course, only the genes can't. Note that the address of a
read/only variable will never be put on stack during gene execution.
That means that only its current *value* can be known to the cell.
There are other classes of variables (like secrets
) that have
no genes to access them. So the genes have per se no possibility to
access them in any way.
The number of variables of the different classes is configured by compile time options.
organ-A ( -a)
, organ-B ( -a)
, organ-C ( -a)
,
...
These are the read/write nuc intern variables. They pass their
address on the stack granting read/write access.
These variables are hereditary and diversificable.
parameter-A ( -n)
, parameter-B ( -n)
,
parameter-C ( -n)
, ...
Read only nuc intern variables passing their current value on stack.
These variables are hereditary and diversificable.
The genome cannot know their address and therefore cannot
change their value in any way. (Technically speaking they
are just ordinary nuc variables. There are just no genes
that deliver their addresses).
A-quality ( -a)
, B-quality ( -a)
,
C-quality ( -a)
, ...
Read/write spot variables, passing their address on the stack.
A-property ( -n)
, B-property ( -n)
,
C-property ( -n)
, ...
Read/only spot variables passing their current value on the stack.
For many experiments it is not necessary to have nuc or spot local variables. These genes give read access to a group of global integer or float variables.
integer-A@ ( -n)
, integer-B@ ( -n)
,
integer-C@ ( -n)
, ...
dfloat-A-f@ ( -r)
, dfloat-B-f@ ( -r)
, ...
The number of these variables is configured by compile time options.
These genes are for experiments like biological simulations. They give the genome read/only access to some data about themselves like energy level or age. They cannot directly change these data, but they could adapt their behaviour to them i.e. do different things in their youth than when they are old. Like all read/only variable access genes all these genes pass the value on stack, hiding the address where it's stored from the genome.
age ( -n)
.
Gene giving the current age of the individual.
age-threshold ( -n)
.
Maximal possible age.
energy ( -n)
.
Gene giving the cells current energy level.
reproduction-threshold ( -n)
.
How much energy needed for reproduction.
f+ ( rr-r )
. Floating point addition.
f- ( rr-r )
. Floating point subtraction.
f* ( rr-r )
. Floating point multiplication.
f/ ( rr-r )
. Floating point division.
fnegate ( r-r )
. Floating point negation.
fabs ( rr-r )
. Floating point absolute value.
fmax ( rr-r )
. Floating point maximum.
fmin ( rr-r )
. Floating point minimum.
f2* ( r-r )
. Double floating point value.
f2/ ( r-r )
. Divide floating point value by two.
1/f ( r-r )
. Floating point reciprocal.
Aliases of ANS Forth float functions. See ANS Forth documentation.
f** ( rr-r )
.
fsqrt ( r-r )
.
fexp ( r-r )
.
fexpm1 ( r-r )
.
fln ( r-r )
.
flnp1 ( r-r )
.
flog ( r-r )
.
falog ( r-r )
.
Aliases of ANS Forth float functions. See ANS Forth documentation.
fsin ( r-r )
.
fcos ( r-r )
.
fsincos ( r-rr )
.
ftan ( r-r )
.
fasin ( r-r )
.
facos ( r-r )
.
fatan ( r-r )
.
fatan2 ( rr-r )
.
fsinh ( r-r )
.
fcosh ( r-r )
.
ftanh ( r-r )
.
fasinh ( r-r )
.
facosh ( r-r )
.
fatanh ( r-r )
.
pi ( -r )
.
f+i ( rn-r )
.
Add integer value to a float and give result as float.
f-i ( rn-r )
.
Subtract integer value from a float and give result as float.
f*i ( rn-r )
.
Multiply a float value by a integer and give result as float.
f/i ( rn-r )
.
Divide a float value by a integer and give result as float.
i/i ( nn-r )
.
Divide a integer value by another integer and give result as float.
i+f ( nr-r )
.
Add float value to a integer and give result as float.
i-f ( nr-r )
.
Subtract float value from a integer and give result as float.
i*f ( nr-r )
.
Multiply an integer by a float value and give result as float.
i/f ( nr-r )
.
Divide an integer by a float value and give result as float.
f/f ( rr-n )
.
Divide a float by another float and give result as integer.
f*f ( rr-n )
.
Multiply two floats and give result as integer.
i*f>i ( nr-n )
.
Multiply an integer by a float and give result as integer.
i/f>i ( nr-n )
.
Divide an integer by a float and give result as integer.
f>s ( r-n )
. Transform a float to an integer.
s>f ( n-r )
. Transform an integer to a float.
Brew stores all floats as dfloats (double-precision IEEE floating-point format) for compatibility reasons.
df ( A-r )
. Read double-precision IEEE floating-point value.
f-take ( A-r )
. Read double-precision IEEE floating-point value
actually 'taking it away' from the address (storing zero there).
Brew stores all floats as dfloats (double-precision IEEE floating-point format) for compatibility reasons.
df! ( rA- )
. Store float as double-precision IEEE floating-point
value at address A.
df+! ( rA- )
. Add float to the float stored at address A and
store the sum as double-precision IEEE floating-point value at A.
df-! ( rA- )
. Subtract a float from the float stored at address A
and store result as double-precision IEEE floating-point value at A.
fdup ( r-rr )
. Clone topmost float stack item.
fdrop ( r- )
. Forget topmost float stack item.
fswap ( rr-rr )
. Exchange the two topmost float stack items.
fover ( rr-rrr )
. Copy second float stack item to the top.
frot ( rrr-rrr )
. Rotate third float stack item to the top.
drop(float-pointer) ( A- )
. Forget address of float on top
of data stack.
These variables are the floating point versions of nuc and spot variables. See Nuc and spot variables, for more informations. Brew always uses double-precision IEEE floating point format when storing float values in memory for compatibility reasons. Float variables have an additional 'f' or 'df' in their name. Some examples:
f-organ-A ( -A )
. Gives address of first read/write nuc
local floating point variable.
f-parameter-B-f ( -r )
. Gives value of second read only nuc
local floating point variable.
A-f-quality ( -A )
. Gives address of first read/write spot
local floating point variable.
C-f-property ( -r )
. Gives value of third read only spot
local floating point variable.
Gene sequences can contain IF ELSE THEN
structures like other
Forth code conditionally executing alternatives depending on numerical
comparisons and such. Please note that these structures take the form
of [IF] [ELSE] [THEN]
during trial phase, as code is interpreted
(not yet compiled) then. Of course brew takes care about that.
g-IF-ELSE-THEN ( C-)
is a pseudo gen, which is never
executed, but triggers insertion of a IF ELSE THEN
structure.
Setting relative probability of this pseudo gene in a gene pool
therefore influences frequency of IF ELSE THEN
structures
relative to other flag taking genes (like AND
or OR
).
(see Probability lists).
IF ( C-)
, [IF] ( C-)
. Conditional branch.
ELSE
, [ELSE]
. Starts alternative sequence.
THEN
, [THEN]
. Ends conditional structure.
0= ( n-C)
. True if n is zero.
0< ( n-C)
. True if n is below zero.
0> ( n-C)
. True if n is positive and not zero.
= ( nn-C)
. True if the two integers are equal.
> ( nn-C)
. True if the first integer is bigger.
< ( nn-C)
. True if the first integer is smaller.
within ( nnn-C)
. True if the first integer is at least as big
as the second one, but smaller than the third (topmost) one.
AND ( CC-C)
. True if both flags are true.
OR ( CC-C)
. True if at least one flag is true.
XOR ( CC-C)
. True if exactly one flag is true.
f< ( rr-C)
.
f> ( rr-C)
.
f0< ( r-C)
.
f0= ( r-C)
.
Brew can put successfully tested genes into a genome pool.
Switch that on or off in ‘Mutation menu’.
See Mutation menu.
Genome pools serve two distinct purposes:
Brew increases the relative probability of each genome every time
a cell with this genome get's reproduced. So successful genomes
will be used more often than less successful ones. This mechanism
is switched by the same switch as mentioned above.
See Probability lists.
You are presented a somehow formatted output of the genomes Forth code. If you select a sub-gene, you will be put (recursively) in the menu regarding the sub-gene, or presented gene information, if it is a gene primitive.
Selecting the genomes name, or pressing e will write the genome to a file and call and external editor (defined in compile-options.fs) on it. You can change this Forth file as you want to, save it and leave the editor. Brew will check your input and inform you if it finds a problem. Otherwise it will replace the nucs genome with your input and set the nuc on trial. (see Trial phase). All your used Forth words must be defined already as genes. Brew will inform you, if you do use a word that isn't. Have a look at some examples in See Genes files, if you want to define new gene primitives. (You could define genes from the Forth input line, if you want to. see Using Forth in menus).
If you press n in brews main screen you get to a menu displaying information about (all living) nucs. For each nuc variable you will see a line displaying minimal, maximal and average value. (see Scrolling menus). At one given time either integer or floating point variables are displayed. Toggle between them with o as usual, or by selecting the entry in the title line. (BTW: If you select one kind of variables brew will assume that you are interested in this type. So the display of i.e. ‘Nuc menu’ will also switch to the same kind. see Nuc menu).
The same menu get's used to display statistical informations about nuc subsets. The title line indicates what variable type gets displayed and if all nucs or only a subset where scanned.
You see a bunch of lines similar to the following:
generation min: 1417 max: 1483 average: 1455 genome-generation min: 0 max: 1098 average: 347 code-cost min: 100 max: 1699 average: 435 energy min: 403 max: 1105 average: 727
Selecting a ‘min’ ‘max’ or ‘average’ value will port you to
a nuc subset screen of the nucs having the value in question.
See Menu nuc subsets.
Selecting a variable name shows you a more detailed view of the distribution of values of the variable as a simple ASCII bar graph:
* * * * * ** *** * *** * **** ** **** * ** ******* ***** ************* ************* * * *************** * * ** ** *************** ** * ******* ******************** * * ******* * *********************** * *** ************************************ * **** * ************************************* ************ ** * * *****************************************************.****.....*.. *...*. . -129 scanning: energy vertical range: 69 2260
Selecting a bar of this display type will port you to a ‘Menu nuc subsets’ with the value range in question, to do more analysis or so. See Menu nuc subsets.
See Menu step display, for a way to display this type of information in
real time while brewing. You'll find some additional information there too.
If you display floating point variables you will see lines like:
f-organ-A min: 0 max: 3.1415926536 avr: .0436332313 .r..
There are four signs at the right border, either dots or ‘-r+?’, which represent negative infinity, real values, positive infinities and NANs. A dot means that no values of this type exist. The above line says, that f-organ-A of all scanned nucs did contain a real value, no infinities or NANs. Selecting the sign will display counts for each value type, a line for each scanned floating point variable:
Type counts: -infinity: real: +infinity: nan: f-organ-A 0 72 0 0
Selecting a title entry like ‘-infinity’ will port you to a nuc subset menu with nucs that have i.e. negative infinities in any one of their nuc float variables. As an exception ‘real’ chooses nucs that have *only* real float values.
Selecting a number, let's say the +infinity count for f-organ-C goes to
the nuc subsets with f-organ-C being +infinity.
See Menu nuc subsets, See Menu spot subsets, for documentation.
Toggle back with o, or by selecting ‘Type counts’.
If you press w from brews main screen you'll get to a menu displaying statistical data over all spots. The same menu get's used at different locations to display statistics about different spot subsets. (see Scrolling menus).
It works exactly as the corresponding menu for nuc statistics.
See Scanning nucs, for more information.
In many situations you might want to do something with a certain class of nucs or on certain spots only.
Maybe you are especially interested in all nucs having a certain genome. So you'd like to replace their display function to something special so you can watch what's happening with them. Or you'd like to multiply one of the inner variables of all the cells having this genome with a given scale, set a special condition on all the spots inhabited by these cells, remove all other cells or whatever might make sense in the given situation. Brew has functions to do such things. You can do quite fancy things with these functions and of course you can record and replay later on what you did just like about everything in brew. (Just switch recording on before you do it).
As you will see soon, there are menu interfaces on a couple of places to do such things. If you want to work on nucs having a special genome as in the examples above, you'd best use the interface from the menu that deals with (this) genome; if you want to work on cells on a spot where spot variables reflect a special condition, approach from a menu that deals with spots. But you can do much fancier things, if you want to.
So we must configure at least two parts, (and often some more).
TRUE
this action will be taken.
Like with conditions there are simple actions (like: remove this
nuc) and more complex ones that need additional parameters (like:
multiply energy level of these nucs by 5/3). You can enter fancy
actions as Forth source at run time. Whatever you'll do, if
recording is on, it will be recorded of course.
Depending the situation you are prompted for nuc or spot related conditions
and actions, or both:
Extended conditions requiring parameters and a comparison:
Actions to be done on the defined subset:
Generic interface to act on a nuc subset:
Please use these advanced functions with great care.
Brew assumes that you know what you are doing here and does not even try to
prevent you from doing the most stupid possible things with this
feature... So if you tell brew to multiply the action pointer
(xt
) of all nucs genome by say 7/9 it will do it obediently ;-)
Brew does its best in many places to prevent you from doing stupid mistakes, but please don't rely on that. Here it does not do *anything* like that. Did I make that clear?
These conditions do not require any parameters.
These conditions do not require any parameters.
The condition is based on the comparison of two values.
These conditions do require additional parameters and the comparison:
secrets
. You can act like a god in this virtual universe ;-)
All the above functions have a floating point version like ‘df-variable-number’. The following words work on dfloat variables only to test value types:
<
. Do it if first value is smaller.
<=
. Do it if first value is smaller or equal.
>
. Do it if first value is bigger.
>=
. Do it if first value is bigger or equal.
=
. Do it if both values are equal.
<>
. Do it if the values are different.
Please note, that of all the above there are distinct versions for integer and floating point data. (Brew tries to select the right version depending on the situation, but don't rely too much on that).
Please note, that of all the above there are distinct versions for integer and floating point data. (Brew tries to select the right version depending on the situation, but don't rely too much on that).
In addition to the generic actions on nuc and/or spot variables you can program the following nuc specific actions:
I call this mechanism of conditionally executing user defined actions
maybe-do
. The menu interface to set it all up looks slightly
different depending on the situation. In some cases half of the job
is already invisibly done, like setting the condition or action part.
A typical interface might look like this before you define anything:
Setup condition and action first. Simple condition: false What to do: noop
‘Simple condition’ switches between simple and extended conditions.
The rest is trivial, you will find out how it works. After you have done
your configuration it might look similar to this:
DO something on some spots: Please use carefully... Extended condition: 2-variables A-quality B-quality > What to do: scale-variable food with 3/2
Selecting the first line of the example, will actually *do* it now.
This menu is the user interface to use the ‘maybe-do’ functions on nucs. See Configurable actions, for an explanation what it does and how to configure it.
After defining the condition you can display and analyse (scan) all nucs that fulfils it. The title line of the menu gives the count of nucs that meet the condition. If an action is defined, you can execute it on each nuc of the subset.
This menu is the user interface to use the ‘maybe-do’ functions on spots. See Configurable actions, for an explanation what it does and how to configure it.
It works on spots analogous to the ‘Menu nuc subsets’.
See Menu nuc subsets, for more information.
Pressing U (or u as a shortcut) from brews main screen
takes you to the ‘Menu current genomes’. This menu deals with the
genomes of all currently living cells. (see Scrolling menus).
The start of the menu screen might look similar to this:
Menu current genomes. Genomes of living cells: 79 genome-id: genome: count: cost: max generations: 0 * noop 948 100 36 2 g-2 t:61 158 287259 26 3 g-3 314 3199 34 4 g-4 10 500 18 7 g-7 t:2 13 500 18 14 g-14 t:3 11 400 15 16 g-16 13 5198 24 18 g-18 t:5 16 4397 17 19 g-19 t:1 9 1000 22 23 on trial 21 1400 16 [ ... ]
The title line tells you how many different genomes there are currently.
The column titles (with the exception of the one for the genome name) are selectable menu items. If you select them, the display order of the lines belonging to the single genomes is changed to be based on the quality in question. Selecting the item again will switch between ascending and descending sorting. You can also use the key bindings given below.
The column have the following meaning:
Selecting the column title or pressing i or g will set the genome-id to be the key for the order of genome display. Selecting it again will switch between ascending and descending order.
Selecting this columns entry of a genome leads to the menu for this individual genome. See Menu this genome.
on trial
get's displayed instead (see genome #23 above).
If the genome *has* been compiled, but there are still some individuals
left in trial phase from before that their number gets displayed as
t: <number>
after the name (see genome #2 above).
(You cannot order display based on genome names).
Selecting this columns entry of a genome will display the genomes program code.
Selecting this columns entry of a genome will display a world map with the cells having this genome coloured.
Selecting this columns entry of a genome will display a three coloured world map. Cells having the same gene code cost as the genome in question are white, cells with shorter code red and those with longer code are displayed cyan. See Colouring on difference.
Selecting this columns entry of a genome will display a three coloured world map. Cells having the same genome generation cost as displayed in the genome entry in question are white, cells with less genome generations red and those with more genome generations are displayed cyan. See Colouring on difference.
You can look at each listed genome one after the other by pressing one of the following keys:
The ‘current’ line will be indicated by a ‘*’ before genome name, and go down one line after examining the genome.
Brew uses this function to show you all cells which share one special quality. Brew displays a world map and colours the cells in question. Similar maps get used to display spot qualities.
If you don't like the colours change ‘color-selected-fg-xt’ and ‘color-miss-fg-xt’ for foreground colours (showing nucs), respectively ‘color-selected-bg-xt’ and ‘color-miss-bg-xt’ for background colours (showing spots) in my-brew-options.fs.
As an example brew uses it to show you all cells sharing the same genome.
See World map interaction, to learn what else you can do here.
Sometimes brew shows you a three coloured world map to indicate which nucs or spots fall below, inside or above a certain range regarding some quality in question. Falling ‘inside’ a range can also mean equality with a single value. Foreground colours code nuc qualities, background shows the spot like always.
As an example the map could show you all nucs having code cost falling into a given range (which is about the same as having a certain code length) in one color, the shorter ones in another, and the longer ones in a third colour. I call this ‘Colouring on difference’.
The meanings of the (default) colours (on foreground) are:
If you don't like the colours change ‘color-below-fg-xt’, ‘color-selected-fg-xt’ and ‘color-above-fg-xt’ for the foreground colours (showing nucs), respectively ‘color-below-bg-xt’, ‘color-selected-bg-xt’ and ‘color-above-bg-xt’ for the background colours (showing spots) in my-brew-options.fs.
See World map interaction, to learn what else you can do here.
You'll get here normally selecting a entry for a genome from menu ‘Menu current genomes’. (Which you reach by pressing U in brews main screen). You cannot come here from brews main screen or from the super menu, as brew can not know which genome you are interested in.
The menu title shows you the name of the compiled genome (if it is compiled already) and how many cells share this same genome.
This menu deals with the selection status of nucs.
You get here from brews main screen by pressing T.
The title line tells you how many nucs are selected and how many aren't.
Nucs can be ‘selected’, which just means that a special flag is set
within them. As a part of the nuc this flag is hereditary and will not
be reset by brew without that you ask for it. The flag has no meaning
at all for brew, it is a tool for the user to use for whatever he likes.
The feature has similar uses as the ‘maybe-do’ functions (see Configurable actions), but there are some differences:
Menu features:
There are two interfaces to the ‘maybe-do’ feature, one for changing
selections based on a condition, the other to do configurable actions on
all selected nucs (see Configurable actions).
This menu gives informations and interfaces to some world wide settings of the current world. You come here from brew main screen by pressing W.
The menu title line tells you how many dimensions of what size this world has.
Following items are purely informative, you cannot change them:
The next few lines give information about dimensionality and size
of the current world and let you configure visibility ranges for
each dimension. See World size and visibility.
The following three entries let you configure special actions that
might be needed for some sort of experiments:
Some interfaces to other world related functions:
The rest of the world menu let's you define a action to do on spots that
meet a certain condition (‘maybe-do’ feature working on spots). You
must configure the condition which spots will be treated and define the action
to take. Then you can select ‘DO something on some spots’ to trigger
the action. Like always in similar cases you can select amongst simple or
more complex conditions and actions or define your own in Forth program
source. On inhabited spots (only) you can access nuc variables too.
(see Configurable actions).
You get to this menu by pressing O (like ‘Other worlds’) in brews main screen. It is a list of all existing brew worlds. Select a world from the list to enter it.
Brew let's you change world names, and shows you some geometry information for each world.
If you want, you can also create new worlds from this menu.
BTW: As a shortcut in brews main screen you can switch to another world by pressing the number key of the world you want to enter.
This menu let's you define and create another world.
You get here by pressing B+B (capital ‘B’ twice) from brews main screen.
The upper half of the menu screen shows you the settings of the current world, the lower half let's you configure and create another one. After creating a new world the new one will be the current one.
The second half is the main part of the menu, here you define the geometrical structure of your new world and the visibility ranges of each dimension and finally create it. Select ‘Clone geometry’ for same geometric structure as the current world has.
Note that you must configure the settings of the newly created world to be able to do something with it. At least you must set some living cells into it to start a new evolution. (see Individuals menu). Also check visibility ranges in the upper menu half, and configure them as you like.
Brews virtual world can have from one to five (or more) dimensions of any size. Often only a part of the world will be displayed. You can configure visibility range for each dimension. Brew does no zooming in world display, so visibility range in the first two dimensions cannot exceed screen size (minus info line as last screen line), but of course it can be like a visibility window in a bigger plane. Higher dimensions are just projected into the plane taking into account visibility range of all dimensions. So a cell of a four dimensional world at coordinates (a,b,c,d) would be displayed at (a,b) provided all coordinates fall into the visibility range of its dimension.
If you want to display a world of more than two dimensions you can choose to show only one layer or a range of layers one over the other. In the latter case it might be helpful to delay display of each individual layer to have a chance to understand the three dimensional structure while the display is building up. The layers can be transparent or opaque on spots where no cell lives, depending on the background being displayed or not on empty spots. Background will always have to be displayed on the first displayed plane, but can be switched off later. As this sounds all more complicated than it is, there are some examples further down.
For each dimension you have a line like this:
1 dimension spots: 80 visible from: 0 to: 80
The entries have the following meaning:
If you have more than two dimensions you will see the following two entries:
Examples:
Two dimensional world, screen sized on the Linux text console. Fast and everything is visible: (Might be too small for some types of experiments).
Current world spots: 1920 1 dimension spots: 80 visible from: 0 to: 80 2 dimension spots: 24 visible from: 0 to: 24 Delay displaying layers: 0
Tree dimensional world, only middle layer visible:
Current world spots: 19200 1 dimension spots: 80 visible from: 0 to: 80 2 dimension spots: 24 visible from: 0 to: 24 3 dimension spots: 10 visible from: 4 to: 4 backgr.off: 4 Delay displaying layers: 0
Tree dimensional world, all layers visible. Brew displays one layer after
the other, all opaque, and pauses a bit after each layer:
Current world spots: 19200 1 dimension spots: 80 visible from: 0 to: 80 2 dimension spots: 24 visible from: 0 to: 24 3 dimension spots: 10 visible from: 0 to: 10 backgr.off: 10 Delay displaying layers: 1000
Tree dimensional world, all layers visible. Brew displays one layer after
the other, the first one opaque (to hide previous display), all the following
transparent. Pauses a bit after each layer:
Current world spots: 19200 1 dimension spots: 80 visible from: 0 to: 80 2 dimension spots: 24 visible from: 0 to: 24 3 dimension spots: 10 visible from: 0 to: 10 backgr.off: 0 Delay displaying layers: 2000
Here you define the geometry of your new world.
In Linux text console (which is the main platform brew is developed for)
it is a good choice to make worlds two dimensional and 80 * 24 sized, to fit
the screen.
This is the menu for brews system wide settings.
You get there by pressing S in brews main screen.
The identity number displayed in the title line can be helpful to identify output files, as the number get's included in file names.
When brew is started with special options (i.e. ‘COUNTING-WORDS’ see Programming tool files) additional items might show up in system menu.
This menu allows you to switch very detailed what brew should write in its log files and what not. You come to this menu by pressing L in brews main screen.
Brew can write very detailed log files about what it does. Actually this
elaborated logging facility is a by-product of my debugging activities ;-)
Debugging evolutionary programming can be quite a task...
Log files can be an excellent help when you want to understand what actually happens during an evolutionary session. If you want to do fancy things like drawing phylogenetic trees of the generated genomes or such, log files will be a big help. You will probably need to write some perl scripts to be able to process that amount of data though.
Logging slows brew down a lot, of course.
Please realize that brews log files can grow really big; don't forget to switch logging back off and delete the log files after use, or your brand new gigantic hard drive will be full very soon...
I will not explain the format of log files here, as this would take too much room and time. Just put logging on for some time, if you are interested in it. I think you should be able to understand the result.
Most of the menu screen is covered by switches what to put in the log file:
Please note that the following mutation logging switches depend on each other in ascending order. You cannot switch a lower order item off before clearing the higher order switches.
The following options help with debugging:
See Scrolling menus.
Brew can write the produced Forth program code to a file, the so called
‘code file’. Code file have normal Forth syntax and should compile
the defined genome when they are included. Beside the code brew can put
some more information (i.e. stack type comments) in the file. This is
the place to configure that.
You'll get here from brews main screen by pressing first m and then
c.
On a Linux system you can watch mutation and selection at work in real time
by switching to another console and say
tail -f OUTPUT/FORTH/gene-code.fs
.
The menu gives you the following options:
Switches what to put in the code file:
(The first three are compound switches).
You get to the Record and Playback menu by pressing R from brews main screen.
Evolutionary programming can be mean: You set up a new experiment, make
some preliminary tests with a few options and see exciting results within
very short time. Then you try to find even better defaults, only to realize
that the defaults you took have been very, very lucky, but unfortunately you
have forgotten them. If only brew could remember them for you...
Or you have done a lot of configuring and want to do a series of experiments starting from that point, but you don't want to do all this configuring all over again and again...
For such situation brew has a feature to record and playback just about every user interaction possible in brew (It will even catch a lot of things you might have configured using configuration files).
If you want the thing to work it will be enough in most cases just to switch recording on. This must be done *before* you put any cells into the play. Brew will automatically record brews state in the moment you switched recording on, catch and record every change you do to this state and every command you pass to brew.
Brews record files are ordinary Forth source text files which can be edited by hand of course.
Use brews recording feature
When you switch recording on in the ‘Record and Playback menu’ brew saves its current configuration to the record file, including all the settings you changed trough the menu interface or configuration files. It does *not* save the current state of the world and its inhabitants though. If you want to record an evolutionary session you must start with an *empty* world. So brew clears the world when you switch recording on and includes a command to do so in the record file. So if you play back the file later it will start with an empty world too. Note that in both cases all the contents of the current world (prior to switching recording on) are lost.
The menu now looks like this:
After playing back a recorded evolutionary session the record/playback menu gives you the choice to continue recording, appending code to the file. You must do this as the very first action after playback, after the option will vanish from the menu. Brew must know the exact state of everything when recording starts.
Please note, that the evolution may not use *anything* else (like genomes, created other worlds or somesuch) than what was created during the playback of the file in question. So you best restart brew, play back the file and switch to recording, if you want to extend an existing record file.
Brew has some special features to make it comparatively easy to create very complex benchmarks.
Brew now gives you a short information about what it has done, like:
I'm appending the following line to maybe-run-benchmark.fs [DEFINED] my-new-bench [IF] include benchmarks/my-new-bench.fs [THEN] I copy the file to the benchmark directory: benchmarks/my-new-bench.fs
After that you can execute the benchmark from the command line if the Forth
you use has an option to interpret a string on start up. It is enough to
CREATE benchmark-name
as in
gforth -e "CREATE my-new-bench" brew.fs
and brew will start the bench
and terminate when it's finished. So startup time (including brews compilation)
is *included* in the measured time. This is intentional.
Very likely you must edit the benchmark file by hand, i.e. you will probably like to switch display off during the bench. Note that brew has spread comments throughout the file that try to give you hints, where you might want to edit something.
If you want terminal and/or key reaction switched off during the benchmark you must edit early-compile-hook.fs by hand.
Select ‘Playback’ in the ‘Record and Playback menu’.
Choose a playback file.
(If you don't, the default record file name is probed).
That's it...
To interrupt playback just press a key. Brew will ask you if you want to continue (c) or quit (q).
THIS NODE DOES NOT EXIST YET ;-)
So you'd better read compile-options.fs...
Here you configure function key bindings.
You reach this menu by pressing K in brews main screen.
Function keys are active in brews main screen and a few other places.
(Generally activating it could possibly confuse brew in some situations.
If function keys don't work on your system try toggling ‘use-ekey’. This might help.
The menu lets you associate each function key with an action.
Function key bindings are active in this menu, so you can try out the result.
You can select amongst the following functions:
anything
, which you can use
as you like. ‘anything’ is not used by brew itself.
Here you can select a few demos.
As brew currently changes very much there are not too many of them at the time being...
There should be a ‘default’ demo, which explains default brew initialisation of the brew version you are running.
Experiments are a more advanced kind of demos.
Currently there are only some simple test experiments, sorry.
While ordinary demos often lead you through an example evolution ‘experiments’ usually just initialise brew and let you run the evolution on your own. You should have some experience with brew to run an experiment.
Please read the source files in INPUTS/experiments/.../ for information what's going on in the different experiments.
In this brew version experiments are started by including an *initialisation* file from the experiments subdirectory in INPUTS/experiments/. The initialisation file will include source files for the experiment on its own.
See System menu, for how to include files.
sorry... THIS CHAPTER DOES NOT REALLY EXIST YET ;-)
Please read the brew source. There are a lot of comments meant to be helpful. Feel free to ask me questions.
The gene primitives (of the new genes/mutation version) get loaded from brew/INPUTS/genes/.
See Gene primitives, for more informations.
Technically there is a big difference between compile time configuration and run time configuration.
Brew get's compiled each time at startup phase from source. The Forth compiler is very fast, you probably won't even notice the time needed for compilation on todays hardware and Forth systems. So the difference between compile time options and run time options is not so obvious at first glance.
Configuration files listed in their load sequence:
For special cases there is a hook early in the compilation process:
Brew creates some temporary files in its tmp/ directory which defaults to brew/OUTPUT/tmp/.
If you leave brew like intended (see Getting started) it will remove most of them, but there are some exceptions:
makeinfo --html brew.texi
.
texi2dvi brew.texi
.