From 2c37b90ad8a797a3ccae794388d8433789498175 Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 27 Apr 2017 20:56:45 +0000 Subject: [PATCH] Add Generation Some more complex algorithms are not yet implemented. --- Makefile | 3 +- src/Generation.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++ src/Generation.hpp | 57 +++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/Generation.cpp create mode 100644 src/Generation.hpp diff --git a/Makefile b/Makefile index f38ba2c..b062042 100644 --- a/Makefile +++ b/Makefile @@ -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)) diff --git a/src/Generation.cpp b/src/Generation.cpp new file mode 100644 index 0000000..6a3480e --- /dev/null +++ b/src/Generation.cpp @@ -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 +} diff --git a/src/Generation.hpp b/src/Generation.hpp new file mode 100644 index 0000000..bfebb78 --- /dev/null +++ b/src/Generation.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#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 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 +};