Skip to content

Commit

Permalink
insert mutation specially favors subgenomes
Browse files Browse the repository at this point in the history
  • Loading branch information
chrxh committed Jul 5, 2023
1 parent 0abbd4c commit c791bad
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 33 deletions.
82 changes: 50 additions & 32 deletions source/EngineGpuKernels/GenomeDecoder.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,6 @@ struct GenomeHeader
class GenomeDecoder
{
public:
//automatic increment genomeReadPosition
__inline__ __device__ static bool readBool(ConstructorFunction& constructor);
__inline__ __device__ static uint8_t readByte(ConstructorFunction& constructor);
__inline__ __device__ static int readOptionalByte(ConstructorFunction& constructor, int moduloValue);
__inline__ __device__ static int readWord(ConstructorFunction& constructor);
__inline__ __device__ static float readFloat(ConstructorFunction& constructor); //return values from -1 to 1
__inline__ __device__ static float readEnergy(ConstructorFunction& constructor); //return values from 36 to 1060
__inline__ __device__ static float readAngle(ConstructorFunction& constructor);

__inline__ __device__ static bool isAtFirstNode(ConstructorFunction const& constructor);
__inline__ __device__ static bool isAtLastNode(ConstructorFunction const& constructor);
__inline__ __device__ static bool isFinished(ConstructorFunction const& constructor);
__inline__ __device__ static bool isFinishedSingleConstruction(ConstructorFunction const& constructor);
__inline__ __device__ static bool isSeparating(ConstructorFunction const& constructor);
template <typename ConstructorOrInjector>
__inline__ __device__ static bool containsSelfReplication(ConstructorOrInjector const& cellFunction);

template <typename GenomeHolderSource, typename GenomeHolderTarget>
__inline__ __device__ static void copyGenome(SimulationData& data, GenomeHolderSource& source, GenomeHolderTarget& target);
__inline__ __device__ static GenomeHeader readGenomeHeader(ConstructorFunction const& constructor);
__inline__ __device__ static int readWord(uint8_t* genome, int nodeAddress);
__inline__ __device__ static void writeWord(uint8_t* genome, int address, int word);
__inline__ __device__ static bool convertByteToBool(uint8_t b);
__inline__ __device__ static int convertBytesToWord(uint8_t b1, uint8_t b2);
__inline__ __device__ static void convertWordToBytes(int word, uint8_t& b1, uint8_t& b2);
__inline__ __device__ static uint8_t convertAngleToByte(float angle);
__inline__ __device__ static uint8_t convertOptionalByteToByte(int value);


template <typename Func>
__inline__ __device__ static void executeForEachNode(uint8_t* genome, int genomeSize, Func func);
template <typename Func>
Expand All @@ -62,7 +33,8 @@ public:
int genomeSize,
bool considerZeroSubGenomes,
int* subGenomesSizeIndices = nullptr,
int* numSubGenomesSizeIndices = nullptr);
int* numSubGenomesSizeIndices = nullptr,
int randomRefIndex = 0);
__inline__ __device__ static void setRandomCellFunctionData(
SimulationData& data,
uint8_t* genome,
Expand All @@ -84,6 +56,8 @@ public:
__inline__ __device__ static void setNextRequiredConnections(uint8_t* genome, int nodeAddress, uint8_t angle);
__inline__ __device__ static void setNextConstructionAngle1(uint8_t* genome, int nodeAddress, uint8_t angle);
__inline__ __device__ static void setNextConstructionAngle2(uint8_t* genome, int nodeAddress, uint8_t angle);
__inline__ __device__ static void setNextConstructorSeparation(uint8_t* genome, int nodeAddress, bool separation);

__inline__ __device__ static int
getNextSubGenomeSize(uint8_t* genome, int genomeSize, int nodeAddress); //prerequisites: (constructor or injector) and !makeSelfCopy
__inline__ __device__ static int getCellFunctionDataSize(
Expand All @@ -92,6 +66,37 @@ public:
int genomeSize); //genomeSize only relevant for cellFunction = constructor or injector
__inline__ __device__ static bool hasSelfCopy(uint8_t* genome, int genomeSize);


//automatic increment genomeReadPosition
__inline__ __device__ static bool readBool(ConstructorFunction& constructor);
__inline__ __device__ static uint8_t readByte(ConstructorFunction& constructor);
__inline__ __device__ static int readOptionalByte(ConstructorFunction& constructor, int moduloValue);
__inline__ __device__ static int readWord(ConstructorFunction& constructor);
__inline__ __device__ static float readFloat(ConstructorFunction& constructor); //return values from -1 to 1
__inline__ __device__ static float readEnergy(ConstructorFunction& constructor); //return values from 36 to 1060
__inline__ __device__ static float readAngle(ConstructorFunction& constructor);

__inline__ __device__ static bool isAtFirstNode(ConstructorFunction const& constructor);
__inline__ __device__ static bool isAtLastNode(ConstructorFunction const& constructor);
__inline__ __device__ static bool isFinished(ConstructorFunction const& constructor);
__inline__ __device__ static bool isFinishedSingleConstruction(ConstructorFunction const& constructor);
__inline__ __device__ static bool isSeparating(ConstructorFunction const& constructor);
template <typename ConstructorOrInjector>
__inline__ __device__ static bool containsSelfReplication(ConstructorOrInjector const& cellFunction);

template <typename GenomeHolderSource, typename GenomeHolderTarget>
__inline__ __device__ static void copyGenome(SimulationData& data, GenomeHolderSource& source, GenomeHolderTarget& target);
__inline__ __device__ static GenomeHeader readGenomeHeader(ConstructorFunction const& constructor);
__inline__ __device__ static int readWord(uint8_t* genome, int nodeAddress);
__inline__ __device__ static void writeWord(uint8_t* genome, int address, int word);

__inline__ __device__ static bool convertByteToBool(uint8_t b);
__inline__ __device__ static uint8_t convertBoolToByte(bool value);
__inline__ __device__ static int convertBytesToWord(uint8_t b1, uint8_t b2);
__inline__ __device__ static void convertWordToBytes(int word, uint8_t& b1, uint8_t& b2);
__inline__ __device__ static uint8_t convertAngleToByte(float angle);
__inline__ __device__ static uint8_t convertOptionalByteToByte(int value);

static auto constexpr MAX_SUBGENOME_RECURSION_DEPTH = 30;
};

