/*
 * Mutation.h
 *
 *  Created on: Jul 27, 2015
 *      Author: jjpalacios
 */

#ifndef SRC_ECOPERATORS_MUTATION_H_
#define SRC_ECOPERATORS_MUTATION_H_

#include "../heading.h"
#include "../ecObjects/SharedVars.h"
#include "../ecObjects/Population.h"


namespace clbDEB {

// Mutation parameters defined in this header file
#define MUTATION_PROBABILITY "mutation-probability"
#define MUTATION_GENE_PROBABILITY "mutation-gene"





//=============================================================================
//
//	Abstract class Mutation
//
//=============================================================================
/**
 * This class provides the framework to implement mutation operators to
 * be used by evolutionary algorithms.
 *
 * Classes inheriting from this one have to implement the method "apply"
 * *
 * @author jjpalacios
 *
 */
class Mutation {
	//=========================================================================
	//		COMMON FIELDS
	//=========================================================================
public:
	/**
	 * Name of the probability parameter to get from the configuration file
	 */
	std::string P_PROB;

	/**
	 * Probability to apply the operator
	 */
	double probability;



	//=========================================================================
	//		CONSTRUCTORS / INITIALIZERS
	//=========================================================================
public:
	/**
	 * Default constructor
	 */
	explicit Mutation(ParameterDB *parameters = NULL);

	/**
	 * Loads the needed parameters: Mutation probability
	 */
	virtual void setup(ParameterDB *parameters);

	/**
	 * Destructor
	 */
	virtual ~Mutation() { }; 	// Nothing to destroy here



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Apply the mutation operator to an individual
	 *
	 * @param individual Individual to mutate
	 * @param svars Shared elements of the algorithm
	 */
	virtual void apply(Individual *individual, const SharedVars *svars) const=0;

	/**
	 * Apply the crossover operator to all pairs in the population. The
	 * offspring will replace their parents in the original population
	 *
	 * @param population Population of individuals to mate
	 * @param svars Shared elements of the algorithm
	 */
	virtual void apply(Population *population, const SharedVars *svars) const;

	/**
	 * Get the name and setup of the operator
	 *
	 * @return A string of parameter values. The first string is the name of
	 * the operator
	 */
	virtual std::vector<std::string> getName() const=0;
};





//=============================================================================
//
//	Class RandomMutation
//
//=============================================================================
/**
 * This class inherits from Mutation and implements a random mutation.
 *
 * Given a probability (prob_gene), a gene is changed to a random value
 *
 * @author jjpalacios
 *
 */
class RandomMutation : public Mutation {
	//=========================================================================
	//		FIELDS
	//=========================================================================
public:
	/**
	 * Name of the probability per gene to get from the configuration file
	 */
	std::string P_PROB_GENE;

	/**
	 * Probability per gene of applying the operator
	 */
	double prob_gene;



	//=========================================================================
	//		CONSTRUCTORS / INITIALIZERS
	//=========================================================================
public:
	/**
	 * Default constructor
	 */
	explicit RandomMutation(ParameterDB *parameters = NULL);

	/**
	 * Loads the needed parameters: Mutation per gene
	 */
	virtual void setup(ParameterDB *parameters);

	/**
	 * Destructor
	 */
	virtual ~RandomMutation() { }; 	// Nothing to destroy here



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Apply the mutation operator to an individual
	 *
	 * @param individual Individual to mutate
	 * @param svars Shared elements of the algorithm
	 */
	virtual void apply(Individual *individual, const SharedVars *svars) const;


	/**
	 * Get the name and setup of the operator
	 *
	 * @return A string of parameter values. The first string is the name of
	 * the operator
	 */
	virtual std::vector<std::string> getName() const {
		std::vector<std::string> setup;
		setup.push_back("Random");
		setup.push_back(";Probability;" + valueToString(this->probability));
		setup.push_back(";Prob. per gene;" + valueToString(this->prob_gene));
		return setup;
	}
};





//=============================================================================
//
//	Class ExtremeMutation
//
//=============================================================================
/**
 * This class inherits from Mutation and implements a mutation in which some
 * of the genes are set to one of the bounds of the interval.
 *
 * Given a probability (prob_gene), a gene is changed to a a limit value
 *
 * @author jjpalacios
 *
 */
class ExtremeMutation : public Mutation {
	//=========================================================================
	//		FIELDS
	//=========================================================================
public:
	/**
	 * Name of the probability per gene to get from the configuration file
	 */
	std::string P_PROB_GENE;

	/**
	 * Probability per gene of applying the operator
	 */
	double prob_gene;



	//=========================================================================
	//		CONSTRUCTORS / INITIALIZERS
	//=========================================================================
public:
	/**
	 * Default constructor
	 */
	explicit ExtremeMutation(ParameterDB *parameters = NULL);

	/**
	 * Loads the needed parameters: Mutation per gene
	 */
	virtual void setup(ParameterDB *parameters);

	/**
	 * Destructor
	 */
	virtual ~ExtremeMutation() { }; 	// Nothing to destroy here



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Apply the mutation operator to an individual
	 *
	 * @param individual Individual to mutate
	 * @param svars Shared elements of the algorithm
	 */
	virtual void apply(Individual *individual, const SharedVars *svars) const;


	/**
	 * Get the name and setup of the operator
	 *
	 * @return A string of parameter values. The first string is the name of
	 * the operator
	 */
	virtual std::vector<std::string> getName() const {
		std::vector<std::string> setup;
		setup.push_back("Extreme");
		setup.push_back(";Probability;" + valueToString(this->probability));
		setup.push_back(";Prob. per gene;" + valueToString(this->prob_gene));
		return setup;
	}
};


}

#endif /* SRC_ECOPERATORS_MUTATION_H_ */
