Skip to content

Commit

Permalink
+ allow higher mutation rates
Browse files Browse the repository at this point in the history
+ prefer mutations that change input execution number to execution number of adjacent nodes
  • Loading branch information
chrxh committed Aug 28, 2024
1 parent 2225db3 commit b261bac
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 74 deletions.
128 changes: 79 additions & 49 deletions source/EngineGpuKernels/MutationProcessor.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public:
private:
template <typename Func>
__inline__ __device__ static void executeEvent(SimulationData& data, float probability, Func eventFunc);
template <typename Func>
__inline__ __device__ static void executeMultipleEvents(SimulationData& data, float probability, Func eventFunc);
__inline__ __device__ static void adaptMutationId(SimulationData& data, ConstructorFunction& constructor);
__inline__ __device__ static bool isRandomEvent(SimulationData& data, float probability);
__inline__ __device__ static int getNewColorFromTransition(SimulationData& data, int origColor);
Expand Down Expand Up @@ -128,11 +130,11 @@ __inline__ __device__ void MutationProcessor::applyRandomMutationsForCell(Simula
cell->pos,
cell->color);

executeEvent(data, cellCopyMutationCellProperties, [&]() { propertiesMutation(data, cell); });
executeEvent(data, cellCopyMutationNeuronData, [&]() { neuronDataMutation(data, cell); });
executeMultipleEvents(data, cellCopyMutationCellProperties, [&]() { propertiesMutation(data, cell); });
executeMultipleEvents(data, cellCopyMutationNeuronData, [&]() { neuronDataMutation(data, cell); });
executeEvent(data, cellCopyMutationGeometry, [&]() { geometryMutation(data, cell); });
executeEvent(data, cellCopyMutationCustomGeometry, [&]() { customGeometryMutation(data, cell); });
executeEvent(data, cellCopyMutationCellFunction, [&]() { cellFunctionMutation(data, cell); });
executeMultipleEvents(data, cellCopyMutationCellFunction, [&]() { cellFunctionMutation(data, cell); });
executeEvent(data, cellCopyMutationInsertion, [&]() {
auto numNonSeparatedNodes = toFloat(GenomeDecoder::getNumNodesRecursively(constructor.genome, constructor.genomeSize, false, false));
if (numNodes < 2 * numNonSeparatedNodes) {
Expand Down Expand Up @@ -184,50 +186,66 @@ __inline__ __device__ void MutationProcessor::propertiesMutation(SimulationData&
auto numNodes = GenomeDecoder::getNumNodesRecursively(genome, genomeSize, false, true);
auto node = data.numberGen1.random(numNodes - 1);
auto sequenceNumber = 0;
uint8_t lastExecutionNumber = 0;
GenomeDecoder::executeForEachNodeRecursively(genome, genomeSize, true, false, [&](int depth, int nodeAddress, int repetition) {
if (sequenceNumber++ != node) {
return;

uint8_t prevExecutionNumber = data.numberGen1.randomByte();
uint8_t nextExecutionNumber = data.numberGen1.randomByte();
int nodeAddress = 0;
GenomeDecoder::executeForEachNodeRecursively(genome, genomeSize, true, false, [&](int depth, int nodeAddressIntern, int repetition) {
auto origSequenceNumber = sequenceNumber;
++sequenceNumber;
if (origSequenceNumber == node - 1) {
prevExecutionNumber = GenomeDecoder::getNextExecutionNumber(genome, nodeAddressIntern);
}
if (origSequenceNumber == node + 1) {
nextExecutionNumber = GenomeDecoder::getNextExecutionNumber(genome, nodeAddressIntern);
}
if (origSequenceNumber == node) {
nodeAddress = nodeAddressIntern;
}
});
if (nodeAddress == 0) {
return;
}

//basic property mutation
//basic property mutation
if (data.numberGen1.randomBool()) {
if (data.numberGen1.randomBool()) {
if (data.numberGen1.randomBool()) {
GenomeDecoder::setNextInputExecutionNumber(
genome, nodeAddress, data.numberGen1.randomBool() ? data.numberGen1.randomByte() : lastExecutionNumber);
//adaptMutationId(data, constructor);
} else {
auto randomDelta = data.numberGen1.random(Const::CellBasicBytes - 1);
if (randomDelta == 0) { //no cell function type change
return;
}
if (randomDelta == Const::CellColorPos) { //no color change
return;
}
if (randomDelta == Const::CellAnglePos || randomDelta == Const::CellRequiredConnectionsPos) { //no structure change
return;
}
genome[nodeAddress + randomDelta] = data.numberGen1.randomByte();
auto randomByte = data.numberGen1.randomByte();
if (data.numberGen1.random() < 0.8f) {
randomByte = data.numberGen1.randomBool() ? prevExecutionNumber : nextExecutionNumber;
}
GenomeDecoder::setNextInputExecutionNumber(genome, nodeAddress, randomByte);
} else {
auto randomDelta = data.numberGen1.random(Const::CellBasicBytes - 1);
auto randomByte = data.numberGen1.randomByte();
if (randomDelta == 0) { //no cell function type change
return;
}
if (randomDelta == Const::CellColorPos) { //no color change
return;
}
if (randomDelta == Const::CellAnglePos || randomDelta == Const::CellRequiredConnectionsPos) { //no structure change
return;
}
genome[nodeAddress + randomDelta] = randomByte;
}
}

//cell function specific mutation
else {
auto nextCellFunctionDataSize = GenomeDecoder::getNextCellFunctionDataSize(genome, genomeSize, nodeAddress, false);
if (nextCellFunctionDataSize > 0) {
auto randomDelta = data.numberGen1.random(nextCellFunctionDataSize - 1);
auto cellFunction = GenomeDecoder::getNextCellFunctionType(genome, nodeAddress);
if (cellFunction == CellFunction_Constructor
&& (randomDelta == Const::ConstructorConstructionAngle1Pos
|| randomDelta == Const::ConstructorConstructionAngle2Pos)) { //no construction angles change
return;
}
genome[nodeAddress + Const::CellBasicBytes + randomDelta] = data.numberGen1.randomByte();
//adaptMutationId(data, constructor);
//cell function specific mutation
else {
auto nextCellFunctionDataSize = GenomeDecoder::getNextCellFunctionDataSize(genome, genomeSize, nodeAddress, false);
if (nextCellFunctionDataSize > 0) {
auto randomDelta = data.numberGen1.random(nextCellFunctionDataSize - 1);
auto cellFunction = GenomeDecoder::getNextCellFunctionType(genome, nodeAddress);
if (cellFunction == CellFunction_Constructor
&& (randomDelta == Const::ConstructorConstructionAngle1Pos
|| randomDelta == Const::ConstructorConstructionAngle2Pos)) { //no construction angles change
return;
}
genome[nodeAddress + Const::CellBasicBytes + randomDelta] = data.numberGen1.randomByte();
//adaptMutationId(data, constructor);
}
lastExecutionNumber = genome[nodeAddress + Const::CellInputExecutionNumberPos];
});
}
}

__inline__ __device__ void MutationProcessor::geometryMutation(SimulationData& data, Cell* cell)
Expand Down Expand Up @@ -417,6 +435,10 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat
int numSubGenomesSizeIndices;

int nodeAddress = 0;
uint8_t prevExecutionNumber = data.numberGen1.randomByte();
uint8_t nextExecutionNumber = data.numberGen1.randomByte();

//calculate addess where the new node should be inserted
if (data.numberGen1.randomBool() && genomeSize > Const::GenomeHeaderSize) {

//choose a random node position to a constructor with a subgenome
Expand All @@ -429,12 +451,13 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat
});
if (numConstructorsWithSubgenome > 0) {
auto randomIndex = data.numberGen1.random(numConstructorsWithSubgenome - 1);
int counter = 0;
auto counter = 0;
GenomeDecoder::executeForEachNodeRecursively(genome, genomeSize, true, false, [&](int depth, int nodeAddressIntern, int repetition) {
auto cellFunctionType = GenomeDecoder::getNextCellFunctionType(genome, nodeAddressIntern);
if (cellFunctionType == CellFunction_Constructor && !GenomeDecoder::isNextCellSelfReplication(genome, nodeAddressIntern)) {
if (randomIndex == counter) {
nodeAddress = nodeAddressIntern + Const::CellBasicBytes + Const::ConstructorFixedBytes + 3 + 1;
prevExecutionNumber = genome[nodeAddressIntern + Const::CellExecutionNumberPos];
}
++counter;
}
Expand All @@ -446,11 +469,11 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat
return;
}

//insert node
auto newColor = cell->color;
auto executionNumber = 0;
if (nodeAddress < genomeSize) {
newColor = GenomeDecoder::getNextCellColor(genome, nodeAddress);
executionNumber = GenomeDecoder::getNextExecutionNumber(genome, nodeAddress);
nextExecutionNumber = GenomeDecoder::getNextExecutionNumber(genome, nodeAddress);
}
auto newCellFunction = data.numberGen1.random(CellFunction_Count - 1);
auto makeSelfCopy = cudaSimulationParameters.cellFunctionConstructorMutationSelfReplication ? data.numberGen1.randomBool() : false;
Expand Down Expand Up @@ -478,11 +501,11 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat
data.numberGen1.randomBytes(targetGenome + nodeAddress, Const::CellBasicBytes);
GenomeDecoder::setNextCellFunctionType(targetGenome, nodeAddress, newCellFunction);
GenomeDecoder::setNextCellColor(targetGenome, nodeAddress, newColor);
if (data.numberGen1.random() < 0.9f) {
GenomeDecoder::setNextInputExecutionNumber(targetGenome, nodeAddress, executionNumber);
if (data.numberGen1.random() < 0.9f) { //fitting input execution number should be often
GenomeDecoder::setNextInputExecutionNumber(targetGenome, nodeAddress, data.numberGen1.randomBool() ? prevExecutionNumber : nextExecutionNumber);
}
if (data.numberGen1.random() < 0.9f) {
GenomeDecoder::setNextOutputBlocked(targetGenome, nodeAddress, false); //'output blocked' should be rare
GenomeDecoder::setNextOutputBlocked(targetGenome, nodeAddress, false); //non-blocking output should be often
}
GenomeDecoder::setRandomCellFunctionData(data, targetGenome, nodeAddress + Const::CellBasicBytes, newCellFunction, makeSelfCopy, Const::GenomeHeaderSize);
if (newCellFunction == CellFunction_Constructor && !makeSelfCopy) {
Expand Down Expand Up @@ -842,13 +865,20 @@ __inline__ __device__ void MutationProcessor::genomeColorMutation(SimulationData
genome, genomeSize, true, false, [&](int depth, int nodeAddress, int repetition) { GenomeDecoder::setNextCellColor(genome, nodeAddress, newColor); });
}

template <typename Func>
__inline__ __device__ void MutationProcessor::executeMultipleEvents(SimulationData& data, float probability, Func eventFunc)
{
for (int i = 0, j = toInt(probability); i < j; ++i) {
eventFunc();
}
if (isRandomEvent(data, probability)) {
eventFunc();
}
}

template <typename Func>
__inline__ __device__ void MutationProcessor::executeEvent(SimulationData& data, float probability, Func eventFunc)
{
//TODO avoid performance deterioration
//for (int i = 0, j = toInt(probability); i < j; ++i) {
// eventFunc();
//}
if (isRandomEvent(data, probability)) {
eventFunc();
}
Expand Down
Loading

0 comments on commit b261bac

Please sign in to comment.