Convenience: Can now evaluate a lambda for fitness on every chromosome, using threads

This commit is contained in:
Mike 2018-04-14 04:10:31 -07:00
parent 4f1522ff43
commit b256a47cde
2 changed files with 90 additions and 1 deletions

View File

@ -16,6 +16,7 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <thread> #include <thread>
#include <functional>
// //
@ -197,6 +198,45 @@ namespace BitEvolver
return this->mutation_rate; return this->mutation_rate;
} }
//
void Population::EvaluateFitness(std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback)
{
//
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes_copy;
std::vector<std::shared_ptr<std::thread>> threads;
std::shared_ptr<std::thread> thread;
int
threads_count,
i
;
// Make a new vector containing all current chromosomes
this->population_modification_mutex.lock();
_chromosomes_copy = std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>>(
new std::vector<std::shared_ptr<Chromosome>>()
);
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<threads_count; i++) {
//
thread = std::shared_ptr<std::thread>(
new std::thread(&Population::EvaluateFitness_Thread, this, _chromosomes_copy, evaluation_callback)
);
threads.push_back(thread);
}
// Wait for threads to finish
for ( i=0; i<threads_count; i++ ) {
threads[i]->join();
}
}
// //
void Population::Evolve() void Population::Evolve()
{ {
@ -373,6 +413,41 @@ namespace BitEvolver
} }
} }
//
void Population::EvaluateFitness_Thread(
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes,
std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback
)
{
//
std::shared_ptr<Chromosome> 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<Chromosome> Population::BreedChild() std::shared_ptr<Chromosome> Population::BreedChild()
{ {

View File

@ -12,6 +12,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <mutex> #include <mutex>
#include <functional>
// //
@ -55,6 +56,9 @@ namespace BitEvolver
void SetMutationRate(double r); void SetMutationRate(double r);
double GetMutationRate(); double GetMutationRate();
//
void EvaluateFitness(std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback);
// //
void Evolve(); void Evolve();
int GetEvolutionNumber(); int GetEvolutionNumber();
@ -90,7 +94,11 @@ namespace BitEvolver
std::shared_ptr<class RouletteWheel> roulette_wheel; std::shared_ptr<class RouletteWheel> roulette_wheel;
// //
std::mutex breed_mutex; std::recursive_mutex
population_modification_mutex,
breed_mutex,
evaluate_fitness_mutex
;
// //
void InitRandomGenerator(); void InitRandomGenerator();
@ -104,6 +112,12 @@ namespace BitEvolver
void BreedNewPopulation(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new, int size); 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); void BreedNewPopulation_Thread(std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> population_new, int size);
//
void EvaluateFitness_Thread(
std::shared_ptr<std::vector<std::shared_ptr<Chromosome>>> _chromosomes,
std::function<double(std::shared_ptr<Chromosome>)> evaluation_callback
);
// //
std::shared_ptr<Chromosome> BreedChild(); std::shared_ptr<Chromosome> BreedChild();