mercere99 / mabe2 Goto Github PK
View Code? Open in Web Editor NEWVersion 2 of the Modular Agent-Based Evolver
License: MIT License
Version 2 of the Modular Agent-Based Evolver
License: MIT License
Right now, .mabe
files don't seem to be able to read negative numbers unless they're in quotation marks, which is a confusing convention. it also means the .gen
file sometimes generates a random seed that the .mabe
file can't read, and that setting a min value on a ValsOrg less than 0 needs quotation marks even though the max value does not.
When an offspring organism is created from a parent, all the offspring's traits will be copies of the parent's traits.
This occurs even when the trait was given a default value to use.
The Organism
class inherits from emp::AnnotatedType
, which contains an emp::DataMap
. This allows users to create and store traits on Organisms.
However, neither the Organism
class nor the emp::Annotatedtype
class explicitly define a copy constructor, and the DataMap
copy constructor simply copies over the raw memory from the original DataMap
.
Offspring are created by first cloning the original organism and then optionally applying mutations. The process of cloning an organism uses its copy constructor (called via ManagerModule::CloneObject_impl()
). Thus the offspring has a DataMap
that is a direct copy of the parent's.
OnPlacement()
core/TraitInfo.hpp
specify multiple INIT methods for traits. Implementing these methods should alleviate this issue.A working example of this issue can be found at https://github.com/FergusonAJ/MABE2/tree/trait_issue
The only modification to the source code was allowing users to deactivate modules in the config files events.
A sample config files, settings/issue.mabe
is included:
random_seed = 0; // Seed for random number generator; use 0 to base on time.
Population main_pop; // Collection of organisms
Population next_pop; // Collection of organisms
Value pop_size = 5; // Local value variable.
CommandLine cl { // Handle basic I/O on the command line.
format = "fitness:max,fitness:mean";// Column format to use in the file.
target = "main_pop"; // Which population(s) should we print from?
}
EvalNK eval_nk { // Evaluate bitstrings on an NK fitness lanscape.
target = "main_pop"; // Which population(s) should we evaluate?
N = 100; // Number of bits required in output
K = 3; // Number of bits used in each gene
bits_trait = "bits"; // Which trait stores the bit sequence to evaluate?
fitness_trait = "fitness"; // Which trait should we store NK fitness in?
}
FileOutput output { // Output collected data into a specified file.
filename = "output.csv"; // Name of file for output data.
format = "fitness:max,fitness:mean,fitness:0,fitness:1,fitness:2,fitness:3,fitness:4";// Column format to use in the file.
target = "main_pop"; // Which population(s) should we print from?
output_updates = "0:1"; // Which updates should we output data?
}
SelectTournament select_t { // Select the top fitness organisms from random subgroups for replication.
select_pop = "main_pop"; // Population from which to select parents
birth_pop = "next_pop"; // Population into which offspring should be placed
tournament_size = 2; // Number of orgs in each tournament
num_tournaments = 5; // Number of tournaments to run
fitness_fun = "fitness"; // Trait equation that produces fitness value to use
}
GrowthPlacement place_next { // Always appened births to the end of a population.
target = "main_pop,next_pop"; // Population(s) to manage.
}
MovePopulation sync_gen { // Move organisms from one populaiton to another.
from_pop = "next_pop"; // Population to move organisms from.
to_pop = "main_pop"; // Population to move organisms into.
reset_to = 1; // Should we erase organisms at the destination?
}
BitsOrg bits_org { // Organism consisting of a series of N bits.
N = 100; // Number of bits in organism
mut_prob = 0.01; // Probability of each bit mutating on reproduction.
output_name = "bits"; // Name of variable to contain bit sequence.
init_random = 1; // Should we randomize ancestor? (0 = all zeros)
}
@start(0) PRINT("random_seed = ", random_seed, "\n");
@start(0) INJECT("bits_org", "main_pop", pop_size);
@update(5) eval_nk._active = 0;
@update(10) EXIT();
In particular, we care that the EvalNK module is deactivated at the start of the 5th update. Thus no organisms born on or after that update should receive fitness scores.
However, upon running the file it is clear that organisms born after update 4 still have a fitness
trait:
#update, fitness:max, fitness:mean, fitness:0, fitness:1, fitness:2, fitness:3, fitness:4
0, 0, 0, 0, 0, 0, 0, 0
1, 55.0215, 52.1714, 49.5619, 49.5619, 53.3559, 53.3559, 55.0215
2, 54.8404, 53.1193, 53.3559, 54.8404, 52.0221, 52.0221, 53.3559
3, 55.0693, 53.8883, 55.0693, 54.6868, 52.4995, 54.6868, 52.4995
4, 55.9023, 54.9373, 52.4995, 55.9023, 54.4799, 55.9023, 55.9023
5, 57.3455, 55.5606, 53.3297, 57.3455, 56.4527, 53.3297, 57.3455
6, 57.3455, 56.8098, 57.3455, 57.3455, 56.4527, 56.4527, 56.4527
7, 57.3455, 56.9884, 57.3455, 56.4527, 56.4527, 57.3455, 57.3455
8, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455
9, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455
10, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455, 57.3455
Indeed, by the final update all organisms have a fitness
score of 57.3455, which is expected because it was the highest score in update 4 and thus swept the population. While these offspring organisms were never actually evaluated, they maintain the score of their parent organisms. This is despite the evaluate/EvalNK.hpp
file setting the default fitness
value to 0.
AddOwnedTrait<double>(fitness_trait, "NK fitness value", 0.0);
The mut_size
parameter goes unused; all mutations use a standard normal distribution.
Simple fix, just needs brought into master.
Often organisms are tracked by their position, but sometimes we may just have the organism pointer and need to affect the rest of its population. Whenever an organism is born or shifts position, we would simply need to update this field. It should have low overhead.
One alternative to consider is to keep the position in the organism's DataMap as a trait. This would allow it to only be stored if anyone is using it. A built-in organism-tracker module could detect if anyone requires the trait and only keep it active when needed. It may be worth doing some speed/size tests between not tracking, tracking as a member variable, and tracking as a DataMap trait.
The exploit diagnostic in /source/evaluate/static/EvalDiagnostic.hpp
should just be copying the genetically encoded values over to the score trait. However, this score trait is not being set.
Looks like an earlier commit switched the vals
and scores
traits from emp::vectors
to std::spans
. In particular, the scores
trait went from a reference to a non-reference variable.
Then, on line 100 of the current file, we see
scores = vals;
Which would have worked for the vector, but at first glance this is doing a shallow copy of the underlying pointer in the span (https://en.cppreference.com/w/cpp/container/span/operator%3D).
Iteratively assigning works, but they may be a better solution. I am unfamiliar with both spans and the new trait system.
for (size_t i = 0; i < scores.size(); i++) scores[i] = vals[i];
Rather than have Eval modules evaluate populations directly, they should produce (or append to) eval sets, where evaluations can be requested on at a time. This technique will allow for a fixed interface where selection schemes can more easily analyze and pick which evaluations need to be performed.
EvalSets should also handle caching of evaluations.
Right now the type system in Config does not track the associated with C++ types beyond Value (double) and String. If we create these links then calling a function on one side can automatically link correct types (and we can do proper overloading).
One easy way is to track emp::TypeID for the different types.
In order to unambiguously identify organisms (especially post-run), it would be helpful for each organism to have an extra size_t as an ID.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.