Elitism and CopyChromosomes()
This commit is contained in:
197
Population.cpp
197
Population.cpp
@@ -17,12 +17,16 @@
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
//
|
||||
namespace BitEvolver
|
||||
{
|
||||
//
|
||||
using std::string;
|
||||
using std::stringstream;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
@@ -45,6 +49,11 @@ namespace BitEvolver
|
||||
this->evolution_number = 0;
|
||||
this->population_size = Population::DEFAULT_POPULATION_SIZE;
|
||||
|
||||
//
|
||||
this->SetElitismType(Population::DEFAULT_ELITISM_TYPE);
|
||||
this->SetElitismRate(Population::DEFAULT_ELITISM_RATE);
|
||||
this->SetElitismCount(Population::DEFAULT_ELITISM_COUNT);
|
||||
|
||||
//
|
||||
this->SetCrossoverType(Population::DEFAULT_CROSSOVER_TYPE);
|
||||
this->SetCrossoverPoint(Population::DEFAULT_CROSSOVER_POINT);
|
||||
@@ -198,6 +207,48 @@ namespace BitEvolver
|
||||
return this->mutation_rate;
|
||||
}
|
||||
|
||||
//
|
||||
void Population::SetElitismType(Enums::ElitismType t)
|
||||
{
|
||||
//
|
||||
this->elitism_type = t;
|
||||
}
|
||||
|
||||
//
|
||||
Enums::ElitismType Population::GetElitismType()
|
||||
{
|
||||
//
|
||||
return this->elitism_type;
|
||||
}
|
||||
|
||||
//
|
||||
void Population::SetElitismRate(double r)
|
||||
{
|
||||
//
|
||||
this->elitism_rate = r;
|
||||
}
|
||||
|
||||
//
|
||||
double Population::GetElitismRate()
|
||||
{
|
||||
//
|
||||
return this->elitism_rate;
|
||||
}
|
||||
|
||||
//
|
||||
void Population::SetElitismCount(int c)
|
||||
{
|
||||
//
|
||||
this->elitism_count = c;
|
||||
}
|
||||
|
||||
//
|
||||
int Population::GetElitismCount()
|
||||
{
|
||||
//
|
||||
return this->elitism_count;
|
||||
}
|
||||
|
||||
//
|
||||
void Population::EvaluateFitness(std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback)
|
||||
{
|
||||
@@ -299,11 +350,6 @@ namespace BitEvolver
|
||||
new std::vector<std::shared_ptr<Chromosome>>()
|
||||
);
|
||||
|
||||
// Start the new population off with our champion,
|
||||
// so the best score always carries over (elitism = 1 unit)
|
||||
#warning "Elitism is only 1 right now"
|
||||
population_new->push_back(this->chromosomes[0]);
|
||||
|
||||
// Breed the new population
|
||||
this->BreedNewPopulation(population_new, (int)this->chromosomes.size());
|
||||
|
||||
@@ -403,7 +449,6 @@ namespace BitEvolver
|
||||
void Population::BreedNewPopulation(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new, int size)
|
||||
{
|
||||
//
|
||||
std::shared_ptr<RouletteWheel> wheel;
|
||||
std::vector<std::shared_ptr<std::thread>> threads;
|
||||
std::shared_ptr<std::thread> thread;
|
||||
int
|
||||
@@ -414,21 +459,25 @@ namespace BitEvolver
|
||||
// First, populate the roulette wheel
|
||||
this->roulette_wheel->SetChromosomes(this->chromosomes);
|
||||
|
||||
//
|
||||
thread_count = this->GetThreadCountSuggestion();
|
||||
// Next, seed the population with elites
|
||||
this->SeedPopulationWithElites(population_new);
|
||||
|
||||
//
|
||||
// Next, breed until we've reached our new size
|
||||
thread_count = this->GetThreadCountSuggestion();
|
||||
for ( i=0; i<thread_count; i++) {
|
||||
thread = std::shared_ptr<std::thread>(
|
||||
new std::thread(&Population::BreedNewPopulation_Thread, this, population_new, size)
|
||||
);
|
||||
threads.push_back(thread);
|
||||
}
|
||||
|
||||
//
|
||||
for ( i=0; i<(int)threads.size(); i++) {
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
// Finally, reset the fitness of the new population
|
||||
for ( i=0; i<(int)population_new->size(); i++ ) {
|
||||
population_new->at(i)->ResetFitness();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -452,6 +501,63 @@ namespace BitEvolver
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
int Population::DetermineEliteCount()
|
||||
{
|
||||
//
|
||||
int count;
|
||||
|
||||
//
|
||||
switch( this->elitism_type )
|
||||
{
|
||||
//
|
||||
default:
|
||||
case Enums::ElitismType::None:
|
||||
count = 0;
|
||||
break;
|
||||
|
||||
//
|
||||
case Enums::ElitismType::Absolute:
|
||||
count = this->elitism_count;
|
||||
break;
|
||||
|
||||
//
|
||||
case Enums::ElitismType::Rate:
|
||||
count = floor( this->chromosomes.size() * this->elitism_rate );
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//
|
||||
void Population::SeedPopulationWithElites(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new)
|
||||
{
|
||||
//
|
||||
std::unique_lock<std::recursive_mutex> lock(this->population_modification_mutex);
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> elites;
|
||||
std::vector<std::shared_ptr<std::thread>> threads;
|
||||
std::shared_ptr<std::thread> thread;
|
||||
int
|
||||
elites_count,
|
||||
i
|
||||
;
|
||||
|
||||
// Determine how many elites to copy
|
||||
elites_count = this->DetermineEliteCount();
|
||||
elites = std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>>(
|
||||
new std::vector<std::shared_ptr<Chromosome>>()
|
||||
);
|
||||
|
||||
// First, copy over just the pointers
|
||||
for ( i=0; i<elites_count && i<(int)this->chromosomes.size(); i++) {
|
||||
elites->push_back( this->chromosomes[i] );
|
||||
}
|
||||
|
||||
// Then, make them full copies (uses threads)
|
||||
this->CopyChromosomes(elites, population_new);
|
||||
}
|
||||
|
||||
//
|
||||
void Population::EvaluateFitness_Thread(
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes,
|
||||
@@ -522,6 +628,75 @@ namespace BitEvolver
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void Population::CopyChromosomes(
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_source,
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_destination
|
||||
)
|
||||
{
|
||||
//
|
||||
std::vector<std::shared_ptr<std::thread>> threads;
|
||||
std::shared_ptr<std::thread> thread;
|
||||
int
|
||||
threads_count,
|
||||
i
|
||||
;
|
||||
|
||||
// Spawn threads
|
||||
threads_count = this->GetThreadCountSuggestion();
|
||||
for ( i=0; i<threads_count; i++) {
|
||||
|
||||
//
|
||||
thread = std::shared_ptr<std::thread>(
|
||||
new std::thread(&Population::CopyChromosomes_Thread, this, _chromosomes_source, _chromosomes_destination)
|
||||
);
|
||||
threads.push_back(thread);
|
||||
}
|
||||
|
||||
// Wait for threads to finish
|
||||
for ( i=0; i<threads_count; i++ ) {
|
||||
threads[i]->join();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void Population::CopyChromosomes_Thread(
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_source,
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_destination
|
||||
)
|
||||
{
|
||||
//
|
||||
std::shared_ptr<Chromosome>
|
||||
chromosome_original,
|
||||
chromosome_copied
|
||||
;
|
||||
stringstream ss;
|
||||
|
||||
//
|
||||
while ( _chromosomes_destination->size() < _chromosomes_source->size() )
|
||||
{
|
||||
// Grab the next slot
|
||||
this->copy_chromosomes_mutex.lock();
|
||||
chromosome_original = nullptr;
|
||||
chromosome_copied = nullptr;
|
||||
if ( _chromosomes_destination->size() < _chromosomes_source->size() ) {
|
||||
|
||||
//
|
||||
chromosome_copied = std::shared_ptr<Chromosome>(
|
||||
new Chromosome(this->random, 0)
|
||||
);
|
||||
_chromosomes_destination->push_back(chromosome_copied);
|
||||
chromosome_original = _chromosomes_source->at(_chromosomes_destination->size()-1);
|
||||
}
|
||||
this->copy_chromosomes_mutex.unlock();
|
||||
|
||||
// Make a full copy of the original, outside the lock
|
||||
if ( chromosome_copied && chromosome_original ) {
|
||||
*chromosome_copied = *chromosome_original;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
std::shared_ptr<Chromosome> Population::BreedChild()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user