/**
* @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/gradientBased/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