Expand Down Expand Up @@ -238,6 +243,11 @@ __inline__ __device__ bool GenomeDecoder::convertByteToBool(uint8_t b)
return static_cast<int8_t>(b) > 0;
}

__inline__ __device__ uint8_t GenomeDecoder::convertBoolToByte(bool value)
{
return value ? 1 : 0;
}

__inline__ __device__ int GenomeDecoder::convertBytesToWord(uint8_t b1, uint8_t b2)
{
return static_cast<int>(b1) | (static_cast<int>(b2 << 8));
Expand Down Expand Up @@ -346,7 +356,8 @@ __inline__ __device__ int GenomeDecoder::getRandomGenomeNodeAddress(
int genomeSize,
bool considerZeroSubGenomes,
int* subGenomesSizeIndices,
int* numSubGenomesSizeIndices)
int* numSubGenomesSizeIndices,
int randomRefIndex)
{
if (numSubGenomesSizeIndices) {
*numSubGenomesSizeIndices = 0;
Expand All @@ -357,7 +368,9 @@ __inline__ __device__ int GenomeDecoder::getRandomGenomeNodeAddress(
if (genomeSize == Const::GenomeHeaderSize) {
return Const::GenomeHeaderSize;
}
auto randomRefIndex = data.numberGen1.random(genomeSize - 1);
if (randomRefIndex == 0) {
randomRefIndex = data.numberGen1.random(genomeSize - 1);
}

int result = 0;
for (int depth = 0; depth < MAX_SUBGENOME_RECURSION_DEPTH; ++depth) {
Expand Down Expand Up @@ -557,6 +570,11 @@ __inline__ __device__ void GenomeDecoder::setNextConstructionAngle2(uint8_t* gen
genome[nodeAddress + Const::CellBasicBytes + Const::ConstructorConstructionAngle2Pos] = angle;
}

__inline__ __device__ void GenomeDecoder::setNextConstructorSeparation(uint8_t* genome, int nodeAddress, bool separation)
{
genome[nodeAddress + Const::CellBasicBytes + Const::ConstructorFixedBytes + 3 + Const::ConstructorSeparation] = convertBoolToByte(separation);
}

__inline__ __device__ int GenomeDecoder::getNextSubGenomeSize(uint8_t* genome, int genomeSize, int nodeAddress)
{
auto cellFunction = getNextCellFunctionType(genome, nodeAddress);
Expand Down
35 changes: 34 additions & 1 deletion source/EngineGpuKernels/MutationProcessor.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,9 @@ __inline__ __device__ void MutationProcessor::cellFunctionMutation(SimulationDat
}
GenomeDecoder::setNextCellFunctionType(targetGenome, nodeAddress, newCellFunction);
GenomeDecoder::setRandomCellFunctionData(data, targetGenome, nodeAddress + Const::CellBasicBytes, newCellFunction, makeSelfCopy, Const::GenomeHeaderSize);
if (!GenomeDecoder::isNextCellSelfCopy(targetGenome, nodeAddress)) {
GenomeDecoder::setNextConstructorSeparation(targetGenome, nodeAddress, false); //currently no subgenome with separation property wished
}

for (int i = nodeAddress + Const::CellBasicBytes + origCellFunctionSize; i < genomeSize; ++i) {
targetGenome[i + sizeDelta] = genome[i];
Expand All @@ -359,7 +362,34 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat

int subGenomesSizeIndices[GenomeDecoder::MAX_SUBGENOME_RECURSION_DEPTH + 1];
int numSubGenomesSizeIndices;
auto nodeAddress = GenomeDecoder::getRandomGenomeNodeAddress(data, genome, genomeSize, true, subGenomesSizeIndices, &numSubGenomesSizeIndices);

int nodeAddress = 0;
if (data.numberGen1.randomBool() && genomeSize > Const::GenomeHeaderSize) {

//choose a random node position to a constructor with a subgenome
int numConstructorsWithSubgenome = 0;
GenomeDecoder::executeForEachNodeRecursively(genome, genomeSize, [&](int depth, int nodeAddressIntern) {
auto cellFunctionType = GenomeDecoder::getNextCellFunctionType(genome, nodeAddressIntern);
if (cellFunctionType == CellFunction_Constructor && !GenomeDecoder::isNextCellSelfCopy(genome, nodeAddressIntern)) {
++numConstructorsWithSubgenome;
}
});
if (numConstructorsWithSubgenome > 0) {
auto randomIndex = data.numberGen1.random(numConstructorsWithSubgenome - 1);
int counter = 0;
GenomeDecoder::executeForEachNodeRecursively(genome, genomeSize, [&](int depth, int nodeAddressIntern) {
auto cellFunctionType = GenomeDecoder::getNextCellFunctionType(genome, nodeAddressIntern);
if (cellFunctionType == CellFunction_Constructor && !GenomeDecoder::isNextCellSelfCopy(genome, nodeAddressIntern)) {
if (randomIndex == counter) {
nodeAddress = nodeAddressIntern + Const::CellBasicBytes + Const::ConstructorFixedBytes + 3 + 1;
}
++counter;
}
});
}
}
nodeAddress = GenomeDecoder::getRandomGenomeNodeAddress(data, genome, genomeSize, true, subGenomesSizeIndices, &numSubGenomesSizeIndices, nodeAddress);


auto newColor = cell->color;
if (nodeAddress < genomeSize) {
Expand Down Expand Up @@ -392,6 +422,9 @@ __inline__ __device__ void MutationProcessor::insertMutation(SimulationData& dat
GenomeDecoder::setNextCellFunctionType(targetGenome, nodeAddress, newCellFunction);
GenomeDecoder::setNextCellColor(targetGenome, nodeAddress, newColor);
GenomeDecoder::setRandomCellFunctionData(data, targetGenome, nodeAddress + Const::CellBasicBytes, newCellFunction, makeSelfCopy, Const::GenomeHeaderSize);
if (!GenomeDecoder::isNextCellSelfCopy(targetGenome, nodeAddress)) {
GenomeDecoder::setNextConstructorSeparation(targetGenome, nodeAddress, false); //currently no subgenome with separation property wished
}

for (int i = nodeAddress; i < genomeSize; ++i) {
targetGenome[i + sizeDelta] = genome[i];
Expand Down
3 changes: 3 additions & 0 deletions source/EngineInterface/GenomeConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ namespace Const
auto constexpr CellAnglePos = 1;
auto constexpr CellRequiredConnectionsPos = 3;
auto constexpr CellColorPos = 5;

auto constexpr ConstructorConstructionAngle1Pos = 3;
auto constexpr ConstructorConstructionAngle2Pos = 4;

auto constexpr ConstructorSeparation = 2;

auto constexpr CellBasicBytes = 8;
auto constexpr NeuronBytes = 72;
auto constexpr TransmitterBytes = 1;
Expand Down

0 comments on commit c791bad

Please sign in to comment.