mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] Add RandomAlgorithm
This commit is contained in:
parent
4665b7a7e4
commit
67fbafab8f
@ -89,6 +89,49 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_the_top_chromosome, GeneticAlgorithmFix
|
||||
BOOST_TEST(countSubstringOccurrences(m_output.str(), toString(algorithm.population().individuals()[0].chromosome)) == 4);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE(RandomAlgorithmTest)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(runNextRound_should_preserve_elite_and_randomise_rest_of_population, GeneticAlgorithmFixture)
|
||||
{
|
||||
auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5);
|
||||
RandomAlgorithm algorithm(population, m_output, {0.5, 1, 1});
|
||||
assert((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 5, 5, 5, 5}));
|
||||
|
||||
algorithm.runNextRound();
|
||||
BOOST_TEST((chromosomeLengths(algorithm.population()) == vector<size_t>{1, 1, 1, 1, 3, 3, 3, 3}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_elite_with_worse_individuals, GeneticAlgorithmFixture)
|
||||
{
|
||||
auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5);
|
||||
RandomAlgorithm algorithm(population, m_output, {0.5, 7, 7});
|
||||
assert((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 5, 5, 5, 5}));
|
||||
|
||||
algorithm.runNextRound();
|
||||
BOOST_TEST((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 7, 7, 7, 7}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(runNextRound_should_replace_all_chromosomes_if_zero_size_elite, GeneticAlgorithmFixture)
|
||||
{
|
||||
auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5);
|
||||
RandomAlgorithm algorithm(population, m_output, {0.0, 1, 1});
|
||||
assert((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 5, 5, 5, 5}));
|
||||
|
||||
algorithm.runNextRound();
|
||||
BOOST_TEST((chromosomeLengths(algorithm.population()) == vector<size_t>{1, 1, 1, 1, 1, 1, 1, 1}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(runNextRound_should_not_replace_any_chromosomes_if_whole_population_is_the_elite, GeneticAlgorithmFixture)
|
||||
{
|
||||
auto population = Population::makeRandom(m_fitnessMetric, 4, 3, 3) + Population::makeRandom(m_fitnessMetric, 4, 5, 5);
|
||||
RandomAlgorithm algorithm(population, m_output, {1.0, 1, 1});
|
||||
assert((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 5, 5, 5, 5}));
|
||||
|
||||
algorithm.runNextRound();
|
||||
BOOST_TEST((chromosomeLengths(algorithm.population()) == vector<size_t>{3, 3, 3, 3, 5, 5, 5, 5}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <tools/yulPhaser/GeneticAlgorithms.h>
|
||||
#include <tools/yulPhaser/Selections.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::phaser;
|
||||
@ -30,3 +31,20 @@ void GeneticAlgorithm::run(optional<size_t> _numRounds)
|
||||
m_outputStream << m_population;
|
||||
}
|
||||
}
|
||||
|
||||
void RandomAlgorithm::runNextRound()
|
||||
{
|
||||
RangeSelection elite(0.0, m_options.elitePoolSize);
|
||||
|
||||
Population elitePopulation = m_population.select(elite);
|
||||
size_t replacementCount = m_population.individuals().size() - elitePopulation.individuals().size();
|
||||
|
||||
m_population =
|
||||
move(elitePopulation) +
|
||||
Population::makeRandom(
|
||||
m_population.fitnessMetric(),
|
||||
replacementCount,
|
||||
m_options.minChromosomeLength,
|
||||
m_options.maxChromosomeLength
|
||||
);
|
||||
}
|
||||
|
@ -63,4 +63,53 @@ private:
|
||||
std::ostream& m_outputStream;
|
||||
};
|
||||
|
||||
/**
|
||||
* Completely random genetic algorithm,
|
||||
*
|
||||
* The algorithm simply replaces the worst chromosomes with entirely new ones, generated
|
||||
* randomly and not based on any member of the current population. Only a constant proportion of the
|
||||
* chromosomes (the elite) is preserved in each round.
|
||||
*
|
||||
* Preserves the size of the population. You can use @a elitePoolSize to make the algorithm
|
||||
* generational (replacing most members in each round) or steady state (replacing only one member).
|
||||
* Both versions are equivalent in terms of the outcome but the generational one converges in a
|
||||
* smaller number of rounds while the steady state one does less work per round. This may matter
|
||||
* in case of metrics that take a long time to compute though in case of this particular
|
||||
* algorithm the same result could also be achieved by simply making the population smaller.
|
||||
*/
|
||||
class RandomAlgorithm: public GeneticAlgorithm
|
||||
{
|
||||
public:
|
||||
struct Options
|
||||
{
|
||||
double elitePoolSize; ///< Percentage of the population treated as the elite
|
||||
size_t minChromosomeLength; ///< Minimum length of newly generated chromosomes
|
||||
size_t maxChromosomeLength; ///< Maximum length of newly generated chromosomes
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return (
|
||||
0 <= elitePoolSize && elitePoolSize <= 1.0 &&
|
||||
minChromosomeLength <= maxChromosomeLength
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
explicit RandomAlgorithm(
|
||||
Population _initialPopulation,
|
||||
std::ostream& _outputStream,
|
||||
Options const& _options
|
||||
):
|
||||
GeneticAlgorithm(_initialPopulation, _outputStream),
|
||||
m_options(_options)
|
||||
{
|
||||
assert(_options.isValid());
|
||||
}
|
||||
|
||||
void runNextRound() override;
|
||||
|
||||
private:
|
||||
Options m_options;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user