/** 
* @file LaplaceApproximation.h
* @author Erik Rodner
* @date 02/17/2010

*/
#ifndef _NICE_OBJREC_LAPLACEAPPROXIMATIONINCLUDE
#define _NICE_OBJREC_LAPLACEAPPROXIMATIONINCLUDE

#include "core/basics/Config.h"
#include "vislearning/classifier/kernelclassifier/LikelihoodFunction.h"
#include "vislearning/math/kernels/KernelData.h"

namespace OBJREC {
  
/** @class LaplaceApproximation
 * some utility functions for laplace approximation 
 *
 * @author Erik Rodner
 */
class LaplaceApproximation
{

    protected:
		/** optimization settings */
		uint maxiterations;
		double minimumDelta;
		bool verbose;

		/** useful variables */
		NICE::Vector mode;
		NICE::Vector hessianW;
		NICE::Vector gradientL;
		NICE::Matrix cholB;

		NICE::Vector a;

		double objective;
		double noiseTerm;

		void updateCache ( const NICE::Matrix & kernelMatrix, const NICE::Vector & y, const LikelihoodFunction *likelihoodFunction );

    public:
  
  		/** use standard settings */
		LaplaceApproximation();

		/** simple constructor using config values for numerical details */
		LaplaceApproximation( const NICE::Config *conf, const std::string & section = "LaplaceApproximation" );
		  
		/** simple destructor */
		virtual ~LaplaceApproximation();
  
  		void approximate ( KernelData *kernelData, const NICE::Vector & y,
					   const LikelihoodFunction *likelihoodFunction );

		double predict ( const NICE::Vector & kernelVector, double kernelSelf, const NICE::Vector & y, 
				const LikelihoodFunction *likelihoodFunction ) const;

		const NICE::Vector & getMode () const { return mode; };
		const NICE::Vector & getHessian () const { return hessianW; };
		const NICE::Vector & getGradient () const { return gradientL; };
		const NICE::Vector & getAVector () const { return a; };
		const NICE::Matrix & getCholeskyB () const { return cholB; };

		double getObjective () const { return objective; };
};

}

#endif