/** 
* @file GPLaplaceOptimizationProblem.h
* @author Erik Rodner
* @date 12/09/2009

*/
#ifndef _NICE_OBJREC_GPREGRESSIONOPTIMIZATIONPROBLEMINCLUDE
#define _NICE_OBJREC_GPREGRESSIONOPTIMIZATIONPROBLEMINCLUDE

#include "core/vector/VVector.h"
#include "vislearning/math/kernels/ParameterizedKernel.h"
#include "core/optimization/OptimizationProblemFirst.h"

#include "vislearning/math/kernels/KernelData.h"

#include "LaplaceApproximation.h"
#include "LikelihoodFunction.h"

namespace OBJREC {
  
/** @class GPLaplaceOptimizationProblem
 * Hyperparameter Optimization Problem for GP with Laplace Approximation
 *
 * @author Erik Rodner
 */
class GPLaplaceOptimizationProblem : public NICE::OptimizationProblemFirst
{

    protected:
		KernelData *kernelData;
		
		NICE::VVector y;

		double bestAvgLooError;
		NICE::Vector bestLooParameters;
		
		ParameterizedKernel *kernel;

		bool verbose;

		const LikelihoodFunction *likelihoodFunction;
		
		std::vector<LaplaceApproximation *> laplaceApproximation;

    public:
  
  
  		/** initialize the optimization problem of laplace approximation integrated in
		 *  GP
		 *  @param kernelData object containing kernel matrix and other stuff
		 *  @param y labels which have to -1 or 1
		 *  @param kernel a parameterized kernel which provides derivations
		 *  @param likelihoodFunction the type of the likelihood p(y_i|f_i), e.g. cumulative gaussian
		 *  @param laplaceApproximation object containing cached matrices of the laplaceApproximation
		 *  @param verbose print some status messages for debugging and boring work days
		 **/
     	GPLaplaceOptimizationProblem ( KernelData *kernelData, const NICE::Vector & y, 
			ParameterizedKernel *kernel, const LikelihoodFunction *likelihoodFunction,
			LaplaceApproximation *laplaceApproximation,
			bool verbose );

		/** initialize the multi-task optimization problem of laplace approximation 
		 * integrated in GP
		 *  @param kernelData object containing kernel matrix and other stuff
		 *  @param y vector of labels which have to -1 or 1
		 *  @param kernel a parameterized kernel which provides derivations
		 *  @param likelihoodFunction the type of the likelihood p(y_i|f_i), e.g. cumulative gaussian
		 *  @param laplaceApproximation object containing cached matrices of the laplaceApproximation
		 *  @param verbose print some status messages for debugging and boring work days
		 **/
     	GPLaplaceOptimizationProblem ( KernelData *kernelData, const NICE::VVector & y, 
			ParameterizedKernel *kernel, const LikelihoodFunction *likelihoodFunction,
			const std::vector<LaplaceApproximation *> & laplaceApproximation,
			bool verbose );

		/** R.I.P. */
		~GPLaplaceOptimizationProblem();

		/** compute the negative log likelihood of the laplace approximation integrated GP */
		double computeObjective();

		/** compute the gradient of the negative log likelihood of the laplace approximation */
		void computeGradient( NICE::Vector& newGradient );

		/** set hyperparameters of the current kernel */
		void setParameters ( const NICE::Vector & newParameters ) { parameters() = newParameters; };

		/** use loo parameters */
		void useLooParameters ();
		
		/** update cached stuff like cholesky factorization (KernelData.h) */
		void update();
};

}

#endif