Evolution tools

World

Definition of a base class for a World template for use in evolutionary algorithms.

A definition of the World template, linking in specialized file handling, iterators, and selection techniques for evolutionary computation applications.

Todo:

Make sure when mutations occur before placement into the population we can control whether or not they also affect injected organisms. (Right now they always do!!)

We should Specialize World so that ANOTHER world can be used as an ORG, with proper delegation to facilitate demes, pools, islands, etc.

Add a signal for DoBirth() for when a birth fails.

Add a signal for population Reset() (and possibly Clear?)

Add a feature to maintain population sorted by each phenotypic trait. This will allow us to more rapidly find phenotypic neighbors and know the current extremes for each phenotype.

template<typename ORG>
class World
#include <World.hpp>

Setup a World with a population of organisms that can evolve or deal with ecological effects.

There are three ways that organisms can enter the population:

  • InjectAt(org, pos) - place the organism at the specified position in the population.

  • Inject(org) - place the organism using a default postion (given other settings).

  • DoBirth(org, parent_pos) - place the organism using current birth settings.

If the population is in EA mode (with synchronous generations), DoBirth will place offspring in a “next generation” placeholder population. Update() will move orgs into primary population.

Organisms have a series of functions that are called on them that are chosen:

FITNESS: Most selection methods require a fitness function to help determine who should be replicated. Other systems merely use fitness as a measured output. 0. If you explicitly set the fitness function using SetFitFun(), it will have priority.

  1. If the organism type has a “GetFitness()” member function, use it!

  2. If the organism type can be cast to double, use it!

  3. Start with a fitness function that throws an assert indicating function must be set.

MUTATIONS: The mutation function determines a main source of variation for most evolving systems. 0. If you set the mutation function using SetMutFun(), it will have priority.

  1. Or DoMutations(random) member function.

  2. Empty, with assert.

PRINTING: How should organisms be printed to the command line? 0. Setting the print function with SetPrintFun() member function.

  1. Org Print() member function that takes an ostream & argument

  2. Proper operator<<

  3. Do not print, just Assert

GENOMES: Do organisms have a genome separate from their instantiation? By default, the full organism is returned when a genome is requested, but a GetGenome() member function in the organism type will override this behavior.

  1. GetGenome member function

  2. Return org AS genome.

Public Types

using this_t = World<ORG>

Resolved type of this templated class.

using org_t = ORG

Type of organisms in this world.

using value_type = org_t

Identical to org_t; vector compatibility.

using pop_t = vector<Ptr<ORG>>

Type for whole populations.

using iterator_t = World_iterator<this_t>

Type for this world’s iterators.

using fit_cache_t = vector<double>

Type for fitness caches for pops.

using genome_t = typename find_genome_t<ORG>

Type of underlying genomes.

using fun_calc_fitness_t = std::function<double(ORG&)>

Function type for calculating fitness.

using fun_calc_dist_t = std::function<double(ORG&, ORG&)>

Function type for calculating the distance between two organisms.

using fun_do_mutations_t = std::function<size_t(ORG&, Random&)>

Function type for a mutation operator on an organism.

using fun_print_org_t = std::function<void(ORG&, std::ostream&)>

Function type for printing an organism’s info to an output stream.

using fun_get_genome_t = std::function<const genome_t&(ORG&)>

Function type for retrieving a genome from an organism.

using fun_find_inject_pos_t = std::function<WorldPosition(Ptr<ORG>)>

Function type for injecting organisms into a world (returns inject position)

using fun_find_birth_pos_t = std::function<WorldPosition(Ptr<ORG>, WorldPosition)>

Function type for adding a newly born organism into a world (returns birth position)

using fun_kill_org_t = std::function<WorldPosition()>

Function type for determining picking and killing an organism (returns newly empty position)

using fun_get_neighbor_t = std::function<WorldPosition(WorldPosition)>

Function type for identifying an organism’s random neighbor.

using fun_is_neighbor_t = std::function<bool(WorldPosition, WorldPosition)>

Function type for determining if two organisms are neighbors.

Public Functions

inline World(std::string _name = "", bool gen_random = true)

The World constructor can take two arguments, both optional:

  • a random number generator (either a pointer or reference)

  • a unique name for the world If no name is provided, the world remains nameless. If no random number generator is provided, gen_random determines if one should be created.

inline World(Random &rnd, std::string _name = "")
inline ~World()
inline size_t GetSize() const

How many organisms can fit in the world?

inline size_t GetNumOrgs() const

How many organisms are currently in the world?

