mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] Store already loaded program in Population and make copies when computing fitness
- Until now the source code was being parsed during every fitness computation. Now the parsed program is reused and only the optimisation steps are applied each time.
This commit is contained in:
parent
57fb64d467
commit
e4c7b73897
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <tools/yulPhaser/Chromosome.h>
|
#include <tools/yulPhaser/Chromosome.h>
|
||||||
#include <tools/yulPhaser/Population.h>
|
#include <tools/yulPhaser/Population.h>
|
||||||
|
#include <tools/yulPhaser/Program.h>
|
||||||
|
|
||||||
#include <libyul/optimiser/BlockFlattener.h>
|
#include <libyul/optimiser/BlockFlattener.h>
|
||||||
#include <libyul/optimiser/SSAReverser.h>
|
#include <libyul/optimiser/SSAReverser.h>
|
||||||
@ -85,7 +86,7 @@ BOOST_AUTO_TEST_CASE(constructor_should_copy_chromosomes_and_not_compute_fitness
|
|||||||
Chromosome::makeRandom(5),
|
Chromosome::makeRandom(5),
|
||||||
Chromosome::makeRandom(10),
|
Chromosome::makeRandom(10),
|
||||||
};
|
};
|
||||||
Population population(sourceStream, chromosomes);
|
Population population(Program::load(sourceStream), chromosomes);
|
||||||
|
|
||||||
BOOST_TEST(population.individuals().size() == 2);
|
BOOST_TEST(population.individuals().size() == 2);
|
||||||
BOOST_TEST(population.individuals()[0].chromosome == chromosomes[0]);
|
BOOST_TEST(population.individuals()[0].chromosome == chromosomes[0]);
|
||||||
@ -98,8 +99,9 @@ BOOST_AUTO_TEST_CASE(constructor_should_copy_chromosomes_and_not_compute_fitness
|
|||||||
BOOST_AUTO_TEST_CASE(makeRandom_should_return_population_with_random_chromosomes)
|
BOOST_AUTO_TEST_CASE(makeRandom_should_return_population_with_random_chromosomes)
|
||||||
{
|
{
|
||||||
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
||||||
auto population1 = Population::makeRandom(sourceStream, 100);
|
auto program = Program::load(sourceStream);
|
||||||
auto population2 = Population::makeRandom(sourceStream, 100);
|
auto population1 = Population::makeRandom(program, 100);
|
||||||
|
auto population2 = Population::makeRandom(program, 100);
|
||||||
|
|
||||||
BOOST_TEST(population1.individuals().size() == 100);
|
BOOST_TEST(population1.individuals().size() == 100);
|
||||||
BOOST_TEST(population2.individuals().size() == 100);
|
BOOST_TEST(population2.individuals().size() == 100);
|
||||||
@ -118,7 +120,7 @@ BOOST_AUTO_TEST_CASE(makeRandom_should_return_population_with_random_chromosomes
|
|||||||
BOOST_AUTO_TEST_CASE(makeRandom_should_not_compute_fitness)
|
BOOST_AUTO_TEST_CASE(makeRandom_should_not_compute_fitness)
|
||||||
{
|
{
|
||||||
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
||||||
auto population = Population::makeRandom(sourceStream, 5);
|
auto population = Population::makeRandom(Program::load(sourceStream), 5);
|
||||||
|
|
||||||
BOOST_TEST(all_of(population.individuals().begin(), population.individuals().end(), fitnessNotSet));
|
BOOST_TEST(all_of(population.individuals().begin(), population.individuals().end(), fitnessNotSet));
|
||||||
}
|
}
|
||||||
@ -127,7 +129,7 @@ BOOST_AUTO_TEST_CASE(run_should_evaluate_fitness)
|
|||||||
{
|
{
|
||||||
stringstream output;
|
stringstream output;
|
||||||
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
CharStream sourceStream(sampleSourceCode, current_test_case().p_name);
|
||||||
auto population = Population::makeRandom(sourceStream, 5);
|
auto population = Population::makeRandom(Program::load(sourceStream), 5);
|
||||||
assert(all_of(population.individuals().begin(), population.individuals().end(), fitnessNotSet));
|
assert(all_of(population.individuals().begin(), population.individuals().end(), fitnessNotSet));
|
||||||
|
|
||||||
population.run(1, output);
|
population.run(1, output);
|
||||||
@ -146,11 +148,12 @@ BOOST_AUTO_TEST_CASE(run_should_not_make_fitness_of_top_chromosomes_worse)
|
|||||||
Chromosome({UnusedPruner::name}),
|
Chromosome({UnusedPruner::name}),
|
||||||
Chromosome({StructuralSimplifier::name, BlockFlattener::name}),
|
Chromosome({StructuralSimplifier::name, BlockFlattener::name}),
|
||||||
};
|
};
|
||||||
Population population(sourceStream, chromosomes);
|
auto program = Program::load(sourceStream);
|
||||||
|
Population population(program, chromosomes);
|
||||||
|
|
||||||
size_t initialTopFitness[2] = {
|
size_t initialTopFitness[2] = {
|
||||||
Population::measureFitness(chromosomes[0], sourceStream),
|
Population::measureFitness(chromosomes[0], program),
|
||||||
Population::measureFitness(chromosomes[1], sourceStream),
|
Population::measureFitness(chromosomes[1], program),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
|
@ -49,27 +49,27 @@ ostream& phaser::operator<<(ostream& _stream, Individual const& _individual)
|
|||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
Population::Population(CharStream _sourceCode, vector<Chromosome> const& _chromosomes):
|
Population::Population(Program _program, vector<Chromosome> const& _chromosomes):
|
||||||
m_sourceCode{move(_sourceCode)}
|
m_program{move(_program)}
|
||||||
{
|
{
|
||||||
for (auto const& chromosome: _chromosomes)
|
for (auto const& chromosome: _chromosomes)
|
||||||
m_individuals.push_back({chromosome});
|
m_individuals.push_back({chromosome});
|
||||||
}
|
}
|
||||||
|
|
||||||
Population Population::makeRandom(CharStream _sourceCode, size_t _size)
|
Population Population::makeRandom(Program _program, size_t _size)
|
||||||
{
|
{
|
||||||
vector<Individual> individuals;
|
vector<Individual> individuals;
|
||||||
for (size_t i = 0; i < _size; ++i)
|
for (size_t i = 0; i < _size; ++i)
|
||||||
individuals.push_back({Chromosome::makeRandom(randomChromosomeLength())});
|
individuals.push_back({Chromosome::makeRandom(randomChromosomeLength())});
|
||||||
|
|
||||||
return Population(move(_sourceCode), individuals);
|
return Population(move(_program), individuals);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Population::measureFitness(Chromosome const& _chromosome, CharStream& _sourceCode)
|
size_t Population::measureFitness(Chromosome const& _chromosome, Program const& _program)
|
||||||
{
|
{
|
||||||
auto program = Program::load(_sourceCode);
|
Program programCopy = _program;
|
||||||
program.optimise(_chromosome.optimisationSteps());
|
programCopy.optimise(_chromosome.optimisationSteps());
|
||||||
return program.codeSize();
|
return programCopy.codeSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Population::run(optional<size_t> _numRounds, ostream& _outputStream)
|
void Population::run(optional<size_t> _numRounds, ostream& _outputStream)
|
||||||
@ -88,8 +88,6 @@ void Population::run(optional<size_t> _numRounds, ostream& _outputStream)
|
|||||||
|
|
||||||
ostream& phaser::operator<<(ostream& _stream, Population const& _population)
|
ostream& phaser::operator<<(ostream& _stream, Population const& _population)
|
||||||
{
|
{
|
||||||
_stream << "Stream name: " << _population.m_sourceCode.name() << endl;
|
|
||||||
|
|
||||||
auto individual = _population.m_individuals.begin();
|
auto individual = _population.m_individuals.begin();
|
||||||
for (; individual != _population.m_individuals.end(); ++individual)
|
for (; individual != _population.m_individuals.end(); ++individual)
|
||||||
_stream << *individual << endl;
|
_stream << *individual << endl;
|
||||||
@ -106,7 +104,7 @@ void Population::doEvaluation()
|
|||||||
{
|
{
|
||||||
for (auto& individual: m_individuals)
|
for (auto& individual: m_individuals)
|
||||||
if (!individual.fitness.has_value())
|
if (!individual.fitness.has_value())
|
||||||
individual.fitness = measureFitness(individual.chromosome, m_sourceCode);
|
individual.fitness = measureFitness(individual.chromosome, m_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Population::doSelection()
|
void Population::doSelection()
|
||||||
|
@ -18,10 +18,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tools/yulPhaser/Chromosome.h>
|
#include <tools/yulPhaser/Chromosome.h>
|
||||||
|
#include <tools/yulPhaser/Program.h>
|
||||||
#include <tools/yulPhaser/Random.h>
|
#include <tools/yulPhaser/Random.h>
|
||||||
|
|
||||||
#include <liblangutil/CharStream.h>
|
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -47,7 +46,7 @@ struct Individual
|
|||||||
* and selecting the best ones for the next round.
|
* and selecting the best ones for the next round.
|
||||||
*
|
*
|
||||||
* An individual is a sequence of optimiser steps represented by a @a Chromosome instance. The whole
|
* An individual is a sequence of optimiser steps represented by a @a Chromosome instance. The whole
|
||||||
* population is associated with a fixed Yul program. By loading the source code into a @a Program
|
* population is associated with a fixed Yul program. By applying the steps to the @a Program
|
||||||
* instance the class can compute fitness of the individual.
|
* instance the class can compute fitness of the individual.
|
||||||
*/
|
*/
|
||||||
class Population
|
class Population
|
||||||
@ -55,21 +54,21 @@ class Population
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t MaxChromosomeLength = 30;
|
static constexpr size_t MaxChromosomeLength = 30;
|
||||||
|
|
||||||
explicit Population(langutil::CharStream _sourceCode, std::vector<Chromosome> const& _chromosomes = {});
|
explicit Population(Program _program, std::vector<Chromosome> const& _chromosomes = {});
|
||||||
static Population makeRandom(langutil::CharStream _sourceCode, size_t _size);
|
static Population makeRandom(Program _program, size_t _size);
|
||||||
|
|
||||||
void run(std::optional<size_t> _numRounds, std::ostream& _outputStream);
|
void run(std::optional<size_t> _numRounds, std::ostream& _outputStream);
|
||||||
|
|
||||||
std::vector<Individual> const& individuals() const { return m_individuals; }
|
std::vector<Individual> const& individuals() const { return m_individuals; }
|
||||||
|
|
||||||
static size_t randomChromosomeLength() { return binomialRandomInt(MaxChromosomeLength, 0.5); }
|
static size_t randomChromosomeLength() { return binomialRandomInt(MaxChromosomeLength, 0.5); }
|
||||||
static size_t measureFitness(Chromosome const& _chromosome, langutil::CharStream& _sourceCode);
|
static size_t measureFitness(Chromosome const& _chromosome, Program const& _program);
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& _stream, Population const& _population);
|
friend std::ostream& operator<<(std::ostream& _stream, Population const& _population);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Population(langutil::CharStream _sourceCode, std::vector<Individual> _individuals = {}):
|
explicit Population(Program _program, std::vector<Individual> _individuals = {}):
|
||||||
m_sourceCode{std::move(_sourceCode)},
|
m_program{std::move(_program)},
|
||||||
m_individuals{std::move(_individuals)} {}
|
m_individuals{std::move(_individuals)} {}
|
||||||
|
|
||||||
void doMutation();
|
void doMutation();
|
||||||
@ -81,8 +80,7 @@ private:
|
|||||||
size_t _count
|
size_t _count
|
||||||
);
|
);
|
||||||
|
|
||||||
langutil::CharStream m_sourceCode;
|
Program m_program;
|
||||||
|
|
||||||
std::vector<Individual> m_individuals;
|
std::vector<Individual> m_individuals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <tools/yulPhaser/Exceptions.h>
|
#include <tools/yulPhaser/Exceptions.h>
|
||||||
#include <tools/yulPhaser/Population.h>
|
#include <tools/yulPhaser/Population.h>
|
||||||
|
#include <tools/yulPhaser/Program.h>
|
||||||
|
|
||||||
#include <libsolutil/Assertions.h>
|
#include <libsolutil/Assertions.h>
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
@ -54,7 +55,8 @@ CharStream loadSource(string const& _sourcePath)
|
|||||||
|
|
||||||
void runAlgorithm(string const& _sourcePath)
|
void runAlgorithm(string const& _sourcePath)
|
||||||
{
|
{
|
||||||
auto population = Population::makeRandom(loadSource(_sourcePath), 10);
|
CharStream sourceCode = loadSource(_sourcePath);
|
||||||
|
auto population = Population::makeRandom(Program::load(sourceCode), 10);
|
||||||
population.run(nullopt, cout);
|
population.run(nullopt, cout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user