[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.
This commit is contained in:
Kamil Śliwak 2020-02-11 22:25:17 +01:00
parent 40a6669538
commit ecb30c670f
3 changed files with 23 additions and 2 deletions

View File

@ -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}));

View File

@ -19,6 +19,8 @@
#include <tools/yulPhaser/Program.h>
#include <libsolutil/CommonIO.h>
#include <algorithm>
#include <cassert>
#include <numeric>
@ -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<Chromosome> const& _chromosomes):

View File

@ -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);
/**