2020-02-21 14:55:02 +00:00
|
|
|
/*
|
|
|
|
This file is part of solidity.
|
|
|
|
|
|
|
|
solidity is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
solidity is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2020-07-17 14:54:12 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0
|
2020-02-21 14:55:02 +00:00
|
|
|
/**
|
2020-02-21 16:18:13 +00:00
|
|
|
* Contains the main class that controls yul-phaser based on command-line parameters and
|
|
|
|
* associated factories for building instances of phaser's components.
|
2020-02-21 14:55:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2020-02-21 19:01:00 +00:00
|
|
|
#include <tools/yulPhaser/AlgorithmRunner.h>
|
2020-03-11 02:39:29 +00:00
|
|
|
#include <tools/yulPhaser/GeneticAlgorithms.h>
|
2020-02-21 19:01:00 +00:00
|
|
|
|
2021-07-13 07:12:04 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
2020-02-21 14:55:02 +00:00
|
|
|
#include <boost/program_options.hpp>
|
|
|
|
|
2021-05-17 09:48:48 +00:00
|
|
|
#include <cstddef>
|
2020-02-21 14:55:02 +00:00
|
|
|
#include <istream>
|
2020-02-21 16:18:13 +00:00
|
|
|
#include <memory>
|
2020-02-28 02:58:26 +00:00
|
|
|
#include <optional>
|
2020-02-21 14:55:02 +00:00
|
|
|
#include <ostream>
|
|
|
|
#include <string>
|
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
namespace solidity::langutil
|
|
|
|
{
|
|
|
|
|
|
|
|
class CharStream;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-02-29 20:57:14 +00:00
|
|
|
namespace solidity::yul
|
|
|
|
{
|
|
|
|
|
|
|
|
struct CodeWeights;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-02-21 14:55:02 +00:00
|
|
|
namespace solidity::phaser
|
|
|
|
{
|
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
class FitnessMetric;
|
|
|
|
class GeneticAlgorithm;
|
|
|
|
class Population;
|
|
|
|
class Program;
|
2020-02-28 21:29:08 +00:00
|
|
|
class ProgramCache;
|
2020-02-21 16:18:13 +00:00
|
|
|
|
2020-02-28 23:56:47 +00:00
|
|
|
enum class PhaserMode
|
|
|
|
{
|
|
|
|
RunAlgorithm,
|
2020-02-28 23:57:24 +00:00
|
|
|
PrintOptimisedPrograms,
|
|
|
|
PrintOptimisedASTs,
|
2020-02-28 23:56:47 +00:00
|
|
|
};
|
|
|
|
|
2020-02-21 14:55:02 +00:00
|
|
|
enum class Algorithm
|
|
|
|
{
|
|
|
|
Random,
|
|
|
|
GEWEP,
|
2020-03-11 01:16:00 +00:00
|
|
|
Classic,
|
2020-02-21 14:55:02 +00:00
|
|
|
};
|
|
|
|
|
2020-02-25 17:56:07 +00:00
|
|
|
enum class MetricChoice
|
|
|
|
{
|
|
|
|
CodeSize,
|
|
|
|
RelativeCodeSize,
|
|
|
|
};
|
|
|
|
|
2020-02-26 15:32:49 +00:00
|
|
|
enum class MetricAggregatorChoice
|
|
|
|
{
|
|
|
|
Average,
|
|
|
|
Sum,
|
|
|
|
Maximum,
|
|
|
|
Minimum,
|
|
|
|
};
|
|
|
|
|
2020-02-28 23:56:47 +00:00
|
|
|
std::istream& operator>>(std::istream& _inputStream, solidity::phaser::PhaserMode& _phaserMode);
|
|
|
|
std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::PhaserMode _phaserMode);
|
2020-02-21 14:55:02 +00:00
|
|
|
std::istream& operator>>(std::istream& _inputStream, solidity::phaser::Algorithm& _algorithm);
|
|
|
|
std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::Algorithm _algorithm);
|
2020-02-25 17:56:07 +00:00
|
|
|
std::istream& operator>>(std::istream& _inputStream, solidity::phaser::MetricChoice& _metric);
|
|
|
|
std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::MetricChoice _metric);
|
2020-02-26 15:32:49 +00:00
|
|
|
std::istream& operator>>(std::istream& _inputStream, solidity::phaser::MetricAggregatorChoice& _aggregator);
|
|
|
|
std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::MetricAggregatorChoice _aggregator);
|
2020-03-11 02:39:29 +00:00
|
|
|
std::istream& operator>>(std::istream& _inputStream, solidity::phaser::CrossoverChoice& _crossover);
|
|
|
|
std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::CrossoverChoice _crossover);
|
2020-02-21 14:55:02 +00:00
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a GeneticAlgorithm and its derived classes.
|
|
|
|
*/
|
|
|
|
class GeneticAlgorithmFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Options
|
|
|
|
{
|
|
|
|
Algorithm algorithm;
|
2020-02-26 21:35:54 +00:00
|
|
|
size_t minChromosomeLength;
|
|
|
|
size_t maxChromosomeLength;
|
2020-03-11 02:39:29 +00:00
|
|
|
CrossoverChoice crossover;
|
|
|
|
double uniformCrossoverSwapChance;
|
|
|
|
|
2020-02-26 21:53:56 +00:00
|
|
|
std::optional<double> randomElitePoolSize;
|
2020-03-11 02:39:29 +00:00
|
|
|
|
2020-02-26 21:53:56 +00:00
|
|
|
double gewepMutationPoolSize;
|
|
|
|
double gewepCrossoverPoolSize;
|
|
|
|
double gewepRandomisationChance;
|
|
|
|
double gewepDeletionVsAdditionChance;
|
|
|
|
std::optional<double> gewepGenesToRandomise;
|
|
|
|
std::optional<double> gewepGenesToAddOrDelete;
|
2020-03-11 02:39:29 +00:00
|
|
|
|
2020-03-11 01:16:00 +00:00
|
|
|
double classicElitePoolSize;
|
|
|
|
double classicCrossoverChance;
|
|
|
|
double classicMutationChance;
|
|
|
|
double classicDeletionChance;
|
|
|
|
double classicAdditionChance;
|
2020-02-21 16:18:13 +00:00
|
|
|
|
|
|
|
static Options fromCommandLine(boost::program_options::variables_map const& _arguments);
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::unique_ptr<GeneticAlgorithm> build(
|
|
|
|
Options const& _options,
|
2020-02-26 21:35:54 +00:00
|
|
|
size_t _populationSize
|
2020-02-21 16:18:13 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-02-29 20:57:14 +00:00
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a CodeWeights.
|
|
|
|
*/
|
|
|
|
class CodeWeightFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static yul::CodeWeights buildFromCommandLine(
|
|
|
|
boost::program_options::variables_map const& _arguments
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a FitnessMetric and its derived classes.
|
|
|
|
*/
|
|
|
|
class FitnessMetricFactory
|
|
|
|
{
|
|
|
|
public:
|
2020-03-01 13:34:23 +00:00
|
|
|
struct Options
|
|
|
|
{
|
2020-02-25 17:56:07 +00:00
|
|
|
MetricChoice metric;
|
2020-02-26 15:32:49 +00:00
|
|
|
MetricAggregatorChoice metricAggregator;
|
2020-02-25 18:33:54 +00:00
|
|
|
size_t relativeMetricScale;
|
2020-03-01 13:34:23 +00:00
|
|
|
size_t chromosomeRepetitions;
|
|
|
|
|
|
|
|
static Options fromCommandLine(boost::program_options::variables_map const& _arguments);
|
|
|
|
};
|
2020-02-21 16:18:13 +00:00
|
|
|
|
|
|
|
static std::unique_ptr<FitnessMetric> build(
|
2020-03-01 13:34:23 +00:00
|
|
|
Options const& _options,
|
2020-02-26 21:00:18 +00:00
|
|
|
std::vector<Program> _programs,
|
2020-02-29 20:57:14 +00:00
|
|
|
std::vector<std::shared_ptr<ProgramCache>> _programCaches,
|
|
|
|
yul::CodeWeights const& _weights
|
2020-02-21 16:18:13 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a Population.
|
|
|
|
*/
|
|
|
|
class PopulationFactory
|
|
|
|
{
|
|
|
|
public:
|
2020-02-21 23:00:29 +00:00
|
|
|
struct Options
|
|
|
|
{
|
2020-02-26 21:35:54 +00:00
|
|
|
size_t minChromosomeLength;
|
|
|
|
size_t maxChromosomeLength;
|
2020-02-21 23:01:06 +00:00
|
|
|
std::vector<std::string> population;
|
2020-02-21 23:00:29 +00:00
|
|
|
std::vector<size_t> randomPopulation;
|
2020-02-21 23:49:06 +00:00
|
|
|
std::vector<std::string> populationFromFile;
|
2020-02-21 23:00:29 +00:00
|
|
|
|
|
|
|
static Options fromCommandLine(boost::program_options::variables_map const& _arguments);
|
|
|
|
};
|
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
static Population build(
|
2020-02-21 23:00:29 +00:00
|
|
|
Options const& _options,
|
|
|
|
std::shared_ptr<FitnessMetric> _fitnessMetric
|
|
|
|
);
|
2020-02-21 23:01:06 +00:00
|
|
|
static Population buildFromStrings(
|
|
|
|
std::vector<std::string> const& _geneSequences,
|
|
|
|
std::shared_ptr<FitnessMetric> _fitnessMetric
|
|
|
|
);
|
2020-02-21 23:00:29 +00:00
|
|
|
static Population buildRandom(
|
|
|
|
size_t _populationSize,
|
2020-02-26 21:35:54 +00:00
|
|
|
size_t _minChromosomeLength,
|
|
|
|
size_t _maxChromosomeLength,
|
2020-02-21 16:18:13 +00:00
|
|
|
std::shared_ptr<FitnessMetric> _fitnessMetric
|
|
|
|
);
|
2020-02-21 23:49:06 +00:00
|
|
|
static Population buildFromFile(
|
|
|
|
std::string const& _filePath,
|
|
|
|
std::shared_ptr<FitnessMetric> _fitnessMetric
|
|
|
|
);
|
2020-02-21 16:18:13 +00:00
|
|
|
};
|
|
|
|
|
2020-02-28 21:29:08 +00:00
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a ProgramCache.
|
|
|
|
*/
|
|
|
|
class ProgramCacheFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Options
|
|
|
|
{
|
|
|
|
bool programCacheEnabled;
|
|
|
|
|
|
|
|
static Options fromCommandLine(boost::program_options::variables_map const& _arguments);
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::vector<std::shared_ptr<ProgramCache>> build(
|
|
|
|
Options const& _options,
|
|
|
|
std::vector<Program> _programs
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2020-02-21 16:18:13 +00:00
|
|
|
/**
|
|
|
|
* Builds and validates instances of @a Program.
|
|
|
|
*/
|
|
|
|
class ProgramFactory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Options
|
|
|
|
{
|
2020-02-25 19:31:51 +00:00
|
|
|
std::vector<std::string> inputFiles;
|
2020-03-20 16:44:34 +00:00
|
|
|
std::string prefix;
|
2020-02-21 16:18:13 +00:00
|
|
|
|
|
|
|
static Options fromCommandLine(boost::program_options::variables_map const& _arguments);
|
|
|
|
};
|
|
|
|
|
2020-02-25 19:31:51 +00:00
|
|
|
static std::vector<Program> build(Options const& _options);
|
2020-02-21 16:18:13 +00:00
|
|
|
|
|
|
|
private:
|
2021-07-13 07:12:04 +00:00
|
|
|
static langutil::CharStream loadSource(boost::filesystem::path const& _sourcePath);
|
2020-02-21 16:18:13 +00:00
|
|
|
};
|
|
|
|
|
2020-02-21 14:55:02 +00:00
|
|
|
/**
|
|
|
|
* Main class that controls yul-phaser based on command-line parameters. The class is responsible
|
|
|
|
* for command-line parsing, initialisation of global objects (like the random number generator),
|
2020-02-21 16:18:13 +00:00
|
|
|
* creating instances of main components using factories and feeding them into @a AlgorithmRunner.
|
2020-02-21 14:55:02 +00:00
|
|
|
*/
|
|
|
|
class Phaser
|
|
|
|
{
|
|
|
|
public:
|
2020-02-28 02:58:26 +00:00
|
|
|
static void main(int argc, char** argv);
|
2020-02-21 14:55:02 +00:00
|
|
|
|
|
|
|
private:
|
2020-02-21 18:23:33 +00:00
|
|
|
struct CommandLineDescription
|
|
|
|
{
|
|
|
|
boost::program_options::options_description keywordDescription;
|
|
|
|
boost::program_options::positional_options_description positionalDescription;
|
|
|
|
};
|
|
|
|
|
|
|
|
static CommandLineDescription buildCommandLineDescription();
|
2020-02-28 02:58:26 +00:00
|
|
|
static std::optional<boost::program_options::variables_map> parseCommandLine(int _argc, char** _argv);
|
2020-02-21 14:55:02 +00:00
|
|
|
static void initialiseRNG(boost::program_options::variables_map const& _arguments);
|
2020-02-21 19:01:00 +00:00
|
|
|
static AlgorithmRunner::Options buildAlgorithmRunnerOptions(boost::program_options::variables_map const& _arguments);
|
2020-02-21 14:55:02 +00:00
|
|
|
|
2020-02-28 23:56:47 +00:00
|
|
|
static void runPhaser(boost::program_options::variables_map const& _arguments);
|
|
|
|
static void runAlgorithm(
|
|
|
|
boost::program_options::variables_map const& _arguments,
|
|
|
|
Population _population,
|
|
|
|
std::vector<std::shared_ptr<ProgramCache>> _programCaches
|
|
|
|
);
|
2020-02-28 23:57:24 +00:00
|
|
|
static void printOptimisedProgramsOrASTs(
|
|
|
|
boost::program_options::variables_map const& _arguments,
|
|
|
|
Population const& _population,
|
|
|
|
std::vector<Program> _programs,
|
|
|
|
PhaserMode phaserMode
|
|
|
|
);
|
2020-02-21 14:55:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|