inline size_t GetUpdate() const

What update number is the world currently on? (assumes Update() is being used)

inline size_t GetWidth() const

How many cells wide is the world? (assumes grids are active.)

inline size_t GetHeight() const

How many cells tall is the world? (assumes grids are active.)

inline size_t GetDepth() const

How many cells deep is the world? (assumes 3d grids are active.)

inline const pop_t &GetFullPop() const

Get the full population to analyze externally.

inline std::pair<org_t, size_t> GetDominantInfo() const

Get the organism most frequently found in the population and its abundance. Be sure to check whether the population is empty before calling!

inline org_t GetDominantOrg() const

Get the organism most frequently found in the population. Be sure to check whether the population is empty before calling!

inline const TraitSet<ORG> &GetPhenotypes() const

What phenotypic traits is the population tracking?

DataFile &AddDataFile(Ptr<DataFile> file)

Add an already-constructed datafile.

inline DataFile &GetFile(const std::string &filename)

Lookup a file by name.

inline bool IsOccupied(WorldPosition pos) const

Does the specified cell ID have an organism in it?

inline bool IsCacheOn() const

Are we currently caching fitness values?

inline bool IsSynchronous() const

Are generations being evaluated synchronously? (i.e., Update() places all births into the population after removing all current organisms.)

inline bool IsSpaceStructured() const

Is there some sort of spatial structure to the population? (i.e., are some organisms closer together than others.)

inline bool IsPhenoStructured() const

Is there some sort of structure to the population based on phenotype? (i.e., are phenotypically-similar organisms forced to be closer together?)

inline this_t &MarkSynchronous(bool in = true)

Denote that this World will be treated as having synchronous generations. (Note: this function does not change functionality, just indicates what’s happening!)

inline this_t &MarkSpaceStructured(bool in = true)

Denote that the World will have a spatial structure to the organisms. (Note: this function does not change functionality, just indicates what’s happening!)

inline this_t &MarkPhenoStructured(bool in = true)

Denote that the World will have organisms structured based on phenotype. (Note: this function does not change functionality, just indicates what’s happening!)

inline const ORG &operator[](size_t id) const

Index into a world to obtain a const reference to an organism. Any manipulations to organisms should go through other functions to be tracked appropriately. Will trip assert if cell is not occupied.

inline ORG &GetOrg(size_t id)

Retrieve a reference to the organsim as the specified position. Same as operator[]; will trip assert if cell is not occupied.

inline ORG &GetOrg(size_t x, size_t y)

Retrieve a const reference to the organism as the specified x,y coordinates.

inline const Ptr<ORG> GetOrgPtr(size_t id) const

Retrive a pointer to the contents of a specified cell; will be nullptr if the cell is not occupied.

inline ORG &GetNextOrg(size_t id)

Retrieve a reference to the organism at the specified position in the NEXT population. Will trip assert if cell is not occupied.

inline const genome_t &GetGenome(ORG &org)

Retrieve the genome corresponding to a specified organism.

inline const genome_t &GetGenomeAt(size_t id)

Retrive the genome corresponding to the organism at the specified position.

inline Ptr<SystematicsBase<ORG>> GetSystematics(int id = 0)

Get a systematics manager (which is tracking lineages in the population.)

Parameters:

id – - which systematics manager to return? Systematics managers are stored in the order they are added to the world.

inline Ptr<SystematicsBase<ORG>> GetSystematics(std::string label)

Get a systematics manager (which is tracking lineages in the population.)

Parameters:

label – - which systematics manager to return? Systematics managers are stored in the order they are added to the world.

inline void RemoveSystematics(int id)

Remove a systematics manager from this world

Parameters:

id – the id of the systematics manager to remove (0 is the first one you added, 1 is 2nd, etc.)

inline void RemoveSystematics(std::string label)

Remove a systematics manager from this world

Parameters:

label – the label of the systematics manager to remove

template<typename ORG_INFO, typename DATA_STRUCT = datastruct::no_data>
inline Ptr<Systematics<ORG, ORG_INFO, DATA_STRUCT>> AddSystematics(std::function<ORG_INFO(const ORG&)> calc_taxon, bool active = true, bool anc = true, bool all = true, bool pos = true, std::string label = "systematics")

Add a new systematics manager to the world by passing in all the information the world needs to construct it.

