/*
 * Replacement.h
 *
 *  Created on: Jul 28, 2015
 *      Author: jjpalacios
 */

#ifndef SRC_ECOPERATORS_REPLACEMENT_H_
#define SRC_ECOPERATORS_REPLACEMENT_H_

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


namespace clbDEB {

// Replacement parameters defined in this header file
#define REPLACE_ELITE "elitism-k"
#define REPLACE_NICHE_CAPACITY "niche-capacity"	// Niche capacity
#define REPLACE_NICHE_RADIUS "niche-radius"	// Niche radius



//=============================================================================
//
//	Abstract class Raplecement
//
//=============================================================================
/**
 * This class provides the framework to implement replacement strategies
 *
 * Classes inheriting from this one have to implement the method "apply"
 *
 * It will receive two populations and both will be combined into a simple one.
 * The newest population serves as a container for the resulting one,
 * while the oldest population will disappear
 *
 * @author jjpalacios
 *
 */
class Replacement {
	//=========================================================================
	//		CONSTRUCTORS / INITIALIZERS
	//=========================================================================
public:
	/**
	 * Default constructor
	 */
	explicit Replacement(ParameterDB *parameters = NULL);

	/**
	 * Loads the needed parameters: No parameters needed by default
	 */
	virtual void setup(ParameterDB *parameters) { }

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



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Merge both populations into one. The resulting population will be kept
	 * in the newPopulation pointer, while the oldPopulation will be removed
	 *
	 * @param oldPopulation Original population. It will disappear
	 * @param newPopulation New generated population to replace the previous
	 * one
	 */
	virtual void apply(Population *oldPopulation, Population *newPopulation,
			const SharedVars *svars) const=0;

	/**
	 * 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 ElitistReplacement
//
//=============================================================================
/**
 * This class implements the classical elitist replacement.
 *
 * It will require an additional parameter, which is the number of elite
 * individuals
 *
 * @author jjpalacios
 *
 */
class ElitistReplacement : public Replacement {
public:
	/**
	 * Name of the parameter for the size of the tournament
	 */
	std::string P_ELITE;

	/**
	 * Number of elite individuals
	 */
	int elite;



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

	/**
	 * Loads the needed parameters: Number of elite individuals
	 */
	virtual void setup(ParameterDB *parameters);

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



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Merge both populations into one. The resulting population will be kept
	 * in the newPopulation pointer, while the oldPopulation will be removed
	 *
	 * @param oldPopulation Original population. It will disappear
	 * @param newPopulation New generated population to replace the previous.
	 * one
	 */
	virtual void apply(Population *oldPopulation, Population *newPopulation,
			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("Elitist");
		setup.push_back(";Elite;" + valueToString(this->elite));
		return setup;
	}
};





//=============================================================================
//
//	Class ClearingReplacement
//
//=============================================================================
/**
 * This class implements a clearing based replacement.
 *
 * It mixes the two populations into one and then apply the clearing. Finally,
 * it takes the N individuals with the best fitness
 *
 * @author jjpalacios
 *
 */
class ClearingReplacement : public Replacement {
public:
	/**
	 * Name of the parameter for the size of the tournament
	 */
	std::string P_CAPACITY;
	std::string P_RADIUS;

	/**
	 * Niche parameters
	 */
	double nicheRadius;
	int nicheCapacity;



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

	/**
	 * Loads the needed parameters: Radius and capacity
	 */
	virtual void setup(ParameterDB *parameters);

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



	//=========================================================================
	//		METHODS
	//=========================================================================
public:
	/**
	 * Merge both populations into one. The resulting population will be kept
	 * in the newPopulation pointer, while the oldPopulation will be removed
	 *
	 * @param oldPopulation Original population. It will disappear
	 * @param newPopulation New generated population to replace the previous.
	 * one
	 */
	virtual void apply(Population *oldPopulation, Population *newPopulation,
			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("Clearing Replacement");
		setup.push_back(";Radius;" + valueToString(this->nicheRadius));
		setup.push_back(";Capacity;" + valueToString(this->nicheCapacity));
		return setup;
	}
};

}



#endif /* SRC_ECOPERATORS_REPLACEMENT_H_ */
