From 4b38d1c4941b700ef726e3ec72e9f2ca35918e53 Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 14 Apr 2018 02:23:43 -0700 Subject: [PATCH] New class RouletteWheel ! --- RouletteWheel.cpp | 260 ++++++++++++++++++++++++++++++++++++++++++++++ RouletteWheel.h | 68 ++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 RouletteWheel.cpp create mode 100644 RouletteWheel.h diff --git a/RouletteWheel.cpp b/RouletteWheel.cpp new file mode 100644 index 0000000..6ba182d --- /dev/null +++ b/RouletteWheel.cpp @@ -0,0 +1,260 @@ + + + +// +#include "BitEvolver/Random.h" +#include "BitEvolver/RouletteWheel.h" +#include "BitEvolver/Chromosome.h" + + +// +#include +#include +#include +#include + + +// +namespace BitEvolver +{ + // + RouletteWheel::RouletteWheel() + { + // + this->Instantiate(); + + // + this->Reset(); + } + + // + void RouletteWheel::Reset() + { + // + this->ClearChromosomes(); + } + + // + void RouletteWheel::ClearChromosomes() + { + // + std::unique_lock lock(this->chromosomes_mutex); + + // + this->chromosomes.clear(); + this->ChromosomesChanged(); + } + + // + void RouletteWheel::SetChromosomes(std::vector> _chromosomes) + { + // + std::unique_lock lock(this->chromosomes_mutex); + + // + this->ClearChromosomes(); + + // + this->chromosomes = _chromosomes; + + // + this->ChromosomesChanged(); + } + + // + void RouletteWheel::AddChromosome(std::shared_ptr _chromosome) + { + // + std::unique_lock lock(this->chromosomes_mutex); + + // + this->chromosomes.push_back(_chromosome); + this->ChromosomesChanged(); + } + + // + void RouletteWheel::AddChromosomes(std::vector> _chromosomes) + { + // + std::unique_lock lock(this->chromosomes_mutex); + + // + for ( std::shared_ptr _chromosome : _chromosomes ) { + + // + this->chromosomes.push_back(_chromosome); + } + + // + this->ChromosomesChanged(); + } + + // + std::shared_ptr RouletteWheel::Spin() + { + // + std::unique_lock lock(this->chromosomes_mutex); + double + range_min, range_max, + spin + ; + size_t i; + + // + this->PopulateSlots(); + + // + if ( !this->wheel_slots.size() ) { + return nullptr; + } + + // Spin a random number in our range + range_min = this->wheel_slots[0].first; + range_max = this->wheel_slots[this->wheel_slots.size()-1].first; + spin = this->random->GetDouble(range_min, range_max); + + // Find the corresponding chromosome + for ( i=0; iwheel_slots.size(); i++ ) { + if ( this->wheel_slots[i].first <= spin ) { + return this->wheel_slots[i].second; + } + } + + // By default, return the first one I guess + return this->wheel_slots[0].second; + } + + // + void RouletteWheel::Instantiate() + { + // + this->random = std::shared_ptr( + new Random() + ); + } + + // + std::vector>> RouletteWheel::GetNormalizedChromosomeFitness() + { + // + std::unique_lock lock(this->chromosomes_mutex); + std::vector< std::pair< double, std::shared_ptr > > pairs; + std::pair< double, std::shared_ptr > pair; + double + fitness, fitness_low, fitness_high + ; + + // + if ( !this->chromosomes.size() ) { + return pairs; + } + + // Locate lowest and highest fitness + fitness_low = fitness_high = this->chromosomes[0]->GetFitness(); + for ( std::shared_ptr chromosome : this->chromosomes ) { + + // + fitness = chromosome->GetFitness(); + if ( fitness > fitness_high ) { + fitness_high = fitness; + } + if ( fitness < fitness_low ) { + fitness_low = fitness; + } + } + + // Generate normalized pairs + for ( std::shared_ptr chromosome : this->chromosomes ) { + + // + pair.first = chromosome->GetFitness() - fitness_low; + pair.second = chromosome; + + // + pairs.push_back(pair); + } + + return pairs; + } + + // + void RouletteWheel::SortChromosomes() + { + // + std::unique_lock lock(this->chromosomes_mutex); + + // + if ( !this->chromosomes_need_sorting ) { + return; + } + + // + std::sort( + this->chromosomes.begin(), + this->chromosomes.end(), + []( const std::shared_ptr& left, const std::shared_ptr& right ) -> bool + { + // + if ( left->GetFitness() > right->GetFitness() ) { + return true; + } + + return false; + } + ); + + // + this->chromosomes_need_sorting = false; + } + + // + void RouletteWheel::PopulateSlots() + { + // + std::unique_lock lock(this->chromosomes_mutex); + std::vector>> chromosomes_normalized_fitness; + std::pair> wheel_slot; + double slot_begin_value; + + // + if ( !this->slots_need_population ) { + return; + } + + // + this->SortChromosomes(); + + // + this->wheel_slots.clear(); + + // + slot_begin_value = 0; + chromosomes_normalized_fitness = this->GetNormalizedChromosomeFitness(); + for ( std::pair> pair: chromosomes_normalized_fitness ) { + + // + wheel_slot.first = pair.first + slot_begin_value; + wheel_slot.second = pair.second; + + // + this->wheel_slots.push_back(wheel_slot); + + // + slot_begin_value += pair.first; + } + + // + this->slots_need_population = false; + } + + // + void RouletteWheel::ChromosomesChanged() + { + // + this->chromosomes_need_sorting = true; + this->slots_need_population = true; + } +}; + + + diff --git a/RouletteWheel.h b/RouletteWheel.h new file mode 100644 index 0000000..b31baaf --- /dev/null +++ b/RouletteWheel.h @@ -0,0 +1,68 @@ + + + +// +#pragma once + + +// +#include +#include +#include + + +// +namespace BitEvolver +{ + // + class RouletteWheel + { + // + public: + + // + RouletteWheel(); + + // + void Reset(); + + // + void ClearChromosomes(); + void SetChromosomes(std::vector> _chromosomes); + void AddChromosome(std::shared_ptr _chromosome); + void AddChromosomes(std::vector> _chromosomes); + + // + std::shared_ptr Spin(); + + // + private: + + // + std::shared_ptr random; + + // + std::vector> chromosomes; + std::recursive_mutex chromosomes_mutex; + bool chromosomes_need_sorting; + // + std::vector>> wheel_slots; + bool slots_need_population; + + + // + void Instantiate(); + + // + std::vector>> GetNormalizedChromosomeFitness(); + void SortChromosomes(); + void PopulateSlots(); + + // + void ChromosomesChanged(); + + }; +}; + + +