Parameters:
  • calc_taxon – a function that calculates the systematics manager’s taxon type from an ORG

  • active – Should living organisms’ taxa be tracked? (typically yes!)

  • anc – Should ancestral organisms’ taxa be maintained? (yes for lineages!)

  • all – Should all dead taxa be maintained? (typically no; it gets BIG!)

  • pos – Should the systematics tracker keep track of organism positions? (yes, unless you’re doing something super weird)

  • label – A label for this tracker so you can find it again

template<typename ORG_INFO, typename DATA_STRUCT>
inline void AddSystematics(Ptr<Systematics<ORG, ORG_INFO, DATA_STRUCT>> s, std::string label = "systematics")

Add a new systematics manager to the world from a pointer Note: You are giving the world object complete control of this systematics manager. It will be deleted in the destructor for this object

Parameters:
  • s – a pointer to the systematics manager to add

  • label – defines a label for this systematics manager, so you can find it again

inline fun_calc_fitness_t GetFitFun()

Get the fitness function currently in use.

void SetPopStruct_Grow(bool synchronous_gen = false)

Set the population to always append new organisms on the end. Argument determines if the generations should be synchronous (true) or not (false, default)

void SetPopStruct_Mixed(bool synchronous_gen = false)

Set the population to be well-mixed (with all organisms counting as neighbors.) Argument determines if the generations should be synchronous (true) or not (false, default)

void SetPopStruct_Grid(size_t width, size_t height, bool synchronous_gen = false)

Set the population to be a grid of cells using the specified dimensions. The third argument determines if the generations should be synchronous (true) or not (false, default)

void SetPopStruct_3DGrid(size_t width, size_t height, size_t depth, bool synchronous_gen = false)

Set the population to be a 3D grid of cells using the specified dimensions. The third argument determines if the generations should be synchronous (true) or not (false, default)

inline void SetAutoMutate()

Setup the population to automatically test for and trigger mutations. By default, this occurs before deciding where an offspring should be placed. Note that this pre-placement timing may be needed if fitness or other phenotypic traits are required to determine placement.

inline void SetAutoMutate(std::function<bool(size_t pos)> test_fun)

Setup the population to automatically test for and trigger mutations based on a provided test function that takes the position where the offspring will be placed and indicates (true/false) whether mutations should be processed. This timing allows position to influence mutations.

inline void SetAutoMutate(size_t first_pos)

Setup the population to automatically test for and trigger mutations IF the organism is being placed in a cell after a designated ID.

inline void SetSynchronousSystematics(bool synchronous)

Tell systematics managers that this world has synchronous generations.

template<typename ...Ts>
inline void AddPhenotype(Ts&&... args)

Add a new phenotype measuring function.

inline Ptr<DataMonitor<double>> GetFitnessDataNode()

Access a data node that tracks fitness information in the population. The fitness will not be collected until the first Update() after this function is initially called, signaling the need for this information.

inline Ptr<DataMonitor<double>> AddDataNode(const std::string &name)

Adds a data nodes to the world with the specified name.

Returns:

a pointer to the DataNode

inline Ptr<DataMonitor<double>> GetDataNode(const std::string &name)

Retrieve a pointer to a DataNode maintained by the world with a name matching name.

DataFile &SetupFile(const std::string &filename)

Setup an arbitrary file; no default filename available.

DataFile &SetupFitnessFile(const std::string &filename = "fitness.csv", const bool &print_header = true)

Setup a file to be printed that collects fitness information over time.

DataFile &SetupSystematicsFile(std::string label, const std::string &filename = "systematics.csv", const bool &print_header = true)

Setup a file (by label) to be printed that collects systematics information over time.

DataFile &SetupSystematicsFile(size_t id = 0, const std::string &filename = "systematics.csv", const bool &print_header = true)

Setup a file (by id) to be printed that collects systematics information over time.

DataFile &SetupPopulationFile(const std::string &filename = "population.csv", const bool &print_header = true)

Setup a file to be printed that collects population information over time.

inline void SetFitFun(const fun_calc_fitness_t &fit_fun)

Setup the function to be used when fitness needs to be calculated. The provided function should take a reference to an organism and return a fitness value of type double.

inline void SetMutFun(const fun_do_mutations_t &mut_fun)

Setup the function to be used to mutate an organism. It should take a reference to an organism and return the number of mutations that occurred.

inline void SetPrintFun(const fun_print_org_t &print_fun)

Setup the function to be used to print an organism. It should take a reference to an organism and an std::ostream, with a void return. The organism should get printed to the provided ostream.

inline void SetGetGenomeFun(const fun_get_genome_t &_fun)

Setup the function to extract or convert an organism to a genome. It should take an organism reference and return a const genome reference.

