/* 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 . */ // SPDX-License-Identifier: GPL-3.0 /** * Contains the main class that controls yul-phaser based on command-line parameters and * associated factories for building instances of phaser's components. */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace solidity::langutil { class CharStream; } namespace solidity::yul { struct CodeWeights; } namespace solidity::phaser { class FitnessMetric; class GeneticAlgorithm; class Population; class Program; class ProgramCache; enum class PhaserMode { RunAlgorithm, PrintOptimisedPrograms, PrintOptimisedASTs, }; enum class Algorithm { Random, GEWEP, Classic, }; enum class MetricChoice { CodeSize, RelativeCodeSize, }; enum class MetricAggregatorChoice { Average, Sum, Maximum, Minimum, }; std::istream& operator>>(std::istream& _inputStream, solidity::phaser::PhaserMode& _phaserMode); std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::PhaserMode _phaserMode); 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); std::istream& operator>>(std::istream& _inputStream, solidity::phaser::CrossoverChoice& _crossover); std::ostream& operator<<(std::ostream& _outputStream, solidity::phaser::CrossoverChoice _crossover); /** * Builds and validates instances of @a GeneticAlgorithm and its derived classes. */ class GeneticAlgorithmFactory { public: struct Options { Algorithm algorithm; size_t minChromosomeLength; size_t maxChromosomeLength; CrossoverChoice crossover; double uniformCrossoverSwapChance; std::optional randomElitePoolSize; double gewepMutationPoolSize; double gewepCrossoverPoolSize; double gewepRandomisationChance; double gewepDeletionVsAdditionChance; std::optional gewepGenesToRandomise; std::optional gewepGenesToAddOrDelete; double classicElitePoolSize; double classicCrossoverChance; double classicMutationChance; double classicDeletionChance; double classicAdditionChance; static Options fromCommandLine(boost::program_options::variables_map const& _arguments); }; static std::unique_ptr build( Options const& _options, size_t _populationSize ); }; /** * Builds and validates instances of @a CodeWeights. */ class CodeWeightFactory { public: static yul::CodeWeights buildFromCommandLine( boost::program_options::variables_map const& _arguments ); }; /** * Builds and validates instances of @a FitnessMetric and its derived classes. */ class FitnessMetricFactory { public: struct Options { MetricChoice metric; MetricAggregatorChoice metricAggregator; size_t relativeMetricScale; size_t chromosomeRepetitions; static Options fromCommandLine(boost::program_options::variables_map const& _arguments); }; static std::unique_ptr build( Options const& _options, std::vector _programs, std::vector> _programCaches, yul::CodeWeights const& _weights ); }; /** * Builds and validates instances of @a Population. */ class PopulationFactory { public: struct Options { size_t minChromosomeLength; size_t maxChromosomeLength; std::vector population; std::vector randomPopulation; std::vector populationFromFile; static Options fromCommandLine(boost::program_options::variables_map const& _arguments); }; static Population build( Options const& _options, std::shared_ptr _fitnessMetric ); static Population buildFromStrings( std::vector const& _geneSequences, std::shared_ptr _fitnessMetric ); static Population buildRandom( size_t _populationSize, size_t _minChromosomeLength, size_t _maxChromosomeLength, std::shared_ptr _fitnessMetric ); static Population buildFromFile( std::string const& _filePath, std::shared_ptr _fitnessMetric ); }; /** * 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> build( Options const& _options, std::vector _programs ); }; /** * Builds and validates instances of @a Program. */ class ProgramFactory { public: struct Options { std::vector inputFiles; std::string prefix; static Options fromCommandLine(boost::program_options::variables_map const& _arguments); }; static std::vector build(Options const& _options); private: static langutil::CharStream loadSource(boost::filesystem::path const& _sourcePath); }; /** * 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), * creating instances of main components using factories and feeding them into @a AlgorithmRunner. */ class Phaser { public: static void main(int argc, char** argv); private: struct CommandLineDescription { boost::program_options::options_description keywordDescription; boost::program_options::positional_options_description positionalDescription; }; static CommandLineDescription buildCommandLineDescription(); static std::optional parseCommandLine(int _argc, char** _argv); static void initialiseRNG(boost::program_options::variables_map const& _arguments); static AlgorithmRunner::Options buildAlgorithmRunnerOptions(boost::program_options::variables_map const& _arguments); static void runPhaser(boost::program_options::variables_map const& _arguments); static void runAlgorithm( boost::program_options::variables_map const& _arguments, Population _population, std::vector> _programCaches ); static void printOptimisedProgramsOrASTs( boost::program_options::variables_map const& _arguments, Population const& _population, std::vector _programs, PhaserMode phaserMode ); }; }