/*
	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 implementation of a class that manages the execution of a genetic algorithm.
 */
#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include 
namespace solidity::phaser
{
/**
 * Manages a population and executes a genetic algorithm on it. It's independent of the
 * implementation details of a specific algorithm which is pluggable via @a GeneticAlgorithm class.
 *
 * The class is also responsible for providing text feedback on the execution of the algorithm
 * to the associated output stream.
 */
class AlgorithmRunner
{
public:
	struct Options
	{
		std::optional maxRounds = std::nullopt;
		std::optional populationAutosaveFile = std::nullopt;
		bool randomiseDuplicates = false;
		std::optional minChromosomeLength = std::nullopt;
		std::optional maxChromosomeLength = std::nullopt;
		bool showInitialPopulation = false;
		bool showOnlyTopChromosome = false;
		bool showRoundInfo = true;
		bool showCacheStats = false;
	};
	AlgorithmRunner(
		Population _initialPopulation,
		std::vector> _programCaches,
		Options _options,
		std::ostream& _outputStream
	):
		m_population(std::move(_initialPopulation)),
		m_programCaches(std::move(_programCaches)),
		m_options(std::move(_options)),
		m_outputStream(_outputStream) {}
	void run(GeneticAlgorithm& _algorithm);
	Options const& options() const { return m_options; }
	Population const& population() const { return m_population; }
private:
	void printRoundSummary(
		size_t _round,
		clock_t _roundTimeStart,
		clock_t _totalTimeStart
	) const;
	void printInitialPopulation() const;
	void printCacheStats() const;
	void populationAutosave() const;
	void randomiseDuplicates();
	void cacheClear();
	void cacheStartRound(size_t _roundNumber);
	static Population randomiseDuplicates(
		Population _population,
		size_t _minChromosomeLength,
		size_t _maxChromosomeLength
	);
	Population m_population;
	std::vector> m_programCaches;
	Options m_options;
	std::ostream& m_outputStream;
};
}