inline void SetAddInjectFun(const fun_find_inject_pos_t &_fun)

Setup the function to inject an organism into the population. It should take a pointer to the organism to be injected and return a WorldPosition indicating where it was placed.

inline void SetAddBirthFun(const fun_find_birth_pos_t &_fun)

Setup the function to place a newly born organism into the population. It should take a pointer to the new organism and the position of the parent, returning a WorldPosition indicating where it was placed.

inline void SetKillOrgFun(const fun_kill_org_t &_fun)

Setup the function to kill an organism. It should return a WorldPosition indicating the newly empty cell, which is not necessarily where the kill occurred.

inline void SetGetNeighborFun(const fun_get_neighbor_t &_fun)

Setup the function to take an organism position id and return a random neighbor id from the population.

inline void SetIsNeighborFun(const fun_is_neighbor_t &_fun)

Setup the function to determine if two organisms are neighbors. It should return a boolean indicating if they are neighbors.

void SetSharedFitFun(const fun_calc_fitness_t &fit_fun, const fun_calc_dist_t &dist_fun, double sharing_threshold, double alpha)

Same as setting a fitness function, but uses Goldberg and Richardson’s fitness sharing function (1987) to make similar organisms detract from each other’s fitness and prevent the population from clustering around a single peak. In addition to the base fitness function, a shared fitness function also requires:

  • a distance function that takes references to two organisms and returns a double indicating the distance between those organisms,

  • a sharing threshold (sigma share) that defines the maximum distance at which members should be considered in the same niche,

  • and a value of alpha, which controls the shape of the fitness sharing curve.

inline SignalControl &GetSignalControl()

Access signal controller used for this world directly.

inline SignalKey OnBeforeRepro(const std::function<void(size_t)> &fun)

Provide a function for World to call each time an organism is about to give birth. Trigger: Immediately prior to parent producing offspring Argument: World ID for the parent-to-be Return: Key value needed to make future modifications.

inline SignalKey OnOffspringReady(const std::function<void(ORG&, size_t)> &fun)

Provide a function for World to call after an offspring organism has been created, but before it is inserted into the World. Trigger: Offspring about to enter population Args: Reference to organism about to be placed in population and position of parent. (note: for multi-offspring orgs, parent may have been replaced already!) Return: Key value needed to make future modifications.

inline SignalKey OnInjectReady(const std::function<void(ORG&)> &fun)

Provide a function for World to call before an external organim is injected into the World. Trigger: New organism about to be added to population from outside Argument: Reference to organism about to be placed in population. Return: Key value needed to make future modifications.

inline SignalKey OnBeforePlacement(const std::function<void(ORG&, size_t)> &fun)

Provide a function for World to call before an organism is added to the active population, but after position is found. With synchonous generations, this occurs during Update(). Trigger: Organism is about to be added to population; position is known (either born or injected) Args: (1) Reference to organism about to be placed; (2) Position organism will be placed. Return: Key value needed to make future modifications.

inline SignalKey OnPlacement(const std::function<void(size_t)> &fun)

Provide a function for World to call immediately after any organism has been added to the active population. With synchonous generations, this occurs during Update(). Trigger: Organism has been added to population (either born or injected) Argument: Position of organism placed in the population. Return: Key value needed to make future modifications.

inline SignalKey OnUpdate(const std::function<void(size_t)> &fun)

Provide a function for World to call each time Update() is run. Trigger: New update is starting Argument: Update number (sequentially increasing) Return: Key value needed to make future modifications.

inline SignalKey OnOrgDeath(const std::function<void(size_t)> &fun)

Provide a function for World to call each time an organism is about to die. Trigger: Organism is about to be killed Argument: Position of organism about to die Return: Key value needed to make future modifications.

inline SignalKey OnSwapOrgs(const std::function<void(WorldPosition, WorldPosition)> &fun)

Provide a function for World to call each time two organisms swap positions in world. Trigger: Organisms have just swapped positions. Arguments: Positions of the two organisms. Return: Key value needed to make future modifications.

inline SignalKey OnWorldDestruct(const std::function<void()> &fun)

Provide a function for World to call at the start of its destructor (for additional cleanup). Trigger: Destructor has begun to execute Argument: None Return: Key value needed to make future modifications.

inline bool HasAttribute(const std::string &name) const

Worlds can have arbitrary attributes that can be set and changed dynamically. This function determines if an attribute exists, regardless of its value.

inline std::string GetAttribute(const std::string name) const

Get the value for an attribute that you know exists.

