diff --git a/test/yulPhaser/Phaser.cpp b/test/yulPhaser/Phaser.cpp index ea06dd771..aab34db61 100644 --- a/test/yulPhaser/Phaser.cpp +++ b/test/yulPhaser/Phaser.cpp @@ -70,6 +70,7 @@ protected: }; FitnessMetricFactory::Options m_options = { /* metric = */ MetricChoice::CodeSize, + /* metricAggregator = */ MetricAggregatorChoice::Average, /* relativeMetricScale = */ 5, /* chromosomeRepetitions = */ 1, }; @@ -152,15 +153,16 @@ BOOST_AUTO_TEST_SUITE(FitnessMetricFactoryTest) BOOST_FIXTURE_TEST_CASE(build_should_create_metric_of_the_right_type, FitnessMetricFactoryFixture) { m_options.metric = MetricChoice::RelativeCodeSize; + m_options.metricAggregator = MetricAggregatorChoice::Sum; unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); BOOST_REQUIRE(metric != nullptr); - auto averageMetric = dynamic_cast(metric.get()); - BOOST_REQUIRE(averageMetric != nullptr); - BOOST_REQUIRE(averageMetric->metrics().size() == 1); - BOOST_REQUIRE(averageMetric->metrics()[0] != nullptr); + auto sumMetric = dynamic_cast(metric.get()); + BOOST_REQUIRE(sumMetric != nullptr); + BOOST_REQUIRE(sumMetric->metrics().size() == 1); + BOOST_REQUIRE(sumMetric->metrics()[0] != nullptr); - auto relativeProgramSizeMetric = dynamic_cast(averageMetric->metrics()[0].get()); + auto relativeProgramSizeMetric = dynamic_cast(sumMetric->metrics()[0].get()); BOOST_REQUIRE(relativeProgramSizeMetric != nullptr); BOOST_TEST(toString(relativeProgramSizeMetric->program()) == toString(m_programs[0])); } @@ -168,6 +170,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_of_the_right_type, FitnessMet BOOST_FIXTURE_TEST_CASE(build_should_respect_chromosome_repetitions_option, FitnessMetricFactoryFixture) { m_options.metric = MetricChoice::CodeSize; + m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.chromosomeRepetitions = 5; unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); BOOST_REQUIRE(metric != nullptr); @@ -185,6 +188,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_chromosome_repetitions_option, Fitn BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFactoryFixture) { m_options.metric = MetricChoice::RelativeCodeSize; + m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.relativeMetricScale = 10; unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); BOOST_REQUIRE(metric != nullptr); diff --git a/tools/yulPhaser/Phaser.cpp b/tools/yulPhaser/Phaser.cpp index d0d9d9a1e..c62b62dc3 100644 --- a/tools/yulPhaser/Phaser.cpp +++ b/tools/yulPhaser/Phaser.cpp @@ -60,12 +60,23 @@ map MetricChoiceToStringMap = }; map const StringToMetricChoiceMap = invertMap(MetricChoiceToStringMap); +map const MetricAggregatorChoiceToStringMap = +{ + {MetricAggregatorChoice::Average, "average"}, + {MetricAggregatorChoice::Sum, "sum"}, + {MetricAggregatorChoice::Maximum, "maximum"}, + {MetricAggregatorChoice::Minimum, "minimum"}, +}; +map const StringToMetricAggregatorChoiceMap = invertMap(MetricAggregatorChoiceToStringMap); + } istream& phaser::operator>>(istream& _inputStream, Algorithm& _algorithm) { return deserializeChoice(_inputStream, _algorithm, StringToAlgorithmMap); } ostream& phaser::operator<<(ostream& _outputStream, Algorithm _algorithm) { return serializeChoice(_outputStream, _algorithm, AlgorithmToStringMap); } istream& phaser::operator>>(istream& _inputStream, MetricChoice& _metric) { return deserializeChoice(_inputStream, _metric, StringToMetricChoiceMap); } ostream& phaser::operator<<(ostream& _outputStream, MetricChoice _metric) { return serializeChoice(_outputStream, _metric, MetricChoiceToStringMap); } +istream& phaser::operator>>(istream& _inputStream, MetricAggregatorChoice& _aggregator) { return deserializeChoice(_inputStream, _aggregator, StringToMetricAggregatorChoiceMap); } +ostream& phaser::operator<<(ostream& _outputStream, MetricAggregatorChoice _aggregator) { return serializeChoice(_outputStream, _aggregator, MetricAggregatorChoiceToStringMap); } GeneticAlgorithmFactory::Options GeneticAlgorithmFactory::Options::fromCommandLine(po::variables_map const& _arguments) { @@ -139,6 +150,7 @@ FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po: { return { _arguments["metric"].as(), + _arguments["metric-aggregator"].as(), _arguments["relative-metric-scale"].as(), _arguments["chromosome-repetitions"].as(), }; @@ -178,7 +190,19 @@ unique_ptr FitnessMetricFactory::build( assertThrow(false, solidity::util::Exception, "Invalid MetricChoice value."); } - return make_unique(move(metrics)); + switch (_options.metricAggregator) + { + case MetricAggregatorChoice::Average: + return make_unique(move(metrics)); + case MetricAggregatorChoice::Sum: + return make_unique(move(metrics)); + case MetricAggregatorChoice::Maximum: + return make_unique(move(metrics)); + case MetricAggregatorChoice::Minimum: + return make_unique(move(metrics)); + default: + assertThrow(false, solidity::util::Exception, "Invalid MetricAggregatorChoice value."); + } } PopulationFactory::Options PopulationFactory::Options::fromCommandLine(po::variables_map const& _arguments) @@ -442,6 +466,12 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription() po::value()->value_name("")->default_value(MetricChoice::CodeSize), "Metric used to evaluate the fitness of a chromosome." ) + ( + "metric-aggregator", + po::value()->value_name("")->default_value(MetricAggregatorChoice::Average), + "Operator used to combine multiple fitness metric obtained by evaluating a chromosome " + "separately for each input program." + ) ( "relative-metric-scale", po::value()->value_name("")->default_value(3), diff --git a/tools/yulPhaser/Phaser.h b/tools/yulPhaser/Phaser.h index 55c808f07..2e72c31f6 100644 --- a/tools/yulPhaser/Phaser.h +++ b/tools/yulPhaser/Phaser.h @@ -58,10 +58,20 @@ enum class MetricChoice RelativeCodeSize, }; +enum class MetricAggregatorChoice +{ + Average, + Sum, + Maximum, + Minimum, +}; + std::istream& operator>>(std::istream& _inputStream, solidity::phaser::Algorithm& _algorithm); std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::Algorithm _algorithm); std::istream& operator>>(std::istream& _inputStream, solidity::phaser::MetricChoice& _metric); std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::MetricChoice _metric); +std::istream& operator>>(std::istream& _inputStream, solidity::phaser::MetricAggregatorChoice& _aggregator); +std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::MetricAggregatorChoice _aggregator); /** * Builds and validates instances of @a GeneticAlgorithm and its derived classes. @@ -100,6 +110,7 @@ public: struct Options { MetricChoice metric; + MetricAggregatorChoice metricAggregator; size_t relativeMetricScale; size_t chromosomeRepetitions;