// file: $isip/class/stat/SupportVectorModel/svm_08.cc
// version: $Id: svm_08.cc 8764 2002-10-26 19:45:56Z jelinek $
//

// isip include files
//
#include "SupportVectorModel.h"

// method: getLogLikelihood
//
// arguments:
//  const VectorFloat& input: (input) test vector
//
// return: float value giving the log-likelihood of the data given the model
//
// this method gives the log likelihood of the test vector.
// log-likelihood will be computed as base 10 logarithm of distance.
//
float SupportVectorModel::getLogLikelihood(const VectorFloat& input_a) {

  // check for initialization
  //
  if ((!is_valid_d) && (!init())) {
    Error::handle(name(), L"getLogLikelihood", Error::ARG,
		  __FILE__, __LINE__);
  }

  double distance = getDistance(input_a);
  double prob = 0;
  sigmoid_d.compute(prob, distance);
  return log(prob);
}

// method: getDistance
//
// arguments:
//  const VectorFloat& input: (input) test vector
//
// return: double value of distance from the test vector, computed
// according to:
//
//                     N
//                   ----                      
// distance = bias + \    [ alpha(i) * kernel (x, sv[i]) ]
//                   /___                    i
//                     i
//
//  'sv' is the support vector
//  'N' is the number of support vectors
//  'alpha(i)' is the weight for i-th support vector
//  'bias' is the distance of hyperplane from the origin
//
double SupportVectorModel::getDistance(const VectorFloat& input_a) {

  double distance = 0;
  float kernel_function = 0;
  
  for (long i = 0; i < support_vectors_d.length(); i++) {

    // compute dot product using the kernel
    //
    if (algorithm_d == MULTIPLE_KERNEL) {
      kernels_d(i).compute(kernel_function, input_a, support_vectors_d(i));
    }
    else if (algorithm_d == SINGLE_KERNEL) {
      kernels_d(0).compute(kernel_function, input_a, support_vectors_d(i));
    }
    else {
      return Error::handle(name(), L"getDistance",
			   Error::NOT_IMPLEM, __FILE__, __LINE__);
    }
    
    distance += alphas_d(i) * (double)kernel_function;
  }
  
  distance -= bias_d;
  
  // exit gracefully
  //
  return distance;
}


// method: accumulate
//
// arguments:
//  VectorFloat& data: (input) feature vector
//
// return: boolean value indicating status
//
// this method accumulates the model parameters using the input features
//
boolean SupportVectorModel::accumulate(VectorFloat& data_a) {

  return Error::handle(name(), L"accumulate", Error::NOT_IMPLEM,
		       __FILE__, __LINE__);
}

// method: initialize
//
// arguments:
//  VectorFloat& param: (input) initialization parameters
//
// return: boolean value indicating status
//
// this method initializes the model parameters using the accumulated features
//
boolean SupportVectorModel::initialize(VectorFloat& param_a) {

  return Error::handle(name(), L"initialize", Error::NOT_IMPLEM,
		       __FILE__, __LINE__);

}

// method: update
//
// arguments:
//  VectorFloat& varfloor: (input) variance floor
//  long min_count: (input) minimum model count
//
// return: a boolean value indicating status
//
// this method updates the statistical model parameters using the
// accumulated statistics during training
//
boolean SupportVectorModel::update(VectorFloat& varfloor_a, long min_count_a) {

  return Error::handle(name(), L"update", Error::NOT_IMPLEM,
		       __FILE__, __LINE__);
}

// method: accumulate
//
// arguments:
//  VectorDouble& param: (input) training parameters
//  VectorFloat& data: (input) observations
//  boolean precomp: (input) flag that indicate if data is precomputed
//
// return: a boolean value indicating status
//
// this method accumulates the statistics for the model which are
// needed to update the model parameters during training
//
boolean SupportVectorModel::accumulate(VectorDouble& param_a,
				  VectorFloat& data_a,
				  boolean precomp_a) {

  return Error::handle(name(), L"accumulate", Error::NOT_IMPLEM,
		       __FILE__, __LINE__);
}

