From ecb30c670fef1a6eeace327336d91d214b79ac07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 11 Feb 2020 22:25:17 +0100 Subject: [PATCH] [yul-phaser] Population: Make ordering of individuals with same fitness deterministic and prioritise shorter chromosomes - Before this change the order of chromosomes with the same fitness in a population depended on the initial order set when the population was first created. Now it only depends on the individual. - The length comparison is not strictly necessary (lexicographical order covers that) but it makes the intention clear and the comparison slightly faster when chromosomes have different lengths. --- test/yulPhaser/Population.cpp | 12 ++++++++++++ tools/yulPhaser/Population.cpp | 9 ++++++++- tools/yulPhaser/Population.h | 4 +++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index 695d6b397..bb2f4cc05 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -104,6 +104,18 @@ BOOST_AUTO_TEST_CASE(isFitter_should_use_fitness_as_the_main_criterion) BOOST_TEST(!isFitter(Individual{Chromosome("aaa"), 10}, Individual{Chromosome("aaaaa"), 5})); } +BOOST_AUTO_TEST_CASE(isFitter_should_use_alphabetical_order_when_fitness_is_the_same) +{ + BOOST_TEST(isFitter(Individual{Chromosome("a"), 3}, Individual{Chromosome("c"), 3})); + BOOST_TEST(!isFitter(Individual{Chromosome("c"), 3}, Individual{Chromosome("a"), 3})); + + BOOST_TEST(isFitter(Individual{Chromosome("a"), 3}, Individual{Chromosome("aa"), 3})); + BOOST_TEST(!isFitter(Individual{Chromosome("aa"), 3}, Individual{Chromosome("a"), 3})); + + BOOST_TEST(isFitter(Individual{Chromosome("T"), 3}, Individual{Chromosome("a"), 3})); + BOOST_TEST(!isFitter(Individual{Chromosome("a"), 3}, Individual{Chromosome("T"), 3})); +} + BOOST_AUTO_TEST_CASE(isFitter_should_return_false_for_identical_individuals) { BOOST_TEST(!isFitter(Individual{Chromosome("a"), 3}, Individual{Chromosome("a"), 3})); diff --git a/tools/yulPhaser/Population.cpp b/tools/yulPhaser/Population.cpp index c4b529a91..890e13b43 100644 --- a/tools/yulPhaser/Population.cpp +++ b/tools/yulPhaser/Population.cpp @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -26,6 +28,7 @@ using namespace std; using namespace solidity; using namespace solidity::langutil; +using namespace solidity::util; using namespace solidity::phaser; namespace solidity::phaser @@ -52,7 +55,11 @@ bool phaser::isFitter(Individual const& a, Individual const& b) { assert(a.fitness.has_value() && b.fitness.has_value()); - return a.fitness.value() < b.fitness.value(); + return ( + (a.fitness.value() < b.fitness.value()) || + (a.fitness.value() == b.fitness.value() && a.chromosome.length() < b.chromosome.length()) || + (a.fitness.value() == b.fitness.value() && a.chromosome.length() == b.chromosome.length() && toString(a.chromosome) < toString(b.chromosome)) + ); } Population::Population(Program _program, vector const& _chromosomes): diff --git a/tools/yulPhaser/Population.h b/tools/yulPhaser/Population.h index 0c6c69be7..43f8643e1 100644 --- a/tools/yulPhaser/Population.h +++ b/tools/yulPhaser/Population.h @@ -40,7 +40,9 @@ struct Individual friend std::ostream& operator<<(std::ostream& _stream, Individual const& _individual); }; -/// Determines which individual is better by comparing fitness values. +/// Determines which individual is better by comparing fitness values. If fitness is the same +/// takes into account all the other properties of the individual to make the comparison +/// deterministic as long as the individuals are not equal. bool isFitter(Individual const& a, Individual const& b); /**