template<typename T>
inline void SetAttribute(const std::string &name, T &&val)

Set the value of a new attribute on this world. If the attribute already exists, it will be updated. If it doesn’t exist, it will be added.

void Update()

Update the world:

  1. Send out an update signal for any external functions to trigger.

  2. If synchronous generations, move next population into place as the current population.

  3. Handle any data-related updates including systematics and files that need to be printed.

  4. Increment the current update number.

template<typename ...ARGS>
inline void Process(ARGS&&... args)

Run the Process member function on all organisms in the population; forward any args passed into this function.

template<typename ...ARGS>
inline void ProcessID(size_t id, ARGS&&... args)

Run the Process member function on a single, specified organism in the population; forward any args passed into this function.

inline void ResetHardware()

Reset the hardware for all organisms.

double CalcFitnessOrg(ORG &org)

Use the configured fitness function on the specified organism.

double CalcFitnessID(size_t id)

Use the configured fitness function on the organism at the specified position.

inline void CalcFitnessAll() const

Calculate the fitness of all organisms, storing the results in the cache.

inline void SetCache(bool _in = true)

Turn on (or off) fitness caching for individual organisms.

inline void ClearCache()

Remove all currently cached fitness values (useful with changing environments, etc.)

inline void DoMutationsOrg(ORG &org)

Use mutation function on a single, specified organism.

inline void DoMutationsID(size_t id)

Use mutation function on the organism at the specified position in the population.

inline void DoMutations(size_t start_id = 0)

Use mutation function on ALL organisms in the population.

void Clear()

Remove all organisms from the world.

inline void Reset()

Clear all of the orgs and reset stats.

inline void Swap(WorldPosition pos1, WorldPosition pos2)

Swap the positions of two organisms.

inline void Resize(size_t new_size)

Change the size of the world. If the new size is smaller than the old, remove any organisms outside the new range. If larger, new positions are empty.

inline void Resize(size_t new_width, size_t new_height)

Change the size of the world based on width and height.

inline void Resize(const vector<size_t> &dims)

Change the size of the world based on a vector of dimensions.

void AddOrgAt(Ptr<ORG> new_org, WorldPosition pos, WorldPosition p_pos = WorldPosition())

AddOrgAt is the core function to add organisms to the population (others must go through here) Note: This function ignores population structure, so requires you to manage your own structure.

void RemoveOrgAt(WorldPosition pos)

RemoveOrgAt is the core function to remove organisms from the population. Note: This function ignores population structure, so requires you to manage your own structure.

void Inject(const genome_t &mem, size_t copy_count = 1)

Inject an organism using the default injection scheme.

void InjectAt(const genome_t &mem, const WorldPosition pos)

Inject an organism at a specific position.

template<typename ...ARGS>
void InjectRandomOrg(ARGS&&... args)

Inject a random organism (constructor must facilitate!)

WorldPosition DoBirth(const genome_t &mem, size_t parent_pos, size_t copy_count = 1)

Place one or more copies of an offspring into population; return position of last placed.

inline void DoDeath(const WorldPosition pos)
inline void DoDeath()
inline Random &GetRandom()

Return a reference to the random number generator currently being used by world.

void SetRandom(Random &r)

Setup a new random number generator created elsewhere.

void NewRandom(int seed = -1)

Create a new random number generator (that World will manage)

inline size_t GetRandomCellID()

Get the position a cell, at random.

inline size_t GetRandomCellID(size_t min_id, size_t max_id)

Get the position a cell in a range, at random.

inline WorldPosition GetRandomNeighborPos(WorldPosition pos)

Use the specified function to get a neighbor (if not set, assume well mixed).

inline bool IsNeighbor(WorldPosition id1, WorldPosition id2)

Use the specified function to determine if two indices are neighboring.

size_t GetRandomOrgID()

Get the id of a random occupied cell.

inline ORG &GetRandomOrg()

Get an organism from a random occupied cell.

vector<size_t> FindCellIDs(const std::function<bool(ORG*)> &filter)

Find ALL cell IDs that return true in the provided filter.

inline vector<size_t> GetValidOrgIDs()

Return IDs of all occupied cells in the population.

inline vector<size_t> GetEmptyPopIDs()

Return IDs of all empty cells in the population.

vector<size_t> GetValidNeighborOrgIDs(size_t id)

Return IDs of all occupied neighbors of specified position.

void DoBottleneck(const size_t new_size, bool choose_random = true)

Run population through a bottleneck to (potentially) shrink it.

void SerialTransfer(const double keep_frac)

