From b256a47cdecd4db80633d3187caecf46a49c126e Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 14 Apr 2018 04:10:31 -0700 Subject: [PATCH] Convenience: Can now evaluate a lambda for fitness on every chromosome, using threads --- Population.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ Population.h | 16 ++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Population.cpp b/Population.cpp index 27b1aa4..4519774 100644 --- a/Population.cpp +++ b/Population.cpp @@ -16,6 +16,7 @@ #include #include #include +#include // @@ -197,6 +198,45 @@ namespace BitEvolver return this->mutation_rate; } + // + void Population::EvaluateFitness(std::function)> evaluation_callback) + { + // + std::shared_ptr>> _chromosomes_copy; + std::vector> threads; + std::shared_ptr thread; + int + threads_count, + i + ; + + // Make a new vector containing all current chromosomes + this->population_modification_mutex.lock(); + _chromosomes_copy = std::shared_ptr>>( + new std::vector>() + ); + for ( i=0; i<(int)this->chromosomes.size(); i++ ) { + _chromosomes_copy->push_back( this->chromosomes[i] ); + } + this->population_modification_mutex.unlock(); + + // Spawn threads + threads_count = this->GetThreadCountSuggestion(); + for ( i=0; i( + new std::thread(&Population::EvaluateFitness_Thread, this, _chromosomes_copy, evaluation_callback) + ); + threads.push_back(thread); + } + + // Wait for threads to finish + for ( i=0; ijoin(); + } + } + // void Population::Evolve() { @@ -373,6 +413,41 @@ namespace BitEvolver } } + // + void Population::EvaluateFitness_Thread( + std::shared_ptr>> _chromosomes, + std::function)> evaluation_callback + ) + { + // + std::shared_ptr chromosome; + double fitness; + + // + while (true) + { + // Grab a free chromosome + this->evaluate_fitness_mutex.lock(); + chromosome = nullptr; + if ( _chromosomes->size() ) { + chromosome = _chromosomes->at(_chromosomes->size()-1); + _chromosomes->pop_back(); + } + this->evaluate_fitness_mutex.unlock(); + + // Call the evaluation callback + if ( chromosome != nullptr ) { + fitness = evaluation_callback(chromosome); + chromosome->SetFitness(fitness); + } + + // We're done if there was nothing to grab + else{ + break; + } + } + } + // std::shared_ptr Population::BreedChild() { diff --git a/Population.h b/Population.h index ad67dd3..24fc6fe 100644 --- a/Population.h +++ b/Population.h @@ -12,6 +12,7 @@ #include #include #include +#include // @@ -55,6 +56,9 @@ namespace BitEvolver void SetMutationRate(double r); double GetMutationRate(); + // + void EvaluateFitness(std::function)> evaluation_callback); + // void Evolve(); int GetEvolutionNumber(); @@ -90,7 +94,11 @@ namespace BitEvolver std::shared_ptr roulette_wheel; // - std::mutex breed_mutex; + std::recursive_mutex + population_modification_mutex, + breed_mutex, + evaluate_fitness_mutex + ; // void InitRandomGenerator(); @@ -104,6 +112,12 @@ namespace BitEvolver void BreedNewPopulation(std::shared_ptr>> population_new, int size); void BreedNewPopulation_Thread(std::shared_ptr>> population_new, int size); + // + void EvaluateFitness_Thread( + std::shared_ptr>> _chromosomes, + std::function)> evaluation_callback + ); + // std::shared_ptr BreedChild();