Elitism and CopyChromosomes()
This commit is contained in:
parent
7db4140bdd
commit
b2f164f464
9
Enums.h
9
Enums.h
@ -15,6 +15,15 @@ namespace BitEvolver
|
||||
None,
|
||||
Sexual
|
||||
};
|
||||
|
||||
//
|
||||
enum class ElitismType
|
||||
{
|
||||
//
|
||||
None,
|
||||
Rate,
|
||||
Absolute
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
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()
|
||||
{
|
||||
|
38
Population.h
38
Population.h
@ -55,6 +55,13 @@ namespace BitEvolver
|
||||
//
|
||||
void SetMutationRate(double r);
|
||||
double GetMutationRate();
|
||||
//
|
||||
void SetElitismType(Enums::ElitismType t);
|
||||
Enums::ElitismType GetElitismType();
|
||||
void SetElitismRate(double r);
|
||||
double GetElitismRate();
|
||||
void SetElitismCount(int c);
|
||||
int GetElitismCount();
|
||||
|
||||
//
|
||||
void EvaluateFitness(std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback);
|
||||
@ -69,8 +76,11 @@ namespace BitEvolver
|
||||
void PrintPopulation(std::vector<std::shared_ptr<class Chromosome>> _chromosomes);
|
||||
|
||||
// Constants
|
||||
const static int DEFAULT_POPULATION_SIZE = 100;
|
||||
const static int DEFAULT_MUTATION_RATE = 0.01;
|
||||
const static int DEFAULT_POPULATION_SIZE = 100;
|
||||
const static Enums::ElitismType DEFAULT_ELITISM_TYPE = Enums::ElitismType::Rate;
|
||||
constexpr static double DEFAULT_ELITISM_RATE = 0.01;
|
||||
const static int DEFAULT_ELITISM_COUNT = 1;
|
||||
constexpr static double DEFAULT_MUTATION_RATE = 0.01;
|
||||
//
|
||||
const static Enums::CrossoverType DEFAULT_CROSSOVER_TYPE = Enums::CrossoverType::Sexual;
|
||||
const static int DEFAULT_CROSSOVER_POINT = 0.7;
|
||||
@ -86,10 +96,15 @@ namespace BitEvolver
|
||||
std::vector<std::shared_ptr<class Chromosome>> chromosomes;
|
||||
int population_size;
|
||||
bool population_needs_sorting;
|
||||
int evolution_number;
|
||||
|
||||
//
|
||||
Enums::CrossoverType crossover_type;
|
||||
double crossover_point;
|
||||
double mutation_rate;
|
||||
int evolution_number;
|
||||
Enums::ElitismType elitism_type;
|
||||
double elitism_rate;
|
||||
int elitism_count;
|
||||
|
||||
//
|
||||
std::shared_ptr<class RouletteWheel> roulette_wheel;
|
||||
@ -98,7 +113,8 @@ namespace BitEvolver
|
||||
std::recursive_mutex
|
||||
population_modification_mutex,
|
||||
breed_mutex,
|
||||
evaluate_fitness_mutex
|
||||
evaluate_fitness_mutex,
|
||||
copy_chromosomes_mutex
|
||||
;
|
||||
|
||||
//
|
||||
@ -113,6 +129,10 @@ namespace BitEvolver
|
||||
void BreedNewPopulation(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new, int size);
|
||||
void BreedNewPopulation_Thread(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new, int size);
|
||||
|
||||
//
|
||||
int DetermineEliteCount();
|
||||
void SeedPopulationWithElites(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new);
|
||||
|
||||
//
|
||||
void EvaluateFitness_Thread(
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes,
|
||||
@ -123,6 +143,16 @@ namespace BitEvolver
|
||||
std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback
|
||||
);
|
||||
|
||||
//
|
||||
void CopyChromosomes(
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_source,
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_destination
|
||||
);
|
||||
void 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> BreedChild();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user