Reimplement and test Generation

This commit is contained in:
Joscha 2017-05-20 23:59:50 +00:00
parent c10a12f29c
commit 5c10ba4a78
4 changed files with 160 additions and 54 deletions

View file

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

View file

@ -4,10 +4,109 @@
size_t Generation::size = 500;
size_t Generation::living = Generation::size*0.25;
float Generation::crossover = 0.25;
Fitness* Generation::fitness;
std::minstd_rand* Generation::re;
Generation::Generation()
{
this->individuals.resize(Generation::size, {Chromosome(), 0, false, false});
}
void Generation::sort()
{
std::sort(
this->individuals.begin(),
this->individuals.end(),
[](Generation::Individual& a, Generation::Individual& b) -> bool {
if (a.alive && b.alive) {
if (a.fitnessEvaluated && b.fitnessEvaluated) {
return a.fitness < b.fitness;
} else {
return a.fitnessEvaluated;
}
} else {
return a.alive;
}
}
);
}
void Generation::advance(unsigned int generations)
{
for (unsigned int i=0; i<generations; ++i) {
// #define debugcount {int alive=0,fitness=0;for(auto&i:individuals){i.alive?++alive:1;i.fitnessEvaluated?++fitness:1;}std::cout<<" -> alive: "<<alive<<", fitness: "<<fitness<<std::endl;}
// std::cout << "-- updating fitness" << std::endl;
// debugcount
this->updateFitness();
// std::cout << "-- sorting" << std::endl;
// debugcount
this->sort();
// std::cout << "-- culling" << std::endl;
// debugcount
this->cull();
// std::cout << "-- sorting" << std::endl;
// debugcount
this->sort();
// std::cout << "-- reproducing" << std::endl;
// debugcount
this->reproduce();
// #undef debugcount
}
}
void Generation::updateFitness()
{
for (auto& individual : this->individuals) {
if (!individual.fitnessEvaluated) {
individual.fitness = Generation::fitness->of(individual.chromosome);
individual.fitnessEvaluated = true;
}
}
}
void Generation::cull()
{
auto it = this->individuals.begin() + Generation::living;
for (; it!=this->individuals.end(); ++it) {
it->alive = false;
}
}
void Generation::reproduce()
{
// reproduce according to parameter(s)
std::uniform_int_distribution<> alivedist(0, Generation::living-1);
std::uniform_real_distribution<> crossoverdist(0, 1);
for (auto& individual : this->individuals) {
if (individual.alive) continue;
auto father = this->individuals.begin() + alivedist(*Generation::re);
if (crossoverdist(*Generation::re) < crossover) {
auto mother = this->individuals.begin() + alivedist(*Generation::re);
individual.chromosome = Chromosome(father->chromosome, mother->chromosome);
} else {
individual.chromosome = father->chromosome;
}
individual.alive = true;
individual.fitness = 0; // technically unnecessary, but who cares
individual.fitnessEvaluated = false;
individual.chromosome.mutate();
}
}
/*
Generation::Generation()
{
this->individuals.resize(Generation::size, {Chromosome(), 0, false, true});
@ -95,3 +194,4 @@ void Generation::cullRoulette()
{
// TODO: implement this
}
*/

View file

@ -10,48 +10,32 @@
class Generation
{
public:
static size_t size;
static size_t living;
static Fitness* fitness;
static std::minstd_rand* 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;
};
static size_t size; // total size of generation
static size_t living; // amount of chromosomes to stay alive between generations
static float crossover; // probability for a new chromosome to have two parents
static Fitness* fitness;
static std::minstd_rand* re;
Generation();
// sorts by
// 1. alive ones first
// 2. ones with fitness first
// 3. ones with lowest fitness first
void sort();
void advance(unsigned int generations=1);
void updateFitness();
void cull();
void reproduce();
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
};

View file

@ -4,6 +4,7 @@
#include <SFML/Graphics.hpp>
#include "Chromosome.hpp"
#include "Fitness.hpp"
#include "Generation.hpp"
int main()
{
@ -12,26 +13,36 @@ int main()
std::minstd_rand randomEngine;
randomEngine.seed(time(nullptr));
Chromosome::allowGeneType(Gene::Circle);
Chromosome::allowGeneType(Gene::Triangle);
Chromosome::re = &randomEngine;
Gene::re = &randomEngine;
Generation::re = &randomEngine;
// Chromosome::allowGeneType(Gene::Circle);
Chromosome::allowGeneType(Gene::Triangle);
Generation::size = 100;
Generation::living = 10;
Generation::crossover = 0;
Fitness fitn;
fitn.loadTarget("tom-face.png");
// fitn.loadTarget("tom-face.png");
fitn.loadTarget("firefox.png");
// fitn.loadTarget("goldman_sachs.jpg");
fitn.loadShader("compare.glsl");
Gene::size = sf::Vector2f(fitn.target.getSize());
Generation::fitness = &fitn;
Chromosome a;
for (int i=0; i<1000; ++i) a.mutate();
Chromosome b(a);
for (int i=0; i<10; ++i) b.mutate();
Chromosome c(a);
Chromosome d(a, b);
Generation gen;
std::cout << a.length() << " | " << b.length() << " | " << c.length() << " | " << d.length() << std::endl;
// Chromosome a;
// for (int i=0; i<1000; ++i) a.mutate();
// Chromosome b(a);
// for (int i=0; i<10; ++i) b.mutate();
// Chromosome c(a);
// Chromosome d(a, b);
// std::cout << a.length() << " | " << b.length() << " | " << c.length() << " | " << d.length() << std::endl;
sf::Sprite ts(fitn.target.getTexture());
sf::Sprite cs(fitn.chromosome.getTexture());
@ -39,19 +50,31 @@ int main()
sf::RenderWindow window(sf::VideoMode(winW, winH), "gross");
// window.setMouseCursorVisible(false);
int gencnt = 0;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::KeyPressed) {
}
// if (event.type == sf::Event::KeyPressed) {
// std::cout << "Trying to advance generation" << std::endl;
// gen.advance();
// std::cout << "Advanced generation" << std::endl;
// }
}
gen.advance();
std::cout << "Generation: " << ++gencnt << " (length: " << gen.individuals[0].chromosome.length() << ")" << std::endl;
// display results
window.clear();
fitn.render(a); cs.setPosition( 0, 0); window.draw(cs);
fitn.render(b); cs.setPosition(240, 0); window.draw(cs);
fitn.render(c); cs.setPosition( 0, 240); window.draw(cs);
fitn.render(d); cs.setPosition(240, 240); window.draw(cs);
ts.setPosition( 0, 0); window.draw(ts);
fitn.render(gen.individuals[0].chromosome); cs.setPosition(240, 0); window.draw(cs);
fitn.render(gen.individuals[9].chromosome); cs.setPosition(240, 240); window.draw(cs);
// fitn.render(a); cs.setPosition( 0, 0); window.draw(cs);
// fitn.render(b); cs.setPosition(240, 0); window.draw(cs);
// fitn.render(c); cs.setPosition( 0, 240); window.draw(cs);
// fitn.render(d); cs.setPosition(240, 240); window.draw(cs);
window.display();
// std::cout << "Generation finished: " << ++gencnt << " (winner's length: "