Perform a Serial Transfer where a fixed percentage of current organisms are maintained.

void Print(std::ostream &os = std::cout, const std::string &empty = "-", const std::string &spacer = " ")

Print all organisms in the population using previously provided print function.

void PrintOrgCounts(std::ostream &os = std::cout)

Print unique organisms and the number of copies of each that exist.

void PrintGrid(std::ostream &os = std::cout, const std::string &empty = "-", const std::string &spacer = " ")

Print the organisms layed out in a grid structure (assumes a grid population.)

inline size_t size() const

[std::vector compatibility] How big is the world?

inline void resize(size_t new_size)

[std::vector compatibility] Update world size.

inline void clear()

[std::vector compatibility] Remove all organisms.

inline iterator_t begin()

[std::vector compatibility] Return iterator to first organism.

inline iterator_t end()

[std::vector compatibility] Return iterator just past last organism.

Protected Functions

template<typename T, typename ...ARGS>
inline void EMPCall_SetupOrg(bool_decoy<decltype(&T::Setup)>, T &target, ARGS&&... args)

Build a Setup function in world that calls ::Setup() on whatever is passed in IF it exists.

template<typename T, typename ...ARGS>
inline void EMPCall_SetupOrg(int, T&, ARGS...)
template<typename T, typename ...ARGS>
inline void SetupOrg(T &target, ARGS&&... args)
inline double GetCache(size_t id) const

Get the current cached value for the organism at the specified position.

inline void ClearCache(size_t id)

Clear the cache value at the specified position.

Protected Attributes

size_t update

How many times has Update() been called?

Ptr<Random> random_ptr

Random object to use.

bool random_owner

Did we create our own random number generator?

WorldVector<Ptr<ORG>> pops

The set of active [0] and “next” [1] organisms in population.

pop_t &pop

A shortcut to pops[0].

size_t num_orgs

How many organisms are actually in the population.

fit_cache_t fit_cache

vector size == 0 when not caching; uncached values == 0.

std::string name

Name of this world (for use in configuration.)

bool cache_on

Should we be caching fitness values?

std::vector<size_t> pop_sizes

Sizes of population dimensions (eg, 2 vals for grid)

TraitSet<ORG> phenotypes

What phenotypes are we tracking?

vector<Ptr<DataFile>> files

Output files.

bool is_synchronous

Does this world have synchronous generations?

bool is_space_structured

Do we have a spatially structured population?

bool is_pheno_structured

Do we have a phenotypically structured population?

DataManager<double, data::Current, data::Info, data::Range, data::Stats> data_nodes

Potential data nodes &#8212; these should be activated only if in use.

fun_calc_fitness_t fun_calc_fitness

…evaluate fitness for provided organism.

fun_do_mutations_t fun_do_mutations

…mutate an organism.

fun_print_org_t fun_print_org

…print an organism.

fun_get_genome_t fun_get_genome

…determine the genome object of an organism.

fun_find_inject_pos_t fun_find_inject_pos

…find where to inject a new, external organism.

fun_find_birth_pos_t fun_find_birth_pos

…find where to add a new offspring organism.

fun_kill_org_t fun_kill_org

…kill an organism.

fun_get_neighbor_t fun_get_neighbor

…choose a random neighbor “near” specified id.

fun_is_neighbor_t fun_is_neighbor

…determine if two organisms are neighbors.

std::map<std::string, std::string> attributes

Attributes are a dynamic way to track extra characteristics about a world.

vector<Ptr<SystematicsBase<ORG>>> systematics

Phylogeny and line-of-descent data collection.

std::unordered_map<std::string, int> systematics_labels
SignalControl control
Signal<void(size_t)> before_repro_sig

…before organism gives birth w/parent position.

Signal<void(ORG&, size_t)> offspring_ready_sig

…when offspring organism is built.

Signal<void(ORG&)> inject_ready_sig

…when outside organism is ready to inject.

Signal<void(ORG&, size_t)> before_placement_sig

…before placing any organism into target cell.

Signal<void(size_t)> on_placement_sig

…after any organism is placed into world.

Signal<void(size_t)> on_update_sig

…at the beginning of Update()

Signal<void(size_t)> on_death_sig

…immediately before any organism dies.

Signal<void(WorldPosition, WorldPosition)> on_swap_sig

…after org positions are swapped

Signal<void()> world_destruct_sig

…in the World destructor.

int ignore_semicolon_to_follow_SetupOrg = 0

Friends

friend class World_iterator< World< ORG > >

Systematics

NK

