mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] AlgorithmRunner: Population autosave
This commit is contained in:
parent
04c7c56d84
commit
1b5960111d
@ -18,9 +18,11 @@
|
||||
#include <test/yulPhaser/TestHelpers.h>
|
||||
|
||||
#include <tools/yulPhaser/AlgorithmRunner.h>
|
||||
#include <tools/yulPhaser/Common.h>
|
||||
|
||||
#include <libsolutil/CommonIO.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/tools/output_test_stream.hpp>
|
||||
|
||||
@ -29,10 +31,12 @@ using namespace boost::unit_test::framework;
|
||||
using namespace boost::test_tools;
|
||||
using namespace solidity::util;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace solidity::phaser::test
|
||||
{
|
||||
|
||||
class DummyAlgorithm: public GeneticAlgorithm
|
||||
class CountingAlgorithm: public GeneticAlgorithm
|
||||
{
|
||||
public:
|
||||
using GeneticAlgorithm::GeneticAlgorithm;
|
||||
@ -45,6 +49,16 @@ public:
|
||||
size_t m_currentRound = 0;
|
||||
};
|
||||
|
||||
class RandomisingAlgorithm: public GeneticAlgorithm
|
||||
{
|
||||
public:
|
||||
using GeneticAlgorithm::GeneticAlgorithm;
|
||||
Population runNextRound(Population _population) override
|
||||
{
|
||||
return Population::makeRandom(_population.fitnessMetric(), _population.individuals().size(), 10, 20);
|
||||
}
|
||||
};
|
||||
|
||||
class AlgorithmRunnerFixture
|
||||
{
|
||||
protected:
|
||||
@ -53,6 +67,25 @@ protected:
|
||||
AlgorithmRunner::Options m_options;
|
||||
};
|
||||
|
||||
class AlgorithmRunnerAutosaveFixture: public AlgorithmRunnerFixture
|
||||
{
|
||||
public:
|
||||
static vector<string> chromosomeStrings(Population const& _population)
|
||||
{
|
||||
vector<string> lines;
|
||||
for (auto const& individual: _population.individuals())
|
||||
lines.push_back(toString(individual.chromosome));
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
protected:
|
||||
TemporaryDirectory m_tempDir;
|
||||
string const m_autosavePath = m_tempDir.memberPath("population-autosave.txt");
|
||||
Population const m_population = Population::makeRandom(m_fitnessMetric, 5, 0, 20);
|
||||
RandomisingAlgorithm m_algorithm;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Phaser)
|
||||
BOOST_AUTO_TEST_SUITE(AlgorithmRunnerTest)
|
||||
|
||||
@ -60,7 +93,8 @@ BOOST_FIXTURE_TEST_CASE(run_should_call_runNextRound_once_per_round, AlgorithmRu
|
||||
{
|
||||
m_options.maxRounds = 5;
|
||||
AlgorithmRunner runner(Population(m_fitnessMetric), m_options, m_output);
|
||||
DummyAlgorithm algorithm;
|
||||
|
||||
CountingAlgorithm algorithm;
|
||||
|
||||
BOOST_TEST(algorithm.m_currentRound == 0);
|
||||
runner.run(algorithm);
|
||||
@ -82,7 +116,7 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_the_top_chromosome, AlgorithmRunnerFixt
|
||||
m_output
|
||||
);
|
||||
|
||||
DummyAlgorithm algorithm;
|
||||
CountingAlgorithm algorithm;
|
||||
|
||||
BOOST_TEST(m_output.is_empty());
|
||||
runner.run(algorithm);
|
||||
@ -93,6 +127,67 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_the_top_chromosome, AlgorithmRunnerFixt
|
||||
BOOST_TEST(countSubstringOccurrences(m_output.str(), toString(runner.population().individuals()[0].chromosome)) == 4);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(run_should_save_initial_population_to_file_if_autosave_file_specified, AlgorithmRunnerAutosaveFixture)
|
||||
{
|
||||
m_options.maxRounds = 0;
|
||||
m_options.populationAutosaveFile = m_autosavePath;
|
||||
AlgorithmRunner runner(m_population, m_options, m_output);
|
||||
assert(!fs::exists(m_autosavePath));
|
||||
|
||||
runner.run(m_algorithm);
|
||||
assert(runner.population() == m_population);
|
||||
|
||||
BOOST_TEST(fs::is_regular_file(m_autosavePath));
|
||||
BOOST_TEST(readLinesFromFile(m_autosavePath) == chromosomeStrings(runner.population()));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(run_should_save_population_to_file_if_autosave_file_specified, AlgorithmRunnerAutosaveFixture)
|
||||
{
|
||||
m_options.maxRounds = 1;
|
||||
m_options.populationAutosaveFile = m_autosavePath;
|
||||
AlgorithmRunner runner(m_population, m_options, m_output);
|
||||
assert(!fs::exists(m_autosavePath));
|
||||
|
||||
runner.run(m_algorithm);
|
||||
assert(runner.population() != m_population);
|
||||
|
||||
BOOST_TEST(fs::is_regular_file(m_autosavePath));
|
||||
BOOST_TEST(readLinesFromFile(m_autosavePath) == chromosomeStrings(runner.population()));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(run_should_overwrite_existing_file_if_autosave_file_specified, AlgorithmRunnerAutosaveFixture)
|
||||
{
|
||||
m_options.maxRounds = 5;
|
||||
m_options.populationAutosaveFile = m_autosavePath;
|
||||
AlgorithmRunner runner(m_population, m_options, m_output);
|
||||
assert(!fs::exists(m_autosavePath));
|
||||
|
||||
vector<string> originalContent = {"Original content"};
|
||||
{
|
||||
ofstream tmpFile(m_autosavePath);
|
||||
tmpFile << originalContent[0] << endl;
|
||||
}
|
||||
assert(fs::exists(m_autosavePath));
|
||||
assert(readLinesFromFile(m_autosavePath) == originalContent);
|
||||
|
||||
runner.run(m_algorithm);
|
||||
|
||||
BOOST_TEST(fs::is_regular_file(m_autosavePath));
|
||||
BOOST_TEST(readLinesFromFile(m_autosavePath) != originalContent);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(run_should_not_save_population_to_file_if_autosave_file_not_specified, AlgorithmRunnerAutosaveFixture)
|
||||
{
|
||||
m_options.maxRounds = 5;
|
||||
m_options.populationAutosaveFile = nullopt;
|
||||
AlgorithmRunner runner(m_population, m_options, m_output);
|
||||
assert(!fs::exists(m_autosavePath));
|
||||
|
||||
runner.run(m_algorithm);
|
||||
|
||||
BOOST_TEST(!fs::exists(m_autosavePath));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
@ -17,16 +17,50 @@
|
||||
|
||||
#include <tools/yulPhaser/AlgorithmRunner.h>
|
||||
|
||||
#include <tools/yulPhaser/Exceptions.h>
|
||||
|
||||
#include <libsolutil/Assertions.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::phaser;
|
||||
|
||||
void AlgorithmRunner::run(GeneticAlgorithm& _algorithm)
|
||||
{
|
||||
populationAutosave();
|
||||
|
||||
for (size_t round = 0; !m_options.maxRounds.has_value() || round < m_options.maxRounds.value(); ++round)
|
||||
{
|
||||
m_population = _algorithm.runNextRound(m_population);
|
||||
|
||||
m_outputStream << "---------- ROUND " << round + 1 << " ----------" << endl;
|
||||
m_outputStream << m_population;
|
||||
|
||||
populationAutosave();
|
||||
}
|
||||
}
|
||||
|
||||
void AlgorithmRunner::populationAutosave() const
|
||||
{
|
||||
if (!m_options.populationAutosaveFile.has_value())
|
||||
return;
|
||||
|
||||
ofstream outputStream(m_options.populationAutosaveFile.value(), ios::out | ios::trunc);
|
||||
assertThrow(
|
||||
outputStream.is_open(),
|
||||
FileOpenError,
|
||||
"Could not open file '" + m_options.populationAutosaveFile.value() + "': " + strerror(errno)
|
||||
);
|
||||
|
||||
for (auto& individual: m_population.individuals())
|
||||
outputStream << individual.chromosome << endl;
|
||||
|
||||
assertThrow(
|
||||
!outputStream.bad(),
|
||||
FileWriteError,
|
||||
"Error while writing to file '" + m_options.populationAutosaveFile.value() + "': " + strerror(errno)
|
||||
);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
struct Options
|
||||
{
|
||||
std::optional<size_t> maxRounds = std::nullopt;
|
||||
std::optional<std::string> populationAutosaveFile = std::nullopt;
|
||||
};
|
||||
|
||||
AlgorithmRunner(
|
||||
@ -59,6 +60,8 @@ public:
|
||||
Population const& population() const { return m_population; }
|
||||
|
||||
private:
|
||||
void populationAutosave() const;
|
||||
|
||||
Population m_population;
|
||||
Options m_options;
|
||||
std::ostream& m_outputStream;
|
||||
|
@ -29,5 +29,6 @@ struct MissingFile: virtual BadInput {};
|
||||
|
||||
struct FileOpenError: virtual util::Exception {};
|
||||
struct FileReadError: virtual util::Exception {};
|
||||
struct FileWriteError: virtual util::Exception {};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user