diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index dfee5f74a..98532c9dc 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -182,38 +182,6 @@ BOOST_FIXTURE_TEST_CASE(makeRandom_should_compute_fitness, PopulationFixture) BOOST_TEST(population.individuals()[2].fitness == m_fitnessMetric->evaluate(population.individuals()[2].chromosome)); } -BOOST_FIXTURE_TEST_CASE(run_should_not_make_fitness_of_top_chromosomes_worse, PopulationFixture) -{ - stringstream output; - vector chromosomes = { - Chromosome(vector{StructuralSimplifier::name}), - Chromosome(vector{BlockFlattener::name}), - Chromosome(vector{SSAReverser::name}), - Chromosome(vector{UnusedPruner::name}), - Chromosome(vector{StructuralSimplifier::name, BlockFlattener::name}), - }; - Population population(m_fitnessMetric, chromosomes); - - size_t initialTopFitness[2] = { - m_fitnessMetric->evaluate(chromosomes[0]), - m_fitnessMetric->evaluate(chromosomes[1]), - }; - - for (int i = 0; i < 6; ++i) - { - population.run(1, output); - BOOST_TEST(population.individuals().size() == 5); - - size_t currentTopFitness[2] = { - population.individuals()[0].fitness, - population.individuals()[1].fitness, - }; - BOOST_TEST(currentTopFitness[0] <= initialTopFitness[0]); - BOOST_TEST(currentTopFitness[1] <= initialTopFitness[1]); - BOOST_TEST(currentTopFitness[0] <= currentTopFitness[1]); - } -} - BOOST_FIXTURE_TEST_CASE(plus_operator_should_add_two_populations, PopulationFixture) { BOOST_CHECK_EQUAL( diff --git a/tools/yulPhaser/Population.cpp b/tools/yulPhaser/Population.cpp index 12acbe417..b39f5dad5 100644 --- a/tools/yulPhaser/Population.cpp +++ b/tools/yulPhaser/Population.cpp @@ -84,18 +84,6 @@ Population Population::makeRandom( ); } -void Population::run(optional _numRounds, ostream& _outputStream) -{ - for (size_t round = 0; !_numRounds.has_value() || round < _numRounds.value(); ++round) - { - doMutation(); - doSelection(); - - _outputStream << "---------- ROUND " << round << " ----------" << endl; - _outputStream << *this; - } -} - Population Population::select(Selection const& _selection) const { vector selectedIndividuals; @@ -131,35 +119,6 @@ ostream& phaser::operator<<(ostream& _stream, Population const& _population) return _stream; } -void Population::doMutation() -{ - // TODO: Implement mutation and crossover -} - -void Population::doSelection() -{ - randomizeWorstChromosomes(*m_fitnessMetric, m_individuals, m_individuals.size() / 2); - m_individuals = sortedIndividuals(move(m_individuals)); -} - -void Population::randomizeWorstChromosomes( - FitnessMetric const& _fitnessMetric, - vector& _individuals, - size_t _count -) -{ - assert(_individuals.size() >= _count); - // ASSUMPTION: _individuals is sorted in ascending order - - auto individual = _individuals.begin() + (_individuals.size() - _count); - for (; individual != _individuals.end(); ++individual) - { - auto chromosome = Chromosome::makeRandom(binomialChromosomeLength(MaxChromosomeLength)); - size_t fitness = _fitnessMetric.evaluate(chromosome); - *individual = {move(chromosome), fitness}; - } -} - vector Population::chromosomesToIndividuals( FitnessMetric const& _fitnessMetric, vector _chromosomes diff --git a/tools/yulPhaser/Population.h b/tools/yulPhaser/Population.h index f66efc9a0..f4f42346d 100644 --- a/tools/yulPhaser/Population.h +++ b/tools/yulPhaser/Population.h @@ -69,19 +69,19 @@ struct Individual bool isFitter(Individual const& a, Individual const& b); /** - * Represents a changing set of individuals undergoing a genetic algorithm. - * Each round of the algorithm involves mutating existing individuals, evaluating their fitness - * and selecting the best ones for the next round. + * Represents a snapshot of a population undergoing a genetic algorithm. Consists of a set of + * chromosomes with associated fitness values. * * An individual is a sequence of optimiser steps represented by a @a Chromosome instance. * Individuals are always ordered by their fitness (based on @_fitnessMetric and @a isFitter()). * The fitness is computed using the metric as soon as an individual is inserted into the population. + * + * The population is immutable. Selections, mutations and crossover work by producing a new + * instance and copying the individuals. */ class Population { public: - static constexpr size_t MaxChromosomeLength = 30; - explicit Population( std::shared_ptr _fitnessMetric, std::vector _chromosomes = {} @@ -103,7 +103,6 @@ public: size_t _maxChromosomeLength ); - void run(std::optional _numRounds, std::ostream& _outputStream); Population select(Selection const& _selection) const; friend Population (::operator+)(Population _a, Population _b); @@ -123,14 +122,6 @@ private: m_fitnessMetric(std::move(_fitnessMetric)), m_individuals{sortedIndividuals(std::move(_individuals))} {} - void doMutation(); - void doSelection(); - - static void randomizeWorstChromosomes( - FitnessMetric const& _fitnessMetric, - std::vector& _individuals, - size_t _count - ); static std::vector chromosomesToIndividuals( FitnessMetric const& _fitnessMetric, std::vector _chromosomes