/**
* @file LinRegression.cpp
* @brief Algorithm for linear regression
* @author Frank Prüfer
* @date 08/13/2013

*/  

#include "vislearning/regression/linregression/LinRegression.h"

using namespace OBJREC;

using namespace std;

using namespace NICE;

LinRegression::LinRegression(){
  dim = 2;
}

LinRegression::LinRegression(uint dimension){
  dim = dimension;
}

LinRegression::~LinRegression()
{
}

void LinRegression::teach ( const NICE::VVector & x, const NICE::Vector & y ){
  
  if (dim == 0){	//dimension not specified via constructor
    dim = x[0].size()+1;  //use full dimension of data
  }
  
  cerr<<"dim: "<<dim<<endl;
  cerr<<"examples: "<<x.size()<<endl;
  
  for ( uint i = 0;i < dim;i++ ){  //initialize alpha-vector
    alpha.push_back(0.0);
  }
  
  if ( dim == 2 ){  //two-dimensional least squares
    double meanX;
    double meanY = y.Mean();
    double sumX = 0.0;
    
    for ( uint i = 0;i < x.size();i++ ){
      sumX += x[i][0];
    }
    meanX = sumX / (double)x.size();
 
    
    for ( uint i = 0; i < x.size(); i++ ){
	alpha[1] += x[i][0] * y[i];
    }
    
    alpha[1] -= x.size() * meanX * meanY;
    
    double tmpAlpha = 0.0;
    for ( uint i = 0; i < x.size(); i++ ){
      tmpAlpha += x[i][0] * x[i][0];
    }
    tmpAlpha -= x.size() * meanX * meanX;
    
    alpha[1] /= tmpAlpha;
    
    alpha[0] = meanY - alpha[1] * meanX;    
  }
}

double LinRegression::predict ( const NICE::Vector & x ){
  double y;
  if ( dim = 2 ){  //two-dimensional least squares
    y = alpha[0] + alpha[1] * x[0];
  }
  
  return y;
}