[yul-phaser] Command-line options for altering weights used by CodeSize metric

This commit is contained in:
Kamil Śliwak 2020-02-29 21:57:14 +01:00
parent 40dfac7683
commit b776021870
3 changed files with 80 additions and 11 deletions

View File

@ -32,6 +32,7 @@
using namespace std; using namespace std;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::yul;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -86,6 +87,7 @@ protected:
/* relativeMetricScale = */ 5, /* relativeMetricScale = */ 5,
/* chromosomeRepetitions = */ 1, /* chromosomeRepetitions = */ 1,
}; };
CodeWeights const m_weights{};
}; };
class PoulationFactoryFixture class PoulationFactoryFixture
@ -183,7 +185,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_of_the_right_type, FitnessMet
{ {
m_options.metric = MetricChoice::RelativeCodeSize; m_options.metric = MetricChoice::RelativeCodeSize;
m_options.metricAggregator = MetricAggregatorChoice::Sum; m_options.metricAggregator = MetricAggregatorChoice::Sum;
unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights);
BOOST_REQUIRE(metric != nullptr); BOOST_REQUIRE(metric != nullptr);
auto sumMetric = dynamic_cast<FitnessMetricSum*>(metric.get()); auto sumMetric = dynamic_cast<FitnessMetricSum*>(metric.get());
@ -201,7 +203,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_chromosome_repetitions_option, Fitn
m_options.metric = MetricChoice::CodeSize; m_options.metric = MetricChoice::CodeSize;
m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.metricAggregator = MetricAggregatorChoice::Average;
m_options.chromosomeRepetitions = 5; m_options.chromosomeRepetitions = 5;
unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights);
BOOST_REQUIRE(metric != nullptr); BOOST_REQUIRE(metric != nullptr);
auto averageMetric = dynamic_cast<FitnessMetricAverage*>(metric.get()); auto averageMetric = dynamic_cast<FitnessMetricAverage*>(metric.get());
@ -219,7 +221,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFac
m_options.metric = MetricChoice::RelativeCodeSize; m_options.metric = MetricChoice::RelativeCodeSize;
m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.metricAggregator = MetricAggregatorChoice::Average;
m_options.relativeMetricScale = 10; m_options.relativeMetricScale = 10;
unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}, m_weights);
BOOST_REQUIRE(metric != nullptr); BOOST_REQUIRE(metric != nullptr);
auto averageMetric = dynamic_cast<FitnessMetricAverage*>(metric.get()); auto averageMetric = dynamic_cast<FitnessMetricAverage*>(metric.get());
@ -237,7 +239,8 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_for_each_input_program, Fitne
unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build( unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(
m_options, m_options,
m_programs, m_programs,
vector<shared_ptr<ProgramCache>>(m_programs.size(), nullptr) vector<shared_ptr<ProgramCache>>(m_programs.size(), nullptr),
m_weights
); );
BOOST_REQUIRE(metric != nullptr); BOOST_REQUIRE(metric != nullptr);
@ -256,7 +259,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_pass_program_caches_to_metrics, FitnessMetr
}; };
m_options.metric = MetricChoice::RelativeCodeSize; m_options.metric = MetricChoice::RelativeCodeSize;
unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, m_programs, caches); unique_ptr<FitnessMetric> metric = FitnessMetricFactory::build(m_options, m_programs, caches, m_weights);
BOOST_REQUIRE(metric != nullptr); BOOST_REQUIRE(metric != nullptr);
auto combinedMetric = dynamic_cast<FitnessMetricCombination*>(metric.get()); auto combinedMetric = dynamic_cast<FitnessMetricCombination*>(metric.get());

View File

