mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] Population: Add symmetricCrossoverWithRemainder()
This commit is contained in:
parent
59011fcde6
commit
ef8d0888af
@ -48,6 +48,14 @@ namespace solidity::phaser::test
|
||||
class PopulationFixture
|
||||
{
|
||||
protected:
|
||||
static ChromosomePair twoStepSwap(Chromosome const& _chromosome1, Chromosome const& _chromosome2)
|
||||
{
|
||||
return ChromosomePair{
|
||||
Chromosome(vector<string>{_chromosome1.optimisationSteps()[0], _chromosome2.optimisationSteps()[1]}),
|
||||
Chromosome(vector<string>{_chromosome2.optimisationSteps()[0], _chromosome1.optimisationSteps()[1]}),
|
||||
};
|
||||
}
|
||||
|
||||
shared_ptr<FitnessMetric> m_fitnessMetric = make_shared<ChromosomeLengthMetric>();
|
||||
};
|
||||
|
||||
@ -309,6 +317,53 @@ BOOST_FIXTURE_TEST_CASE(crossover_should_return_empty_population_if_selection_is
|
||||
BOOST_TEST(population.crossover(selection, fixedPointCrossover(0.5)).individuals().empty());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_return_crossed_population_and_remainder, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")});
|
||||
PairMosaicSelection selection({{2, 1}}, 0.25);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<tuple<size_t, size_t>>{{2, 1}}));
|
||||
|
||||
Population expectedCrossedPopulation(m_fitnessMetric, {Chromosome("gc"), Chromosome("cg")});
|
||||
Population expectedRemainder(m_fitnessMetric, {Chromosome("aa"), Chromosome("hh")});
|
||||
|
||||
BOOST_TEST(
|
||||
population.symmetricCrossoverWithRemainder(selection, twoStepSwap) ==
|
||||
(tuple<Population, Population>{expectedCrossedPopulation, expectedRemainder})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_should_allow_crossing_the_same_individual_multiple_times, PopulationFixture)
|
||||
{
|
||||
Population population(m_fitnessMetric, {Chromosome("aa"), Chromosome("cc"), Chromosome("gg"), Chromosome("hh")});
|
||||
PairMosaicSelection selection({{0, 0}, {2, 1}}, 1.0);
|
||||
assert(selection.materialise(population.individuals().size()) == (vector<tuple<size_t, size_t>>{{0, 0}, {2, 1}, {0, 0}, {2, 1}}));
|
||||
|
||||
Population expectedCrossedPopulation(m_fitnessMetric, {
|
||||
Chromosome("aa"), Chromosome("aa"),
|
||||
Chromosome("aa"), Chromosome("aa"),
|
||||
Chromosome("gc"), Chromosome("cg"),
|
||||
Chromosome("gc"), Chromosome("cg"),
|
||||
});
|
||||
Population expectedRemainder(m_fitnessMetric, {Chromosome("hh")});
|
||||
|
||||
BOOST_TEST(
|
||||
population.symmetricCrossoverWithRemainder(selection, twoStepSwap) ==
|
||||
(tuple<Population, Population>{expectedCrossedPopulation, expectedRemainder})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(symmetricCrossoverWithRemainder_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.symmetricCrossoverWithRemainder(selection, twoStepSwap) ==
|
||||
(tuple<Population, Population>{Population(m_fitnessMetric), population})
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
@ -117,6 +117,37 @@ Population Population::crossover(PairSelection const& _selection, function<Cross
|
||||
return Population(m_fitnessMetric, crossedIndividuals);
|
||||
}
|
||||
|
||||
tuple<Population, Population> Population::symmetricCrossoverWithRemainder(
|
||||
PairSelection const& _selection,
|
||||
function<SymmetricCrossover> _symmetricCrossover
|
||||
) const
|
||||
{
|
||||
vector<int> indexSelected(m_individuals.size(), false);
|
||||
|
||||
vector<Individual> crossedIndividuals;
|
||||
for (auto const& [i, j]: _selection.materialise(m_individuals.size()))
|
||||
{
|
||||
auto children = _symmetricCrossover(
|
||||
m_individuals[i].chromosome,
|
||||
m_individuals[j].chromosome
|
||||
);
|
||||
crossedIndividuals.emplace_back(move(get<0>(children)), *m_fitnessMetric);
|
||||
crossedIndividuals.emplace_back(move(get<1>(children)), *m_fitnessMetric);
|
||||
indexSelected[i] = true;
|
||||
indexSelected[j] = true;
|
||||
}
|
||||
|
||||
vector<Individual> remainder;
|
||||
for (size_t i = 0; i < indexSelected.size(); ++i)
|
||||
if (!indexSelected[i])
|
||||
remainder.emplace_back(m_individuals[i]);
|
||||
|
||||
return {
|
||||
Population(m_fitnessMetric, crossedIndividuals),
|
||||
Population(m_fitnessMetric, remainder),
|
||||
};
|
||||
}
|
||||
|
||||
namespace solidity::phaser
|
||||
{
|
||||
|
||||
|
@ -100,6 +100,10 @@ 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;
|
||||
std::tuple<Population, Population> symmetricCrossoverWithRemainder(
|
||||
PairSelection const& _selection,
|
||||
std::function<SymmetricCrossover> _symmetricCrossover
|
||||
) const;
|
||||
|
||||
friend Population operator+(Population _a, Population _b);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user