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

*/
#ifndef _NICE_OBJREC_REGGAUSSIANPROCESSINCLUDE
#define _NICE_OBJREC_REGGAUSSIANPROCESSINCLUDE

#include "core/basics/Config.h"
#include "vislearning/math/kernels/KernelData.h"
#include "vislearning/math/kernels/TraceApproximation.h"
#include "vislearning/math/kernels/ParameterizedKernel.h"

#include "vislearning/regression/regressionbase/RegressionAlgorithmKernel.h"
#include "vislearning/regression/regressionbase/TeachWithInverseKernelMatrix.h"

#include "vislearning/regression/gpregression/modelselcrit/genericGPModelSelection.h"
#include "vislearning/regression/regressionbase/RegressionAlgorithmKernel.h"

namespace OBJREC {
  
/** @class RegGaussianProcess
 * Regression using Gaussian Processes 
 *
 * @author Erik Rodner
 */
class RegGaussianProcess : public RegressionAlgorithmKernel
{

    protected:
		enum {
			OPTIMIZATION_METHOD_RASMUSSEN = 0,
			OPTIMIZATION_METHOD_TRUSTREGION
		};

		NICE::Vector kInvY;
		bool verbose;

		bool optimizeParameters;
		int optimizationMethod;
		int maxIterations;

		TraceApproximation *traceApproximation;
		GPMSCLooLikelihoodRegression *modelselcrit;

		bool useLooParameters;

    public:
  
		/** simple constructor */
		RegGaussianProcess( const NICE::Config *conf, 
			Kernel *kernelFunction = NULL, 
			const std::string & section = "RegGaussianProcess" );

		/** copy constructor */
		RegGaussianProcess ( const RegGaussianProcess & src );
		  
		/** simple destructor */
		virtual ~RegGaussianProcess();
		 
    using RegressionAlgorithmKernel::teach;   // <-- un-hides teach function
    
		/** learn parameters/models/whatever with a kernel matrix of a set
		 *  of vectors and the corresponding function values \c y 
		 */
		void teach ( KernelData *kernelData, const NICE::Vector & y );

		/** predict the function value for a vector by using its kernel values with
		 * the used training set, be careful with the order in \c kernelVector
		 */
		double predictKernel ( const NICE::Vector & kernelVector, double kernelSelf );
		
		virtual RegGaussianProcess *clone(void) const;

		void setOptimization ( bool optimizeParameters ) { this->optimizeParameters = optimizeParameters; };
		
		void restore(std::istream& ifs, int type = 0);
		void store(std::ostream& ofs, int type = 0) const;
		
		// moved to KernelData: std::pair< NICE::Vector, NICE::Vector> get_loo_estimates() const;
};

}

#endif