From df033a74e9dae48ba6a9efe3b0a5ad03c5caa324 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20D=C5=82ugo=C5=82=C4=99cki?= Date: Sun, 5 Apr 2015 17:41:21 +0200 Subject: [PATCH] Add usage of operators in Generation and Chromosome. Optimize code. (from 10s to 6s for 1000 of generations with 200 chromosomes with 10 genes each). --- src/algorithm.h | 16 ++++++++-------- src/chromosome.h | 22 +++++++++++++++++----- src/crossover/crossover.h | 20 ++++++++++---------- src/fitness/fitness.h | 2 +- src/fitness/wsti.h | 17 +++++++++-------- src/generation.h | 18 ++++++++++++++++++ src/main.cpp | 2 +- src/mutation/mutation.h | 11 ++++------- src/selection/roulette.h | 6 +++--- 9 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/algorithm.h b/src/algorithm.h index 9b2e3be..67b7160 100644 --- a/src/algorithm.h +++ b/src/algorithm.h @@ -119,10 +119,10 @@ namespace genetic { * \attention Method is currently not in use. */ void showGeneration() { - for (unsigned int i = 0; i < this->generation.get().size(); i++) { + for (unsigned int i = 0; i < this->generation.size(); i++) { cout << "# " << i << ") "; - for (unsigned int j = 0; j < this->generation.get()[i].get().size(); j++) { - cout << this->generation.get()[i].get()[j].get(); + for (unsigned int j = 0; j < this->generation[i].size(); j++) { + cout << this->generation[i][j].get(); } cout << "\n"; } @@ -133,12 +133,12 @@ namespace genetic { */ void showAvgFitness() { double avg = 0; - for (unsigned int i = 0; i < this->generation.get().size(); i++) { - _Fitness fit(this->generation.get()[i]); + for (unsigned int i = 0; i < this->generation.size(); i++) { + _Fitness fit(this->generation[i]); fit.parseArguments(fitness.getArguments()); avg += fit.calculate(); } - cout << " " << avg / this->generation.get().size(); + cout << " " << avg / this->generation.size(); } /** @@ -146,8 +146,8 @@ namespace genetic { */ void showBestFitness() { double best = -100000; - for (unsigned int i = 0; i < this->generation.get().size(); i++) { - _Fitness fit(this->generation.get()[i]); + for (unsigned int i = 0; i < this->generation.size(); i++) { + _Fitness fit(this->generation[i]); fit.parseArguments(fitness.getArguments()); double tmp = fit.calculate(); diff --git a/src/chromosome.h b/src/chromosome.h index 7399ea4..08d24c9 100644 --- a/src/chromosome.h +++ b/src/chromosome.h @@ -24,6 +24,7 @@ namespace genetic { */ vector<_Gene> genes; + template friend class Chromosome; public: /** * Default constructor @@ -41,7 +42,7 @@ namespace genetic { /** Copy constructor */ Chromosome(const Chromosome& chromosome) - : genes(chromosome.get()) { + : genes(chromosome.genes) { } /** @@ -51,15 +52,26 @@ namespace genetic { * @return Chromosome instance containing copied Genes */ Chromosome& operator=(const Chromosome& chromosome) { - this->genes = chromosome.get(); + this->genes = chromosome.genes; return *this; } /** - * Allows read-only access to Chromosome Genes + * Returns number of Genes in current Chromosome + * + * @return number of Genes in current Chromosome + */ + unsigned int size() const { + return this->genes.size(); + } + + /** + * Returns i-th Gene in the current Chromosome + * + * @return i-th Gene in the current Chromosome */ - vector<_Gene> get() const { - return this->genes; + _Gene& operator[](unsigned int i) { + return this->genes[i]; } }; } diff --git a/src/crossover/crossover.h b/src/crossover/crossover.h index 0d9b309..d2eada8 100644 --- a/src/crossover/crossover.h +++ b/src/crossover/crossover.h @@ -35,15 +35,15 @@ namespace genetic { * @return new Chromosome crossed between given two */ _Chromosome do_cross(_Chromosome first, _Chromosome second, unsigned int splitPlace) { - const unsigned int chromosomeSize = first.get().size(); + const unsigned int chromosomeSize = first.size(); // cout << " "; // for (unsigned int i = 0; i < chromosomeSize; i++) { -// cout << first.get()[i].get(); +// cout << first[i].get(); // } // cout << "\n x "; // for (unsigned int i = 0; i < chromosomeSize; i++) { -// cout << second.get()[i].get(); +// cout << second[i].get(); // } // cout << "\n--------"; // for (unsigned int i = 0; i < chromosomeSize; i++) { @@ -58,16 +58,16 @@ namespace genetic { vector crossedChromosome; for (unsigned int i = 0; i < chromosomeSize; i++) { if (i < splitPlace) { - crossedChromosome.push_back(first.get()[i].get()); + crossedChromosome.push_back(first[i].get()); } else { - crossedChromosome.push_back(second.get()[i].get()); + crossedChromosome.push_back(second[i].get()); } } // cout << "\n "; // for (unsigned int i = 0; i < chromosomeSize; i++) { -// cout << crossedChromosome[i].get(); +// cout << crossedChromosome[i]; // } // cout << "\n"; @@ -91,14 +91,14 @@ namespace genetic { * @return new Generation of Chromosome's after the Crossover */ Generation<_Chromosome> cross(Generation<_Chromosome> _generation) { - const unsigned int generationSize = _generation.get().size(); + const unsigned int generationSize = _generation.size(); vector<_Chromosome> newGeneration; for (unsigned int i = 0; i < generationSize; i++) { CrossoverChanceType random = (rand() + 1 % 10000) / 10000.0; - _Chromosome chromosome = _generation.get()[i]; + _Chromosome chromosome = _generation[i]; if (random < this->chance) { - const unsigned int chromosomeSize = chromosome.get().size(); + const unsigned int chromosomeSize = chromosome.size(); const unsigned int splitPlace = rand() % chromosomeSize; unsigned int pairedChromosome = 0; @@ -109,7 +109,7 @@ namespace genetic { pairedChromosome = rand() % generationSize; } while(pairedChromosome == i); - chromosome = do_cross(chromosome, _generation.get()[pairedChromosome], splitPlace); + chromosome = do_cross(chromosome, _generation[pairedChromosome], splitPlace); } newGeneration.push_back(chromosome); } diff --git a/src/fitness/fitness.h b/src/fitness/fitness.h index 093490d..a975034 100644 --- a/src/fitness/fitness.h +++ b/src/fitness/fitness.h @@ -47,7 +47,7 @@ namespace genetic { * Copy constructor */ Fitness(_Chromosome& _chromosome) - : chromosome(_chromosome.get()) { + : chromosome(_chromosome) { } /** diff --git a/src/fitness/wsti.h b/src/fitness/wsti.h index 3743a9c..1724936 100644 --- a/src/fitness/wsti.h +++ b/src/fitness/wsti.h @@ -17,14 +17,16 @@ namespace genetic { class WSTI : public Fitness<_Chromosome, _Value> { protected: /** - * Value of the begining of the Fitness function domain + * Value of the begining of the Fitness function domain. + * By default it is equal to 0. */ - float span_start; + float span_start = 0; /** - * Value of the end of the Fitness function domain + * Value of the end of the Fitness function domain. + * By default it is equal to 0. */ - float span_end; + float span_end = 0; /** * Calculates fenotype of the current Chromosome @@ -32,11 +34,10 @@ namespace genetic { _Value fenotype() { int _fenotype = 0; int ratio = 1; - for (unsigned int i = 0; i < this->chromosome.get().size(); i++) { - _fenotype = _fenotype + this->chromosome.get()[i].get() * ratio; + for (unsigned int i = 0; i < this->chromosome.size(); i++) { + _fenotype = _fenotype + this->chromosome[i].get() * ratio; ratio = ratio * 2; } -// cout << "Fenotyp: " << _fenotype << "\n"; return _fenotype; } @@ -44,7 +45,7 @@ namespace genetic { * Calculates fenotype of the current Chromosome */ _Value calculateFenotype() { - const unsigned int power2N = 1 << this->chromosome.get().size(); + const unsigned int power2N = 1 << this->chromosome.size(); return span_start + (span_end - span_start) * this->fenotype() / power2N; } diff --git a/src/generation.h b/src/generation.h index a376028..f195d7e 100644 --- a/src/generation.h +++ b/src/generation.h @@ -57,6 +57,24 @@ namespace genetic { this->chromosomes = generation.get(); return *this; } + + /** + * Returns number of Chromosomes in current Generation + * + * @return number of Chromosomes in current Generation + */ + unsigned int size() const { + return this->chromosomes.size(); + } + + /** + * Returns i-th Chromosome in the current Generation + * + * @return i-th Chromosome in the current Generation + */ + _Chromosome& operator[](unsigned int i) { + return this->chromosomes[i]; + } }; } diff --git a/src/main.cpp b/src/main.cpp index f2aec13..8002052 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,7 @@ int main() { const int chromosomeSize = 10; const int generationSize = 200; const double crossoverChance = 0.75; - const double mutationChance = 0.01; + const double mutationChance = 0.1; _Fitness fitness(0.5, 2.5); _Generator generationGenerator(generationSize, chromosomeSize); diff --git a/src/mutation/mutation.h b/src/mutation/mutation.h index 7b626ba..69c2326 100644 --- a/src/mutation/mutation.h +++ b/src/mutation/mutation.h @@ -49,21 +49,18 @@ namespace genetic { * @return new Generation of Chromosome's that passed the mutation */ Generation<_Chromosome> mutate(Generation<_Chromosome> _generation) { - const unsigned int generationSize = _generation.get().size(); - const unsigned int chromosomeSize = _generation.get()[0].get().size(); + const unsigned int generationSize = _generation.size(); + const unsigned int chromosomeSize = _generation[0].size(); vector<_Chromosome> newGeneration; for (unsigned int i = 0; i < generationSize; i++) { MutationChanceType random = (rand() % 10000) / 10000.0; - _Chromosome chromosome = _generation.get()[i]; + _Chromosome chromosome = _generation[i]; if (random < this->chance) { unsigned int mutatedGene = (rand() % chromosomeSize); - vector newChromosome = chromosome.get(); - newChromosome[mutatedGene] = GeneType(!newChromosome[mutatedGene].get()); - - chromosome = _Chromosome(newChromosome); + chromosome[mutatedGene] = GeneType(!chromosome[mutatedGene].get()); } newGeneration.push_back(chromosome); } diff --git a/src/selection/roulette.h b/src/selection/roulette.h index 6db71ef..b5c1f33 100644 --- a/src/selection/roulette.h +++ b/src/selection/roulette.h @@ -109,8 +109,8 @@ namespace genetic { vector<_Chromosome> selected; multimap probabilities; - unsigned int size = this->generation.get().size(); - const unsigned int power2N = 1 << this->generation.get()[0].get().size(); + unsigned int size = this->generation.size(); + const unsigned int power2N = 1 << this->generation[0].size(); /** Random value used to draw chromosome */ FitnessValueType random = 0; @@ -170,7 +170,7 @@ namespace genetic { normalizedFitness = this->normalizeFitness( this->calculateGenerationFitness(this->generation), - this->generation.get()[0].get().size() + this->generation[0].size() ); return spinRoulette(normalizedFitness); -- 2.30.2