/** 
* @file RegressionAlgorithmKernel.cpp
* @brief interface for a regression algorithm which is based on kernels
* @author Erik Rodner
* @date 12/09/2009

*/
#include <iostream>

#include "RegressionAlgorithmKernel.h"

using namespace std;
using namespace NICE;
using namespace OBJREC;



RegressionAlgorithmKernel::RegressionAlgorithmKernel( const Config *_conf, Kernel *kernelFunction ) : conf( *_conf )
{
	this->kernelFunction = kernelFunction;
}
	
RegressionAlgorithmKernel::RegressionAlgorithmKernel( const RegressionAlgorithmKernel & src )
{
	if ( src.kernelFunction != NULL )
		this->kernelFunction = src.kernelFunction->clone();
	else
		this->kernelFunction = NULL;
	
	this->X = src.X;
	this->y = src.y;
  this->conf = src.conf;
}

RegressionAlgorithmKernel::~RegressionAlgorithmKernel()
{
}

void RegressionAlgorithmKernel::teach ( const VVector & X, const NICE::Vector & y )
{
	if ( kernelFunction == NULL )
		fthrow( Exception, "RegressionAlgorithmKernel::teach: To use this function, you have to specify a kernel function using the constructor" );
  
	this->y = y;
	this->X = X;

	KernelData *kernelData = new KernelData ( &conf );

	kernelFunction->calcKernelData ( this->X, kernelData );
	kernelData->updateCholeskyFactorization();

	teach ( kernelData, this->y );
  
  delete kernelData;
}

double RegressionAlgorithmKernel::predict ( const NICE::Vector & x )
{
	if ( kernelFunction == NULL )
		fthrow( Exception, "RegressionAlgorithmKernel::predict: To use this function, you have to specify a kernel function using the constructor" );

	if ( this->X.size() == 0 ) 
		fthrow( Exception, "RegressionAlgorithmKernel::predict: To use this function, you have to use teach(const VVector&, const Vector&) !" );

	NICE::Vector kstar;
	kernelFunction->calcKernelVector ( this->X, x, kstar );	

	double kstarstar = kernelFunction->K(x,x);

	return predictKernel (kstar, kstarstar);
}