This file provides code to build NK-based algorithms.

Two version of landscapes are provided. NKLandscape pre-calculates the entire landscape, for easy lookup. NKLandscapeMemo does lazy evaluation, memorizing values when they’re first used. NKLandscape is faster, but goes up in memory size exponentially with K. NKLandscapeMemo is slightly slower, but can handle arbitrarily large landscapes.

Todo:

Right now we make the library user decide between NKLandscape and NKLandscapeMemo. Based on K value, we should be able to do this automatically, so we could merge the two.

class NKLandscape
#include <NK.hpp>

An NK Landscape is a popular tool for studying theoretical questions about evolutionary dynamics. It is a randomly generated fitness landscape on which bitstrings can evolve. NK Landscapes have two parameters: N (the length of the bitstrings) and K (epistasis). Since you have control over the amount of epistasis, NK Landscapes are often called “tunably rugged” - a useful feature, since the ruggedness of the fitness landscape is thought to be important to many evolutionary dynamics. For each possible value that a site and its K neighbors to the right can have, a random fitness contribution is chosen. These contributions are summed across the bitstring. So when K = 0, each site has a single optimal value, resulting in a single smooth fitness peak.

For more information, see Kauffman and Levin, 1987 (Towards a general theory of adaptive walks on rugged landscapes).

This object handles generating and maintaining an NK fitness landscape. Note: Overly large Ns and Ks currently trigger a seg-fault, caused by trying to build a table that is larger than will fit in memory. If you are using small values for N and K, you can get better performance by using an NKLandscapeConst instead.

Public Functions

inline NKLandscape()
NKLandscape(const NKLandscape&) = default
NKLandscape(NKLandscape&&) = default
inline NKLandscape(size_t _N, size_t _K, Random &random)

N is the length of bitstrings in your population, K is the number of neighboring sites the affect the fitness contribution of each site (i.e. epistasis or ruggedness), random is the random number generator to use to generate this landscape.

inline ~NKLandscape()
NKLandscape &operator=(const NKLandscape&) = delete
NKLandscape &operator=(NKLandscape&&) = default
inline void Reset(Random &random)

Randomize the landscape without changing the landscape size.

inline void Config(size_t _N, size_t _K, Random &random)

Configure for new values of N and K.

inline size_t GetN() const

Returns N.

inline size_t GetK() const

Returns K.

inline size_t GetStateCount() const

Get the number of posssible states for a given site.

inline size_t GetTotalCount() const

Get the total number of states possible in the landscape (i.e. the number of different fitness contributions in the table)

inline double GetFitness(size_t n, size_t state) const

Get the fitness contribution of position [n] when it (and its K neighbors) have the value [state]

inline double GetFitness(std::vector<size_t> states) const

Get the fitness of a whole bitstring.

inline double GetFitness(BitVector genome) const

Get the fitness of a whole bitstring (pass by value so can be modified.)

inline double GetSiteFitness(size_t n, BitVector genome) const

Get the fitness of a site in a bitstring.

inline vector<double> GetFitnesses(BitVector genome) const

Get the fitness of a whole bitstring (pass by value so can be modified.)

inline void SetState(size_t n, size_t state, double in_fit)
inline void RandomizeStates(Random &random, size_t num_states = 1)

Private Members

size_t N

The number of bits in each genome.

size_t K

The number of OTHER bits with which each bit is epistatic.

size_t state_count

The total number of states associated with each bit table.

size_t total_count

The total number of states in the entire landscape space.

vector<vector<double>> landscape

The actual values in the landscape.

class NKLandscapeMemo
#include <NK.hpp>

The NKLandscapeMemo class is simialar to NKLandscape, but it does not pre-calculate all of the landscape states. Instead it determines the value of each gene combination on first use and memorizes it.

Public Functions

NKLandscapeMemo() = delete
NKLandscapeMemo(const NKLandscapeMemo&) = delete
NKLandscapeMemo(NKLandscapeMemo&&) = default
inline NKLandscapeMemo(size_t _N, size_t _K, Random &random)
inline ~NKLandscapeMemo()
NKLandscapeMemo &operator=(const NKLandscapeMemo&) = delete
NKLandscapeMemo &operator=(NKLandscapeMemo&&) = default
inline size_t GetN() const
inline size_t GetK() const
inline double GetFitness(size_t n, const BitVector &state) const
inline double GetFitness(const BitVector &genome) const

Private Members

size_t N
size_t K
mutable vector<memo_function<double(const BitVector&)>> landscape
vector<BitVector> masks

