Skip to content
Clifford Bohm edited this page Jan 24, 2018 · 30 revisions

In the simplest terms, worlds evaluate organisms. Before we get into details, there are is a broad classifications that are useful to understand.

Single vs. Multi Generation

Worlds that evaluate organisms and generate scores (generational worlds)
These worlds evaluate all of the organisms in a single generation. The results of the evaluation are then used by an optimizer to create the next generation. These worlds are easy to work with as an archivst can simply be called between world evaluations.
Worlds with internal organism reproduction
These worlds manage reproduction and death. They may make use of scores (and even optimizers) but may also use other methods to initiate and manage reproduction and mutation. Here are some examples:
  • if an organism has collected a sufficient number of resources they will divide
  • if two organisms co-locate and both have indicated a willingness to mate with some output pattern, an offspring will be generated
  • an organism will have a random probability to die based on age
  • etc.
These worlds are more involved as they will be responsible for managing more data and determining when to call an archivist.

requirments

Worlds expect some number of populations (actually Groups) and that each of these groups have organisms with a certain number of genomes and brains. Worlds also expect that each brain will be able to accept a certain number of inputs and deliver a certain number of outputs. Worlds define these requirements with the requiredGroups() function. If you are using a world all you need to know is that MABE takes care of the details (while MABE is starting up, MABE asks the world for its requirements and then builds the Groups, genomes and brains to suit these requirements). If you are writing a world, you will need to write a requiredGroups() function.

Choosing a World

choosing a world is as simple as setting the WORLD-worldType parameter in the settings_world.cfg file.

For programmers.

Building Worlds

Worlds are called with the evaluate function. By default, evaluate will call evaluateSolo on each organism in the population. If your world only evaluates a single organism at a time, you can simply override evaluateSolo. If your world must evaluate more than one organism at a time then you will need to override evaluate.

Next, you need to decide if you're writing a generational world or if your world will manage reproduction internally.

  • Generational World - in a generational world all that you need to need to do is make sure that a value to optimize is written into the data map of each organism. After each world evaluation, MABE will automatically create a new population and advance time (global::update).
  • Worlds with internal mating - in addition to evaluating the organisms in some way, these worlds must also manage populations, offspring ( which can be created with organism::makeMutatedOffspringFrom() ), global::update and when the archivist is called. Unlike, Generational Worlds, where MABE decides when global::update indicates that the run is done, in this type of world you control global::update, and so you will need to determine when to stop running. Once you're done, control will return to MABE, and global::update must be set, or the evolution loop will call evaluate again! This is not difficult though, as long as you are incrementing global::update, calls to archive will return a boolen value which will indicate if you are done.

Evaluate Flags

Worlds are accessed through an Evaluate function. This function takes the following arguments.

  • analyze - indicates to world that it should run its analyze code (generally this consists of code that gathers more detailed and sometimes expensive statistics)
  • visualize - indicates to world that it should run its visualize code (generally this consists of code that writes files which can be used for visualization tools, python, processing, etc.)
  • debug - indicates to world that it should run its debug code (generally this consists of code that prints additional information to the screen in order to help with debugging worlds... particularly useful when used with human brain)

requiredGroups()

When you write a world, you will design it to work with groups that have been formatted in a particular way (depending on what you need.) For example, a simple world may just require a single population where each organism has a brain. On the other hand, perhaps you are writing a world with predator and pray groups (wolfs and sheep?) where the predator groups require organisms with a brain, but the sheep group requires organisms with two brains (one for navigation and the other to run their little virtual stomachs). To communicate to the rest of MABE what sorts of groups your world needs, you will need to include a requiredGroups() function in your world.

virtual unordered_map> requiredGroups() {
	return { { groupName,{"B:"+ brainName+","+to_string(requiredInputs())+","+to_string(requiredOutputs())}} }; // default requires a root group and a brain (in root namespace) and no genome 
}

This function returns a map of string to string with one entry per required group.

A group entry looks like:

GROUPNAME,{B:BRAINNAME,#IN,#Out}

A group entry may include one or more genomes and brains

Sheep,{B:Head,3,5,B:Stomach,2,2,G:Stomach}

Here a sheep group is defined to have organisms with two brains (Head and Stomach) and one genome (Stomach - which is probably used to determine something about how the stomach is defined in these sheep)

popFileColumns

  • when writing a world, in the constructor you should set (see set popFileColumns ). This list will tell the Archivist what values being generated by this world should be written to pop files.
Clone this wiki locally