simulation provides the Simulation class, a master class for creating and executing Pykaryote simulations. Conventionally Simulation is managed by one of the command line utilities, but it can also be imported and run in an interactive Python console.
A Simulation manages all the components of a simulation. It contains an Environment that represents, funnily enough, the environment in which the the population of Organism‘s live. Through the environment, it also contains a ComplexTracker and a FamilyTracker that keep track of the complexes and complex families that exist in the simulation.
A Simulation is run as a series of generations. Each generation starts with a population of organisms, distrubuted in some fashion in an environment. The generation is comprised of generation_length steps. In each step all of the organisms perform one action (the actual implementation groups these together with each organism performing org_step steps at a time. This is only for optimization and doesn’t currently affect the workings of the model). It is also possible to update the environment over the course of the generation, although no methods for doing so are yet fully implemented.
At the end of a generation, the fitness for each organism is computed and used to determine which organisms will reproduce. Analysis data is logged by the CreativeAnalyzer. Every log_step generations, the state of the simulation is logged in a human-readable fashion. Every save_step generations, the simulation is pickled and stored for later loading. Finally, a new generation is created and the whole process starts anew.
Every organism has a chance to reproduce, a chance determined by its fitness score. Fitness scores are computed as follows. For each chemical that it posesses, the organism receives a bonus to its fitness based on the fitness function specified in chemical_fitness_falloff. The sum of the chemical fitness scores is then multiplied by the normalization constant discussed below. Finally, the product of genome_fitness_factor and the length of the organism’s genome is subtracted from the normalized score.
The normalization constant is intended to allow comparison of simulations with different environments, gather rates, etc. This constant is computed by the simulation when it is created. The simulation calculates the amount of chemicals an organism would acquire if it gathered evenly distributed amounts of all available chemicals, with no proteins or movement, in a square that was the average of all the squares in the environment. The normalization constant is assigned so that after the chemical fitness is normalized and the genome fitness cost subtracted, this ideal organism would have a fitness equal to fitness_scale.
Simulations save themselves every save_step generations while running. These saves can be reloaded as simulations and run again to–for instance–recover from a system crash or explore a different possible future. Loading simulations is simple, but it must be done in the interpreter.:
>>> from pykaroyte.sim.simulation import load_sim
>>> my_sim = load_sim("my/saved/simulation/save_gen_150.p")
>>> # show some graphs
>>> my_sim.analyzer.save_all() # saves data to the 'graphs' directory
>>> # runs from the point it left off
>>> my_sim.run()
Pykaryote Simulations
The Simulation class organizes and runs the complexity simulations.
name (str): The name of this simulation
config (str): the configuration file for the simulation.
clear (bool): Default True, delete the contents of this simulation’s data directory before starting.
Computes the fitness of an “average” primitive organism which has the minimum genome length.
Prints the details of the simulation in such a way that a new simulation can be constructed from the data.
Returns True if the simulation should end.
As specified in the config files, a simulation should end after generation_limit generations or once complexity grows past complexity_limit or if the estimated total runtime exceeds runtime_limit. If any of these configuration options are zero, there is no limit.
Advances the simulation one step with each organism reading one step of their genome.
Creates a human-readable log file of the simulation in the specified file.
Breeds a new generation from the previous. Overwrites the old generation with the new, and returns a list of organisms that reproduced (with organisms that reproduced more than once appearing more than once).
Runs the simulation until it finishes.
Args:
- log (boolean): Log the state of the simulation every log_step
- generations
verbose (boolean): Print generation numbers
Saves a pickled copy of the simulation. This can be loaded via the simulation.load_sim(file) method
Prints a summary of the current generation, giving their fitnesses and net fitness
Loads and returns a pickled simulation.
Args:
sim_file (str): the filename of the pickled simulation