Add Generation

Some more complex algorithms are not yet implemented.
This commit is contained in:
Joscha 2017-04-27 20:56:45 +00:00
parent 0d686b2008
commit 2c37b90ad8
3 changed files with 156 additions and 1 deletions

View file

@ -8,7 +8,8 @@ SOURCEFILES = cpp
SRCDIR = src
TMPDIR = build
TARGET = gross
FILES = Chromosome Fitness main
#FILES = Chromosome Fitness Generation main
FILES = Chromosome Fitness Generation main
#SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES))
OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES))

97
src/Generation.cpp Normal file
View file

@ -0,0 +1,97 @@
#include "Generation.hpp"
size_t Generation::size = 500;
size_t Generation::living = Generation::size*0.25;
Fitness* Generation::fitness;
std::mt19937_64* Generation::re;
Generation::Generation()
{
this->individuals.reserve(Generation::size);
}
void Generation::updateFitness()
{
for (auto individual : this->individuals) {
if (!individual.fitnessEvaluated) {
individual.fitness = Generation::fitness->of(individual.chromosome);
individual.fitnessEvaluated = true;
}
}
}
void Generation::cull(CullType algorithm)
{
// sort by fitness
std::sort(
this->individuals.begin(),
this->individuals.end(),
[](Generation::Individual& a, Generation::Individual& b) -> bool {
return a.fitness < b.fitness;
}
);
// apply correct culling algorithm
switch (algorithm) {
case Generation::CUTOFF: this->cullCutoff(); break;
case Generation::ROULETTE: this->cullRoulette(); break;
}
}
void Generation::reproduce(float crossover)
{
// sort by fitness/available
std::sort(
this->individuals.begin(),
this->individuals.end(),
[](Generation::Individual& a, Generation::Individual& b) -> bool {
if (a.alive && b.alive) {
return a.fitness < b.fitness;
} else {
return a.alive;
}
}
);
// reproduce according to parameters
std::uniform_int_distribution<> alivedist(0, Generation::living-1);
std::uniform_real_distribution<> crossoverdist(0, 1);
auto it = this->individuals.begin() + Generation::living;
for (; it!=this->individuals.end(); ++it) {
auto father = this->individuals.begin() + alivedist(*Generation::re);
if (crossoverdist(*Generation::re) <= crossover) {
auto mother = this->individuals.begin() + alivedist(*Generation::re);
it->chromosome = Chromosome(father->chromosome, mother->chromosome);
} else {
it->chromosome = father->chromosome;
}
it->alive = true;
it->fitness = 0;
it->fitnessEvaluated = false;
it->chromosome.mutate();
}
}
void Generation::cullCutoff()
{
auto it = this->individuals.begin() + Generation::living;
for (; it!=this->individuals.end(); ++it) {
it->alive = false;
}
}
void Generation::cullRoulette()
{
// TODO: implement this
}

57
src/Generation.hpp Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include <random>
#include <vector>
#include "Chromosome.hpp"
#include "Fitness.hpp"
class Generation
{
public:
static size_t size;
static size_t living;
static Fitness* fitness;
static std::mt19937_64* re;
Generation();
enum CullType
{
CUTOFF,
ROULETTE
};
void updateFitness();
void cull(CullType algorithm=Generation::ROULETTE);
void reproduce(float crossover=0.5); // how often a child is the result of two parents,
// and not simply mutation.
struct Individual
{
// Individual(Chromosome& father, Chromosome& mother) : chromosome(father, mother) {}
Chromosome chromosome;
unsigned long long fitness = 0;
bool fitnessEvaluated = false;
bool alive = true;
};
std::vector<Individual> individuals;
private:
// all of the culling algorithms can assume:
// - sorted array
// - alive flag set to true on all individuals
void cullCutoff();
void cullRoulette();
// pool of Chromosomes
// sort pool?
// min/max/median
// extract stats
// calculate fitness
// cull/selection
// render full generation? No
};