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

#ifndef SRC_ECOPERATORS_CROSSOVER_H_
#define SRC_ECOPERATORS_CROSSOVER_H_

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


namespace clbDEB {

// Crossover parameters defined in this header file
#define CROSSOVER_PROBABILITY "crossover-probability"
#define CROSSOVER_ALPHA "crossover-alpha"





//=============================================================================
//
//	Abstract class Crossover
//
//=============================================================================
/**
 * This class provides the framework to implement crossover operators to
 * be used by evolutionary algorithms.
 *
 * Classes inheriting from this one have to implement the method "apply"
 *
 * The crossover operator will generate 2 offspring that will replace their
 * parents automatically
 *
 * @author jjpalacios
 *
 */
class Crossover {
	//=========================================================================
	//		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 Crossover(ParameterDB *parameters = NULL);

	/**
	 * Loads the needed parameters.
	 * Loads the crossover probability
	 */
	virtual void setup(ParameterDB *parameters);

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



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Apply the crossover operator to a pair of individuals and produces two
	 * offspring. The offspring will automatically replace their parents
	 *
	 * @param ind1 First parent for the mating
	 * @param ind2 Second parent for the mating
	 * @param svars Shared elements of the algorithm
	 */
	virtual void apply(Individual *ind1,
			Individual *ind2, 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 BlxCrossover
//
//=============================================================================
/**
 * This class is needed for ECJ to work properly.
 * It implements the BLX crossover operator both for real and integer
 * array values.
 *
 * Given 2 parents, A and B, the BLX-alpha crossover generates two
 * offspring such that each gene i in the offspring is taken as a
 * random value in the interval [min(i) - alpha x IR, max(i) + alpha x IR]
 * where min(i) = min{A(i), B(i)}, max(i) = max{A(i), B(i)}
 * and IR = max(i) - min(i).
 *
 * In the case in which the genes have an interval of feasible values [MINi, MAXi],
 * we must take into account that the operator can generate values
 * out of the bounds. There are mainly two ways to fix this:
 *
 * 1. Change the intervla in which we generate the random values to:
 * 		[max{min(i) - alpha x IR, MINi}, min{max(i) + alpha x IR, MAXi}]
 *
 * 2. Generate the random value and if its larger MAXi (or smaller than MINi),
 * change its value to MAXi (MINi respectively)
 *
 * Here we take the second approach because the first one makes more
 * difficult to have values at the extremes of the interval of feasible values
 *
 * @author jjpalacios
 *
 */
class BlxCrossover : public Crossover {
	//=========================================================================
	//		FIELDS
	//=========================================================================
public:
	/**
	 * Name of the alpha parameter to get from the configuration file
	 */
	std::string P_ALPHA;

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



	//=========================================================================
	//		CONSTRUCTORS / INITIALIZERS
	//=========================================================================
public:
	/**
	 * Constructor using the parameters file
	 */
	explicit BlxCrossover(ParameterDB *parameters = NULL);

	/**
	 * Loads extra parameters.
	 * Loads the alpha value
	 */
	virtual void setup(ParameterDB *parameters);

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



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Apply the crossover operator to a pair of individuals and produces two
	 * offspring. The offspring will automatically replace their parents
	 *
	 * @param ind1 First parent for the mating
	 * @param ind2 Second parent for the mating
	 * @param svars Shared elements of the algorithm
	 * @return The two offspring produced
	 */
	virtual void apply(Individual *ind1,
			Individual *ind2, 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("BLX-alpha");
		setup.push_back(";Probability;" + valueToString(this->probability));
		setup.push_back(";Alpha;" + valueToString(this->alpha));
		return setup;
	}

protected:
	/**
	 * Crossover operator depending on the type of individual we are
	 * receiving
	 *
	 * @param ind1 First parent for the mating
	 * @param ind2 Second parent for the mating
	 * @param svars Shared elements of the algorithm
	 * @return The two offspring produced
	 */
	virtual void applyDouble(DoubleIndividual *ind1, DoubleIndividual *ind2,
			const SharedVars *svars) const;

	virtual void applyInteger(IntegerIndividual *ind1, IntegerIndividual *ind2,
			const SharedVars *svars) const;

};

}

#endif /* SRC_ECOPERATORS_CROSSOVER_H_ */
