/** 
* @file KCGPRegOneVsAll.h
* @author Erik Rodner
* @date 12/10/2009

*/
#ifndef _NICE_OBJREC_KCGPREGONEVSALLINCLUDE
#define _NICE_OBJREC_KCGPREGONEVSALLINCLUDE

#include "vislearning/classifier/classifierbase/KernelClassifier.h"
#include "vislearning/regression/gpregression/RegGaussianProcess.h"
#include "vislearning/math/kernels/TraceApproximation.h"
#include "vislearning/regression/gpregression/modelselcrit/genericGPModelSelection.h"

#include <vector>

namespace OBJREC {
  
#undef ROADWORKS
#define ROADWORKS fthrow(Exception, "Persistent interface not implemented!");

/** @class KCGPRegOneVsAll
 * One vs. All GP regression classifier with joint optimization
 * of kernel parameters
 *
 * @author Erik Rodner
 */
class KCGPRegOneVsAll : public KernelClassifier
{

    protected:
		/** set of classifiers with the corresponding class */
		std::vector< std::pair<int, RegGaussianProcess *> > classifiers;
	
		/** clone from prototype to generate new classifiers */
		const RegGaussianProcess *prototype;

		/** whether to optimize hyper-parameters */
		bool optimizeParameters;

		/** tell us something about what you are doing */
		bool verbose;

		/** maximum number of iterations of the hyper-parameter estimation */
		int maxIterations;

		TraceApproximation *traceApproximation;
		GPMSCLooLikelihoodRegression *modelselcrit;

		/** use the hyperparameters which lead to the best leave-one-out criterion */
		bool useLooParameters;

		/** whether to invest some computation time to estimate the uncertainty of the prediction */
		bool computeUncertainty;

		/** for computing uncertainties we need the cholesky decomposition of the kernel matrix */
		NICE::Matrix choleskyMatrix;

		/** whether to calibrate the probabilities using uncertainty estimates */
		bool calibrateProbabilities;

		/** how many samples should we draw to estimate the probabilities */
		uint numSamplesCalibration;

    public:
  		/** simplest constructor */
		KCGPRegOneVsAll(){};
	    	
		/** simple constructor */
		KCGPRegOneVsAll( const NICE::Config *conf, Kernel *kernelFunction = NULL, const std::string & section = "KCGPRegOneVsAll" );
		  
		/** copy constructor */
		KCGPRegOneVsAll( const KCGPRegOneVsAll &vcova );
		
		/** simple destructor */
		virtual ~KCGPRegOneVsAll();
     
	 	/** teach the classifier with a kernel matrix and the corresponding class labels @param y ! */
		void teach ( KernelData *kernelData, const NICE::Vector & y );
		void teach ( KernelData *kernelData, const std::vector<double> & y );

		/** classify an example by using its kernel values with the training set,
			be careful with the order in @param kernelVector */
		ClassificationResult classifyKernel ( const NICE::Vector & kernelVector, double kernelSelf ) const;

		void restore(std::istream&, int);
		void store(std::ostream&, int) const;
		void clear();
		
		/** clone this object */
		virtual KCGPRegOneVsAll *clone(void) const;

};

#undef ROADWORKS

}

#endif