Homework 1: evolution

Due Wednesday, 2009-02-04

Download these 9 Python modules and two data files. You will create a new module, genome.py and will also edit thing.py and world.py. Submit all files that you create or edit.

The biomorph program

Before running the program, you may have to edit the first line in biomorph.py so that the path points to Python 2.5 or 2.6 on your system. Once this is in place, you should be able to run the program by doing 'biomorph.py' from within the directory where the program resides. If this doesn't work, email me.

The program runs in two modes, depending on what arguments you pass to biomorph.py. An argument following -w specifies a "world" in which various things live and die. An argument following -x specifies an experiment to be run in a neural network. You will only have to worry about the "world" mode for this assignment.

The argument following -w should be the name of a file in the same directory as the program. Start with the file evol that is provided. This file specifies a number of parameters that control how the program is set up and how it runs. Each is separated by a blank line. Comments can appear in the file, but don't include equal signs within them. Any parameter that does not appear in the file gets a default value.

Parameters

THINGS is a dictionary specifying which things there are in the world and how many of each. For each type, you can specify an initial number ("init"), a minimum number ("min"), a maximum number ("max"), an amount to increase on each time step ("growth"). For Bunnies and Kitties, you can also specify "senses" (see below for possibilities). For Bunnies, you can also specify whether learning and/or evolution is to take place (but don't change these for this assignment).

Among the strength-related parameters, the only ones you might want to change are INIT_STRENGTH, which is the strength that new Critters (Bunnies and Kitties) start with, and LIFE_EXPECT, which controls the length of the lifetime of Critters.

The reinforcement values control changes in the strength of Bunnies when various things happen.

Three parameters control reproduction.

Interface

The main window of the program displays the current state of the world and has menus for controlling evolution, the number of steps that happen when you click on "Run", and some display properties and buttons for running the network once ("Step") and multiple times ("Run") and for restoring the initial number of each thing ("Reinit"). All of the graphics methods for this window are in world.py. Since some Tkinter methods are used to calculate sensory input, the graphics can never actually be turned off completely. Unless you select "Always update graphics" in the "View" menu, the display won't update until the end of a run, however. You probably will not have to worry about any of the code in world.py, except for the mate() method in World (see below).

Once you have defined show() in the Genome class (see below), then selecting "Show Genomes after Run" will cause all of the Genomes to be displayed when a run ends.

How it works

The heart of the program is the thing module, which defines the hierarchy of Thing classes, in particular, Bunny, Kitty, and Veggie. Each thing has an associated Tkinter Canvas object, identified by its id attribute. Control over the number of things of each type that are created at the beginning and updated during a run happens via the values in the THINGS dictionary.

All Orgs have the potential to reproduce themselves, but this is turned off for Veggies and Kittys in the current version.

Each Bunny and Kitty has a neural network (defined in Network.py) that controls how it behaves. The number of input units is figured on the basis of the sensor(s) the agent has, and the number of output units is figured on the basis of the number of possible actions. Each network consists of two Layers of units. Clicking on a Bunny or Kitty brings up a window that displays its neural network. Pressing the mouse on an output unit in this window shows the weights into it from the input units and the bias unit (displayed in the lower left corner).

On each time step, each Critter calls its attend_state() method, which generates input from its sensor(s) (defined in Sense.py). By default Bunnies start with two sensors, a Touch sensor that records whether something is in a narrow region around it, and a Feel sensor, a sort of whisker that sticks out its mouth and tells it what is directly in front of it. Each of these sensors can detect four "textures" (those of Veggies, Walls, Bunnies, and Kitties), and the presence or absence of these values is passed to the neural network input layer (8 units). Kittys have a Smell sensor, which can detect the presence of three "smells" within a large region around it (those of Kitties, Veggies, and Bunnies; Walls don't smell). You can see what regions the sensors respond to by selecting "Show senses" in the "View" menu.

Bunnies and Kitties select an action stochastically on the basis of their sensory input; that is, the activations of the output units of their neural networks are treated as probabilities. Bunnies have four possible actions: move, turn, hide, and eat; Kitties have all of these except hide. Moving is a move in the direction of the Critter's heading with a magnitude that is proportional to its strength. Turning is a 60° rotation in a clockwise or counterclockwise direction; the direction is selected randomly. All of the actions are methods in the Critter class. An eat action succeeds if the food item belongs to the right class (Veggie for Bunnies, Bunny for Kitties, and the food item is within a small radius of the end of the Critter's mouth.

The neural network of Kitties is hard-wired so that they behave "smartly": eating when they smell Bunnies, turning or moving otherwise.

All Orgs have a genome attribute, assigned in the method set_genome. This defaults to None, and you will have to change it in the Bunny class to implement evolution. Bunnies can reproduce in two ways, through copying and mating. Which happens is controlled by the "Evolve" menu. Selecting "No reproduction" causes no reproduction at all to take place. Selecting "Copy without evolving" causes copying of Bunnies to take place, but the new genomes are generated randomly. Selecting "Evolve by copying" causes causes copying of Bunnies to take place, and the new genomes are copies of the old (with mutation). Selecting "Evolve by mating" causes mating of Bunnies to take place, and the genomes of the offspring are created from their parent's genomes through crossover.

(Evolutionary) copying should copy the parent genome and mutate it. This already happens in the copy() method in the Bunny class; you don't have to edit it. Mating should produce two offspring from two parents, applying crossover to produce the new genomes. This happens in the mate() method in the World class. You will have to edit this method.

When you run the world, some statistics are displayed in the shell, including the mean and maximum strengths for each type of Thing after every 100 time steps (though these numbers will only be of interest for Bunnies).

What you have to do

  1. In a separate file genome.py, define the Genome class. This must at least have an __init__() method that takes a critter as its single argument (in addition to self), an initialize() method that sets the length of the genome and assigns initial random values, a copy() method that yields a new Genome that is a copy of this one with random bits mutated, and a show() method that displays the genome. All of these methods are called in thing.py or world.py. You will also need a way to assign the weights and biases in the neural network from the values in the genome. The Network class has two methods you will probably want to use: get_n_weights() and assign_weights(). You will also need to uncomment the from genome import * line in thing.py and the line in the __init__ method for Bunny that assigns the genome attribute to a new instance of Genome.
  2. Edit mate() in world.py so that it does the right thing.
  3. The initial setup of the THINGS dictionary creates a relatively world in which the number of Bunnies and Veggies is fixed and there are not Kitties. Given this world and the other values in evol, show that evolution with reproduction by copying exhibits significant improvement over no evolution and tha evolution by mating exhibits some improvement over no evolution (considering either mean strength or maximum strength or both).
  4. Make the world more realistic by allowing the number of Bunnies to decrease and increase (set the "min" value to 0 and the "max" value to a large number such as 120). Discuss how this changes the outcome. You will probably want to change some of the other parameters, for example, INIT_STRENGTH, to make things "easier" for the Bunnies. If so, explain what settings you used.
  5. Make the world still more realistic by allowing the number of plants to decrease and increase (set the "min" value to 0 and the "growth" value to 1 or 2). Discuss how this changes the outcome. Again you may have to change some of the parameters to make the world easier; report the settings you used.

Home

Calendar

Coursework

Notes

Code


IU | INFO | CSCI

Contact instructor