#ifndef OPTIMIZEREVOLUTIONARY_H
#define OPTIMIZEREVOLUTIONARY_H
#include "OptimizerBase.h"

namespace mdd {
	class OptimizerEvolutionary : public OptimizerBase {
	public:
		struct Individual {
		public:
			std::vector<std::vector<double>> dna;
			double fitness = 0;
			bool operator== (const Individual& ind) {
				return (dna == ind.dna) && (fitness == ind.fitness);
			};
		};
	protected:
		static int random_num(double min, double max, double inc = 1.0)
		{
			int range = (max - min)/inc + 1;
			return min + inc*(std::rand() % range);
		}

		Individual generateIndividual();
		Individual combine(Individual par1, Individual par2);

		std::vector<Individual> _children;
		Individual _best;
		int _min_generations;
		double _max_fitness;
		size_t _grow_generation;
		size_t _converges;

		void evolve(std::vector<Individual> parents);
		void evaluate(size_t ignore_len = 0);
		std::vector<double> mutateGene(std::shared_ptr<IInput> input, std::vector<double> seed = std::vector<double>());
		

	public:
		OptimizerEvolutionary(std::shared_ptr<IModule> module,
			size_t converges = 0,
			size_t grow_generation = 20,
			double max_fitness = 0.0,
			int min_generations = -1);
		std::vector<std::vector<double>> update() override;
		Individual getBest();
		double evaluateFitness(const Individual& ind);
	};
}
#endif