Reimplement and test Generation
This commit is contained in:
parent
c10a12f29c
commit
5c10ba4a78
4 changed files with 160 additions and 54 deletions
3
Makefile
3
Makefile
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
57
src/main.cpp
57
src/main.cpp
|
|
@ -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: "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue