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_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()
|
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/GeneticAlgorithms.h>
|
||||||
|
#include <tools/yulPhaser/Selections.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity::phaser;
|
using namespace solidity::phaser;
|
||||||
@ -30,3 +31,20 @@ void GeneticAlgorithm::run(optional<size_t> _numRounds)
|
|||||||
m_outputStream << m_population;
|
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;
|
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