@ -189,6 +189,27 @@ unique_ptr<GeneticAlgorithm> GeneticAlgorithmFactory::build(
} }
} }
CodeWeights CodeWeightFactory::buildFromCommandLine(po::variables_map const& _arguments)
{
return {
_arguments["expression-statement-cost"].as<size_t>(),
_arguments["assignment-cost"].as<size_t>(),
_arguments["variable-declaration-cost"].as<size_t>(),
_arguments["function-definition-cost"].as<size_t>(),
_arguments["if-cost"].as<size_t>(),
_arguments["switch-cost"].as<size_t>(),
_arguments["case-cost"].as<size_t>(),
_arguments["for-loop-cost"].as<size_t>(),
_arguments["break-cost"].as<size_t>(),
_arguments["continue-cost"].as<size_t>(),
_arguments["leave-cost"].as<size_t>(),
_arguments["block-cost"].as<size_t>(),
_arguments["function-call-cost"].as<size_t>(),
_arguments["identifier-cost"].as<size_t>(),
_arguments["literal-cost"].as<size_t>(),
};
}
FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po::variables_map const& _arguments) FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po::variables_map const& _arguments)
{ {
return { return {
@ -202,7 +223,8 @@ FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po:
unique_ptr<FitnessMetric> FitnessMetricFactory::build( unique_ptr<FitnessMetric> FitnessMetricFactory::build(
Options const& _options, Options const& _options,
vector<Program> _programs, vector<Program> _programs,
vector<shared_ptr<ProgramCache>> _programCaches vector<shared_ptr<ProgramCache>> _programCaches,
CodeWeights const& _weights
) )
{ {
assert(_programCaches.size() == _programs.size()); assert(_programCaches.size() == _programs.size());
@ -217,7 +239,7 @@ unique_ptr<FitnessMetric> FitnessMetricFactory::build(
metrics.push_back(make_unique<ProgramSize>( metrics.push_back(make_unique<ProgramSize>(
_programCaches[i] != nullptr ? optional<Program>{} : move(_programs[i]), _programCaches[i] != nullptr ? optional<Program>{} : move(_programs[i]),
move(_programCaches[i]), move(_programCaches[i]),
CodeWeights{}, _weights,
_options.chromosomeRepetitions _options.chromosomeRepetitions
)); ));
@ -230,7 +252,7 @@ unique_ptr<FitnessMetric> FitnessMetricFactory::build(
_programCaches[i] != nullptr ? optional<Program>{} : move(_programs[i]), _programCaches[i] != nullptr ? optional<Program>{} : move(_programs[i]),
move(_programCaches[i]), move(_programCaches[i]),
_options.relativeMetricScale, _options.relativeMetricScale,
CodeWeights{}, _weights,
_options.chromosomeRepetitions _options.chromosomeRepetitions
)); ));
break; break;
@ -656,6 +678,26 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription()
; ;
keywordDescription.add(metricsDescription); keywordDescription.add(metricsDescription);
po::options_description metricWeightDescription("METRIC WEIGHTS", lineLength, minDescriptionLength);
metricWeightDescription.add_options()
("expression-statement-cost", po::value<size_t>()->value_name("<COST>")->default_value(0))
("assignment-cost", po::value<size_t>()->value_name("<COST>")->default_value(0))
("variable-declaration-cost", po::value<size_t>()->value_name("<COST>")->default_value(0))
("function-definition-cost", po::value<size_t>()->value_name("<COST>")->default_value(1))
("if-cost", po::value<size_t>()->value_name("<COST>")->default_value(2))
("switch-cost", po::value<size_t>()->value_name("<COST>")->default_value(1))
("case-cost", po::value<size_t>()->value_name("<COST>")->default_value(2))
("for-loop-cost", po::value<size_t>()->value_name("<COST>")->default_value(3))
("break-cost", po::value<size_t>()->value_name("<COST>")->default_value(2))
("continue-cost", po::value<size_t>()->value_name("<COST>")->default_value(2))
("leave-cost", po::value<size_t>()->value_name("<COST>")->default_value(2))
("block-cost", po::value<size_t>()->value_name("<COST>")->default_value(0))
("function-call-cost", po::value<size_t>()->value_name("<COST>")->default_value(1))
("identifier-cost", po::value<size_t>()->value_name("<COST>")->default_value(0))
("literal-cost", po::value<size_t>()->value_name("<COST>")->default_value(1))
;
keywordDescription.add(metricWeightDescription);
po::options_description cacheDescription("CACHE", lineLength, minDescriptionLength); po::options_description cacheDescription("CACHE", lineLength, minDescriptionLength);
cacheDescription.add_options() cacheDescription.add_options()
( (
@ -765,8 +807,13 @@ void Phaser::runPhaser(po::variables_map const& _arguments)
vector<Program> programs = ProgramFactory::build(programOptions); vector<Program> programs = ProgramFactory::build(programOptions);
vector<shared_ptr<ProgramCache>> programCaches = ProgramCacheFactory::build(cacheOptions, programs); vector<shared_ptr<ProgramCache>> programCaches = ProgramCacheFactory::build(cacheOptions, programs);
CodeWeights codeWeights = CodeWeightFactory::buildFromCommandLine(_arguments);
unique_ptr<FitnessMetric> fitnessMetric = FitnessMetricFactory::build(metricOptions, programs, programCaches); unique_ptr<FitnessMetric> fitnessMetric = FitnessMetricFactory::build(
metricOptions,
programs,
programCaches,
codeWeights
);
Population population = PopulationFactory::build(populationOptions, move(fitnessMetric)); Population population = PopulationFactory::build(populationOptions, move(fitnessMetric));
if (_arguments["mode"].as<PhaserMode>() == PhaserMode::RunAlgorithm) if (_arguments["mode"].as<PhaserMode>() == PhaserMode::RunAlgorithm)

View File

@ -39,6 +39,13 @@ class CharStream;
} }
namespace solidity::yul
{
struct CodeWeights;
}
namespace solidity::phaser namespace solidity::phaser
{ {
@ -125,6 +132,17 @@ public:
); );
}; };
/**
* Builds and validates instances of @a CodeWeights.
*/
class CodeWeightFactory
{
public:
static yul::CodeWeights buildFromCommandLine(
boost::program_options::variables_map const& _arguments
);
};
/** /**
* Builds and validates instances of @a FitnessMetric and its derived classes. * Builds and validates instances of @a FitnessMetric and its derived classes.
*/ */
@ -144,7 +162,8 @@ public:
static std::unique_ptr<FitnessMetric> build( static std::unique_ptr<FitnessMetric> build(
Options const& _options, Options const& _options,
std::vector<Program> _programs, std::vector<Program> _programs,
std::vector<std::shared_ptr<ProgramCache>> _programCaches std::vector<std::shared_ptr<ProgramCache>> _programCaches,
yul::CodeWeights const& _weights
); );
}; };