Selection

Functions for popular selection methods applied to worlds.

Functions

template<typename ORG>
void EliteSelect(World<ORG> &world, size_t e_count = 1, size_t copy_count = 1)

==ELITE== Selection picks a set of the most fit individuals from the population to move to the next generation. Find top e_count individuals and make copy_count copies of each.

Parameters:
  • world – The World object with the organisms to be selected.

  • e_count – How many distinct organisms should be chosen, starting from the most fit.

  • copy_count – How many copies should be made of each elite organism?

template<typename ORG>
void RandomSelect(World<ORG> &world, size_t r_count = 1, size_t copy_count = 1)

==RANDOM== Selection picks an organism with uniform-random probability form the populaiton.

Parameters:
  • world – The World object with the organisms to be selected.

  • r_count – How many distinct organisms should be chosen?

  • copy_count – How many copies should be made of each chosen organism?

template<typename ORG>
void TournamentSelect(World<ORG> &world, size_t t_size, size_t tourny_count = 1)

==TOURNAMENT== Selection creates a tournament with a random sub-set of organisms, finds the one with the highest fitness, and moves it to the next generation. User provides the world (with a fitness function), the tournament size, and (optionally) the number of tournaments to run.

Parameters:
  • world – The World object with the organisms to be selected.

  • t_size – How many organisms should be placed in each tournament?

  • tourny_count – How many tournaments should be run? (with replacement of organisms)

template<typename ORG>
void LocalTournamentSelect(World<ORG> &world, size_t t_size, size_t tourny_count = 1)

==LOCAL TOURNAMENT== Selection creates a tournament with a random sub-set of organisms that are neighbor to a random organism, finds the one with the highest fitness, and moves it to the next generation. User provides the world (with a fitness function), the tournament size, and (optionally) the number of tournaments to run.

Parameters:
  • world – The World object with the organisms to be selected.

  • t_size – How many organisms should be placed in each tournament?

  • tourny_count – How many tournaments should be run? (with replacement of organisms)

template<typename ORG>
void RouletteSelect(World<ORG> &world, size_t count = 1)

==ROULETTE== Selection (aka Fitness-Proportional Selection) chooses organisms to reproduce based on their current fitness.

Parameters:
  • world – The World object with the organisms to be selected.

  • count – How many organims should be selected for replication? (with replacement)

template<typename T, typename ...ARGS>
void EMPCall_TriggerOnLexicaseSelect(bool_decoy<decltype(&T::TriggerOnLexicaseSelect)>, T &target, ARGS&&... args)
template<typename T, typename ...ARGS>
void EMPCall_TriggerOnLexicaseSelect(int, T&, ARGS...)
template<typename T, typename ...ARGS>
void TriggerOnLexicaseSelect(T &target, ARGS&&... args)
template<typename ORG>
void LexicaseSelect(World<ORG> &world, const vector<std::function<double(const ORG&)>> &fit_funs, size_t repro_count = 1, size_t max_funs = 0)

==LEXICASE== Selection runs through multiple fitness functions in a random order for EACH offspring produced.

Parameters:
  • world – The World object with the organisms to be selected.

  • fit_funs – The set of fitness functions to shuffle for each organism reproduced.

  • repro_count – How many rounds of replication should we do. (default 1)

  • max_funs – The maximum number of fitness functions to use. (use 0 for all; default)

template<typename ORG>
void OptimizedLexicaseSelect(World<ORG> &world, const vector<std::function<double(const ORG&)>> &fit_funs, size_t repro_count = 1, size_t max_funs = 0)

==OPTIMIZED LEXICASE== Is the same as regular lexicase, but determines how many unique genotypes there are

Parameters:
  • world – The World object with the organisms to be selected.

  • fit_funs – The set of fitness functions to shuffle for each organism reproduced.

  • repro_count – How many rounds of repliction should we do. (default 1)

  • max_funs – The maximum number of fitness functions to use. (use 0 for all; default)

template<typename ORG>
void EcoSelect(World<ORG> &world, const vector<std::function<double(ORG&)>> &extra_funs, const vector<double> &pool_sizes, size_t t_size, size_t tourny_count = 1)
template<typename ORG>
void EcoSelect(World<ORG> &world, const vector<typename World<ORG>::fun_calc_fitness_t> &extra_funs, double pool_sizes, size_t t_size, size_t tourny_count = 1)

EcoSelect can be provided a single value if all pool sizes are identical.

Variables

int ignore_semicolon_to_follow_TriggerOnLexicaseSelect = 0