//===========================================================================
/*!
 * 
 *
 * \brief       Implements the most recent version of the elitist CMA-ES.
 * 
 * The algorithm is based on
 * 
 * C. Igel, T. Suttorp, and N. Hansen. A Computational Efficient
 * Covariance Matrix Update and a (1+1)-CMA for Evolution
 * Strategies. In Proceedings of the Genetic and Evolutionary
 * Computation Conference (GECCO 2006), pp. 453-460, ACM Press, 2006
 * 
 * D. V. Arnold and N. Hansen: Active covariance matrix adaptation for
 * the (1+1)-CMA-ES. In Proceedings of the Genetic and Evolutionary
 * Computation Conference (GECCO 2010): pp 385-392, ACM Press 2010
 * 
 *
 * \author      O. Krause T.Voss
 * \date        2014
 *
 *
 * \par Copyright 1995-2017 Shark Development Team
 * 
 * <BR><HR>
 * This file is part of Shark.
 * <http://shark-ml.org/>
 * 
 * Shark is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published 
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Shark 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Shark.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
//===========================================================================


#ifndef SHARK_ALGORITHMS_DIRECTSEARCH_ELITIST_CMA_H
#define SHARK_ALGORITHMS_DIRECTSEARCH_ELITIST_CMA_H

#include <shark/Core/DLLSupport.h>
#include <shark/Algorithms/AbstractSingleObjectiveOptimizer.h>
#include <shark/Algorithms/DirectSearch/CMA/CMAIndividual.h>
#include <shark/Algorithms/DirectSearch/Operators/Evaluation/PenalizingEvaluator.h>

namespace shark {


/// \brief Implements the elitist CMA-ES.
/// 
/// The algorithm is based on
/// 
/// C. Igel, T. Suttorp, and N. Hansen. A Computational Efficient
/// Covariance Matrix Update and a (1+1)-CMA for Evolution
/// Strategies. In Proceedings of the Genetic and Evolutionary
/// Computation Conference (GECCO 2006), pp. 453-460, ACM Press, 2006
/// 
/// D. V. Arnold and N. Hansen: Active covariance matrix adaptation for
/// the (1+1)-CMA-ES. In Proceedings of the Genetic and Evolutionary
/// \ingroup singledirect
class ElitistCMA : public AbstractSingleObjectiveOptimizer<RealVector >{	    
public:

	SHARK_EXPORT_SYMBOL ElitistCMA(random::rng_type& rng = random::globalRng);

	/// \brief From INameable: return the class name.
	std::string name() const
	{ return "ElitistCMA"; }

	SHARK_EXPORT_SYMBOL void read( InArchive & archive );

	SHARK_EXPORT_SYMBOL void write( OutArchive & archive ) const;

	using AbstractSingleObjectiveOptimizer<RealVector >::init;
	
	/// \brief Initializes the algorithm for the supplied objective function.
	SHARK_EXPORT_SYMBOL void init( ObjectiveFunctionType const& function, SearchPointType const& p);

	///\brief Executes one iteration of the algorithm.
	SHARK_EXPORT_SYMBOL void step(ObjectiveFunctionType const& function);
	
	/// \brief Returns true when the active update is used (default true).
	bool activeUpdate()const{
		return m_activeUpdate;
	}
	/// \brief Setter function to enable active update. Returns true when the active update is used (default true).
	bool& activeUpdate(){
		return m_activeUpdate;
	}
	
	/// \brief Returns the penalty factor for an individual that is outside the feasible area.
	///
	/// The value is multiplied with the distance to the nearest feasible point.
	double constrainedPenaltyFactor()const{
		return m_evaluator.m_penaltyFactor;
	}
	
	/// \brief Returns a reference to the penalty factor for an individual that is outside the feasible area.
	///
	/// The value is multiplied with the distance to the nearest feasible point.
	double& constrainedPenaltyFactor(){
		return m_evaluator.m_penaltyFactor;
	}
	
	/// \brief  Returns the current step length
	double sigma()const{
		return m_individual.chromosome().m_stepSize;
	}
	
	/// \brief  Returns the current step length
	double& sigma(){
		return m_individual.chromosome().m_stepSize;
	}

private:
	CMAIndividual<double> m_individual;///< Individual holding strategy parameter. usd as parent and offspring
	PenalizingEvaluator m_evaluator;///< evaluates the fitness of the individual and handles constraints
	std::vector<double> m_ancestralFitness; ///< stores the last k fitness values (by default 5).
	bool m_activeUpdate;///< Should bad individuals be actively purged from the strategy?

	random::rng_type* mpe_rng;///< the internal random number generator
};
}

#endif
