|
std::function<size_t(AagosOrg &, emp::Random &)> mut_fun = |
|
[this](AagosOrg &org, emp::Random &random) { |
|
// Do gene moves. |
|
size_t num_moves = random.GetRandBinomial(org.GetNumGenes(), config.GENE_MOVE_PROB()); |
|
for (size_t m = 0; m < num_moves; m++) |
|
{ |
|
size_t gene_id = random.GetUInt(org.GetNumGenes()); |
|
org.gene_starts[gene_id] = random.GetUInt(org.GetNumBits()); |
|
} |
|
|
|
// Do bit flips mutations |
|
size_t num_flips = random.GetRandBinomial(org.GetNumBits(), config.BIT_FLIP_PROB()); |
|
for (size_t m = 0; m < num_flips; m++) |
|
{ |
|
const size_t pos = random.GetUInt(org.GetNumBits()); |
|
org.bits[pos] ^= 1; |
|
} |
|
|
|
// Get num of insertions and deletions. |
|
int num_insert = random.GetRandBinomial(org.GetNumBits(), config.BIT_INS_PROB()); |
|
int num_delete = random.GetRandBinomial(org.GetNumBits(), config.BIT_DEL_PROB()); |
|
const int proj_size = (int)org.bits.GetSize() + num_insert - num_delete; |
|
|
|
// checks gene size is within range |
|
if (proj_size > config.MAX_SIZE()) |
|
{ // if size of genome larger than max, restrict to max size |
|
num_insert -= proj_size - config.MAX_SIZE(); |
|
} |
|
else if (proj_size < config.MIN_SIZE()) |
|
{ // else if size of genome smaller than min, restrict as well |
|
num_delete -= config.MIN_SIZE() - proj_size; |
|
} |
|
|
|
// asserts size limitations |
|
emp_assert((int)org.bits.GetSize() + num_insert - num_delete >= config.MIN_SIZE(), |
|
"the genome size can't be smaller than the genome length, else BitSet breaks"); |
|
emp_assert((int)org.bits.GetSize() + num_insert - num_delete <= config.MAX_SIZE(), "some limit on bloat of program"); |
|
|
|
// Do insertions |
|
for (int i = 0; i < num_insert; i++) // For each insertion that occurs, |
|
{ |
|
const size_t pos = random.GetUInt(org.GetNumBits()); // Figure out position for insertion. |
|
org.bits.Resize(org.bits.GetSize() + 1); // Increase size to make room for insertion. |
|
emp::BitVector mask(pos, 1); // Setup a mask to preserve early bits. |
|
mask.Resize(org.bits.GetSize()); // Align mask size. |
|
|
|
// Now build the new string! |
|
org.bits = (mask & org.bits) | ((org.bits << 1) & ~mask); |
|
org.bits[pos] = random.P(0.5); // Randomize the new bit. |
|
|
|
// Shift any genes that started at pos or later. |
|
for (auto &x : org.gene_starts) |
|
if (x >= pos) |
|
x++; |
|
} |
|
|
|
// Do deletions |
|
for (int i = 0; i < num_delete; i++) // For each deletion that occurs, |
|
{ |
|
size_t pos = random.GetUInt(org.GetNumBits()); // Figure out position to delete. |
|
emp::BitVector mask(pos, 1); // Setup a mask to preserve early bits. |
|
mask.Resize(org.bits.GetSize()); // Align mask size. |
|
|
|
org.bits = (mask & org.bits) | ((org.bits >> 1) & ~mask); // Build the new string! |
|
org.bits.Resize(org.bits.GetSize() - 1); // Decrease size to account for deletion |
|
|
|
// Shift any genes that started at pos or later. |
|
if (pos == 0) |
|
pos = 1; // Adjust position if beginning was deleted. |
|
for (auto &x : org.gene_starts) |
|
if (x >= pos) |
|
x--; |
|
} |
|
|
|
return num_moves + num_flips + num_insert + num_delete; // Returns total num mutations |
|
}; |
|
SetMutFun(mut_fun); // set mutation function of world to above |
|
SetPopStruct_Mixed(true); // uses well-mixed population structure |
|
SetDataTracking(); // sets up data tracking |
|
|
|
} |