Initial Commit
This commit is contained in:
parent
3114157395
commit
08cd9ca383
|
@ -0,0 +1,2 @@
|
|||
main.exe
|
||||
.vscode
|
|
@ -0,0 +1,220 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#define ITERATION 100
|
||||
#define POPULATIONCOUNT 20
|
||||
#define CROSSOVERCHANCE .5
|
||||
#define MUTATIONCHANCE .02
|
||||
#define CROSSOVERCOUNTPERITERATION 10
|
||||
#define POPULATIONSIZE 200
|
||||
#define BITCOUNT 12
|
||||
|
||||
const float ValuePeriod = (float)(1 << BITCOUNT);
|
||||
const unsigned int ValuePeriodMask = (1 << BITCOUNT) - 1;
|
||||
|
||||
struct Chromosome
|
||||
{
|
||||
unsigned int x1;
|
||||
unsigned int x2;
|
||||
};
|
||||
|
||||
unsigned int GetRandomValue() { return rand() & ValuePeriodMask; }
|
||||
float GetRandomPercentage()
|
||||
{
|
||||
// RAND_MAX in Windows causes the rand values to be between 0 and 32767
|
||||
// So to overcome we get two random numbers and bitshift the one of them
|
||||
int random = rand() << 15 | rand();
|
||||
return float(random % 1000000) / 1000000.0;
|
||||
}
|
||||
|
||||
float GetX1(unsigned int value) { return -1.5 + value * (4.0 / ValuePeriod); }
|
||||
float GetX2(unsigned int value) { return value * (5.0 / ValuePeriod); }
|
||||
|
||||
float GetFitnessScore(const Chromosome &chromosome)
|
||||
{
|
||||
float x1 = GetX1(chromosome.x1);
|
||||
float x2 = GetX2(chromosome.x2);
|
||||
|
||||
float score = 40.0;
|
||||
score -= 4.5 * x1;
|
||||
score += 4.0 * x2;
|
||||
score -= x1 * x1;
|
||||
score -= 2.0 * x2 * x2;
|
||||
score += 2.0 * x1 * x2;
|
||||
score -= x1 * x1 * x1 * x1;
|
||||
score += 2.0 * x1 * x1 * x2;
|
||||
return score;
|
||||
}
|
||||
|
||||
void Initialize(Chromosome &chromosome)
|
||||
{
|
||||
chromosome.x1 = GetRandomValue();
|
||||
chromosome.x2 = GetRandomValue();
|
||||
}
|
||||
|
||||
unsigned int InvertBits(unsigned int &value) { return (~value) & ValuePeriodMask; }
|
||||
unsigned int GetRandomBits(float chance)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
for (size_t i = 0; i < BITCOUNT; i++)
|
||||
if (GetRandomPercentage() < chance)
|
||||
result += 1 << i;
|
||||
|
||||
return result & ValuePeriodMask;
|
||||
}
|
||||
|
||||
void Mutate(Chromosome &chromosome)
|
||||
{
|
||||
unsigned int mutationBitsX1 = GetRandomBits(MUTATIONCHANCE);
|
||||
unsigned int mutationBitsX2 = GetRandomBits(MUTATIONCHANCE);
|
||||
|
||||
chromosome.x1 ^= mutationBitsX1;
|
||||
chromosome.x2 ^= mutationBitsX2;
|
||||
}
|
||||
|
||||
Chromosome Crossover(Chromosome &chromosomeLeft, Chromosome &chromosomeRight)
|
||||
{
|
||||
Chromosome result = Chromosome();
|
||||
|
||||
unsigned int crossoverBitsX1 = GetRandomBits(CROSSOVERCHANCE);
|
||||
unsigned int crossoverBitsX2 = GetRandomBits(CROSSOVERCHANCE);
|
||||
|
||||
result.x1 = chromosomeLeft.x1 & crossoverBitsX1;
|
||||
result.x1 |= chromosomeRight.x1 & InvertBits(crossoverBitsX1);
|
||||
|
||||
result.x2 = chromosomeLeft.x2 & crossoverBitsX2;
|
||||
result.x2 |= chromosomeRight.x2 & InvertBits(crossoverBitsX2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void UpdateFitnessScores(Chromosome *populationPointer, float *fitnessPointer)
|
||||
{
|
||||
for (size_t i = 0; i < POPULATIONSIZE; i++)
|
||||
*(fitnessPointer++) = GetFitnessScore(*(populationPointer++));
|
||||
}
|
||||
|
||||
Chromosome *GetRandomChromosome(Chromosome *populationPointer) { return populationPointer + rand() % POPULATIONSIZE; }
|
||||
Chromosome *GetRandomCumulativeChromosome(Chromosome *populationPointer, float *fitnessPointer)
|
||||
{
|
||||
float sumOfScores = 0.0;
|
||||
float cumulativeFloat = 0.0;
|
||||
float randomPoint = GetRandomPercentage();
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < POPULATIONSIZE; i++)
|
||||
sumOfScores += *(fitnessPointer + i);
|
||||
|
||||
for (i = 0; i < POPULATIONSIZE; i++)
|
||||
{
|
||||
cumulativeFloat += *(fitnessPointer + i) / sumOfScores;
|
||||
|
||||
if (randomPoint <= cumulativeFloat)
|
||||
return populationPointer + i;
|
||||
}
|
||||
|
||||
return populationPointer;
|
||||
}
|
||||
|
||||
Chromosome *GetFittest(Chromosome *populationPointer, float *fitnessPointer)
|
||||
{
|
||||
unsigned int fittestIndex = 0;
|
||||
for (size_t i = 0; i < POPULATIONSIZE; i++)
|
||||
if (*(fitnessPointer + i) > *(fitnessPointer + fittestIndex))
|
||||
fittestIndex = i;
|
||||
|
||||
return populationPointer + fittestIndex;
|
||||
}
|
||||
|
||||
Chromosome *GetElitistOffSpring(Chromosome *fittest, Chromosome *populationPointer)
|
||||
{
|
||||
Chromosome *offspring = nullptr;
|
||||
|
||||
do
|
||||
offspring = GetRandomChromosome(populationPointer);
|
||||
while (fittest == offspring);
|
||||
|
||||
return offspring;
|
||||
}
|
||||
|
||||
void SortScores(float *scores)
|
||||
{
|
||||
float temp;
|
||||
for (size_t i = 0; i < POPULATIONCOUNT; i++)
|
||||
for (size_t j = i + 1; j < POPULATIONCOUNT; j++)
|
||||
if (*(scores + i) > *(scores + j))
|
||||
{
|
||||
temp = *(scores + i);
|
||||
*(scores + i) = *(scores + j);
|
||||
*(scores + j) = temp;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Chromosome population[POPULATIONSIZE];
|
||||
float fitnessScores[POPULATIONSIZE];
|
||||
float fitnessScoreRecord[POPULATIONCOUNT];
|
||||
Chromosome *offspring = nullptr;
|
||||
Chromosome *left = nullptr;
|
||||
Chromosome *right = nullptr;
|
||||
Chromosome *fittest = nullptr;
|
||||
int i;
|
||||
int generation;
|
||||
int crossoverCounter;
|
||||
int mutationIndex;
|
||||
int populationCounter;
|
||||
|
||||
srand(0);
|
||||
|
||||
for (populationCounter = 0; populationCounter < POPULATIONCOUNT; populationCounter++)
|
||||
{
|
||||
for (i = 0; i < POPULATIONSIZE; i++)
|
||||
Initialize(population[i]);
|
||||
UpdateFitnessScores(population, fitnessScores);
|
||||
fittest = GetFittest(population, fitnessScores);
|
||||
|
||||
for (generation = 0; generation < ITERATION; generation++)
|
||||
{
|
||||
for (crossoverCounter = 0; crossoverCounter < CROSSOVERCOUNTPERITERATION; crossoverCounter++)
|
||||
{
|
||||
offspring = GetElitistOffSpring(fittest, population);
|
||||
|
||||
left = GetRandomCumulativeChromosome(population, fitnessScores);
|
||||
right = GetRandomCumulativeChromosome(population, fitnessScores);
|
||||
(*offspring) = Crossover(*left, *right);
|
||||
}
|
||||
|
||||
// Mutate all except the Fittest
|
||||
for (mutationIndex = 0; mutationIndex < POPULATIONSIZE; mutationIndex++)
|
||||
if (population + mutationIndex != fittest)
|
||||
Mutate(*(population + mutationIndex));
|
||||
|
||||
UpdateFitnessScores(population, fitnessScores);
|
||||
fittest = GetFittest(population, fitnessScores);
|
||||
|
||||
// std::cout << "Fittest Score: " << GetFitnessScore(*fittest) << "\n";
|
||||
// std::cout << "x1: " << GetX1(fittest->x1) << "\n";
|
||||
// std::cout << "x2: " << GetX2(fittest->x2) << "\n";
|
||||
// std::cout << "-----End of Generation " << generation << "-----\n";
|
||||
}
|
||||
fitnessScoreRecord[populationCounter] = GetFitnessScore(*fittest);
|
||||
}
|
||||
|
||||
SortScores(fitnessScoreRecord);
|
||||
|
||||
std::cout << "Population Size: " << POPULATIONSIZE << "\n";
|
||||
std::cout << "Population Count: " << POPULATIONCOUNT << "\n";
|
||||
std::cout << "Iteration Count: " << ITERATION << "\n";
|
||||
std::cout << "Crossover Per Iteration: " << CROSSOVERCOUNTPERITERATION << "\n";
|
||||
std::cout << "Crossover Ratio: " << CROSSOVERCHANCE << "\n";
|
||||
std::cout << "Mutation Ratio: " << MUTATIONCHANCE << "\n";
|
||||
std::cout << "Bits Per Value: " << BITCOUNT << "\n";
|
||||
std::cout << "-----------------\n";
|
||||
std::cout << "Best: " << fitnessScoreRecord[POPULATIONCOUNT - 1] << "\n";
|
||||
std::cout << "Median: " << fitnessScoreRecord[(POPULATIONCOUNT - 1) / 2] << "\n";
|
||||
std::cout << "Worst: " << fitnessScoreRecord[0] << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue