mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] Population: Add mutate() and crossover() methods
This commit is contained in:
parent
92b54d83a3
commit
7e80ac861f
@ -158,6 +158,7 @@ set(yul_phaser_sources
|
||||
../tools/yulPhaser/Chromosome.cpp
|
||||
../tools/yulPhaser/FitnessMetrics.cpp
|
||||
../tools/yulPhaser/GeneticAlgorithms.cpp
|
||||
../tools/yulPhaser/Mutations.cpp
|
||||
../tools/yulPhaser/PairSelections.cpp
|
||||
../tools/yulPhaser/Population.cpp
|
||||
../tools/yulPhaser/Program.cpp
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <test/yulPhaser/Common.h>
|
||||
|
||||
#include <tools/yulPhaser/Chromosome.h>
|
||||
#include <tools/yulPhaser/PairSelections.h>
|
||||
#include <tools/yulPhaser/Population.h>
|
||||
#include <tools/yulPhaser/Program.h>
|
||||
#include <tools/yulPhaser/Selections.h>
|
||||
@ -31,6 +32,7 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@ -226,6 +228,70 @@ BOOST_FIXTURE_TEST_CASE(select_should_return_empty_population_if_selection_is_em
|
||||
BOOST_TEST(population.select(selection).individuals().empty());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(mutate_should_return_population_containing_individuals_indicated_by_selection_with_mutation_applied, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")});
|
||||
RangeSelection selection(0.25, 0.75);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<size_t>{1, 2}));
|
||||
|
||||
Population expectedPopulation(m_fitnessMetric, {Chromosome("fc"), Chromosome("fg")});
|
||||
|
||||
BOOST_TEST(population.mutate(selection, geneSubstitution(0, BlockFlattener::name)) == expectedPopulation);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(mutate_should_include_duplicates_if_selection_contains_duplicates, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("aa")});
|
||||
RangeSelection selection(0.0, 1.0);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<size_t>{0, 1}));
|
||||
|
||||
BOOST_TEST(
|
||||
population.mutate(selection, geneSubstitution(0, BlockFlattener::name)) ==
|
||||
Population(m_fitnessMetric, {Chromosome("fa"), Chromosome("fa")})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(mutate_should_return_empty_population_if_selection_is_empty, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc")});
|
||||
RangeSelection selection(0.0, 0.0);
|
||||
assert(selection.materialise(population.individuals().size()).empty());
|
||||
|
||||
BOOST_TEST(population.mutate(selection, geneSubstitution(0, BlockFlattener::name)).individuals().empty());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(crossover_should_return_population_containing_individuals_indicated_by_selection_with_crossover_applied, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")});
|
||||
PairMosaicSelection selection({{0, 1}, {2, 1}}, 0.5);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<tuple<size_t, size_t>>{{0, 1}, {2, 1}}));
|
||||
|
||||
Population expectedPopulation(m_fitnessMetric, {Chromosome("ac"), Chromosome("ca"), Chromosome("cg"), Chromosome("gc")});
|
||||
|
||||
BOOST_TEST(population.crossover(selection, fixedPointCrossover(0.5)) == expectedPopulation);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(crossover_should_include_duplicates_if_selection_contains_duplicates, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("aa")});
|
||||
PairMosaicSelection selection({{0, 0}, {1, 1}}, 1.0);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<tuple<size_t, size_t>>{{0, 0}, {1, 1}}));
|
||||
|
||||
BOOST_TEST(
|
||||
population.crossover(selection, fixedPointCrossover(0.5)) ==
|
||||
Population(m_fitnessMetric, {Chromosome("aa"), Chromosome("aa"), Chromosome("aa"), Chromosome("aa")})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(crossover_should_return_empty_population_if_selection_is_empty, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc")});
|
||||
PairMosaicSelection selection({}, 0.0);
|
||||
assert(selection.materialise(population.individuals().size()).empty());
|
||||
|
||||
BOOST_TEST(population.crossover(selection, fixedPointCrossover(0.5)).individuals().empty());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <tools/yulPhaser/Population.h>
|
||||
|
||||
#include <tools/yulPhaser/PairSelections.h>
|
||||
#include <tools/yulPhaser/Selections.h>
|
||||
|
||||
#include <libsolutil/CommonData.h>
|
||||
@ -93,6 +94,31 @@ Population Population::select(Selection const& _selection) const
|
||||
return Population(m_fitnessMetric, selectedIndividuals);
|
||||
}
|
||||
|
||||
Population Population::mutate(Selection const& _selection, function<Mutation> _mutation) const
|
||||
{
|
||||
vector<Individual> mutatedIndividuals;
|
||||
for (size_t i: _selection.materialise(m_individuals.size()))
|
||||
mutatedIndividuals.emplace_back(_mutation(m_individuals[i].chromosome), *m_fitnessMetric);
|
||||
|
||||
return Population(m_fitnessMetric, mutatedIndividuals);
|
||||
}
|
||||
|
||||
Population Population::crossover(PairSelection const& _selection, function<Crossover> _crossover) const
|
||||
{
|
||||
vector<Individual> crossedIndividuals;
|
||||
for (auto const& [i, j]: _selection.materialise(m_individuals.size()))
|
||||
{
|
||||
auto [childChromosome1, childChromosome2] = _crossover(
|
||||
m_individuals[i].chromosome,
|
||||
m_individuals[j].chromosome
|
||||
);
|
||||
crossedIndividuals.emplace_back(move(childChromosome1), *m_fitnessMetric);
|
||||
crossedIndividuals.emplace_back(move(childChromosome2), *m_fitnessMetric);
|
||||
}
|
||||
|
||||
return Population(m_fitnessMetric, crossedIndividuals);
|
||||
}
|
||||
|
||||
Population operator+(Population _a, Population _b)
|
||||
{
|
||||
// This operator is meant to be used only with populations sharing the same metric (and, to make
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <tools/yulPhaser/Chromosome.h>
|
||||
#include <tools/yulPhaser/FitnessMetrics.h>
|
||||
#include <tools/yulPhaser/Mutations.h>
|
||||
#include <tools/yulPhaser/SimulationRNG.h>
|
||||
|
||||
#include <optional>
|
||||
@ -39,6 +40,7 @@ solidity::phaser::Population operator+(solidity::phaser::Population _a, solidity
|
||||
namespace solidity::phaser
|
||||
{
|
||||
|
||||
class PairSelection;
|
||||
class Selection;
|
||||
|
||||
/**
|
||||
@ -104,6 +106,8 @@ public:
|
||||
);
|
||||
|
||||
Population select(Selection const& _selection) const;
|
||||
Population mutate(Selection const& _selection, std::function<Mutation> _mutation) const;
|
||||
Population crossover(PairSelection const& _selection, std::function<Crossover> _crossover) const;
|
||||
friend Population (::operator+)(Population _a, Population _b);
|
||||
|
||||
std::shared_ptr<FitnessMetric const> fitnessMetric() const { return m_fitnessMetric; }
|
||||
|
Loading…
Reference in New Issue
Block a user