// file: $isip_ifc/class/pr/RelevanceVectorMachine/rvmt_00.cc
// version: $Id: rvmt_00.cc 10424 2006-02-10 20:37:45Z raghavan $
//

// isip include files
//
#include "RVMTrainData.h"
#include <Boolean.h>

// method: RVMTrainData
//
// arguments: none
//
// return: none
//
RVMTrainData::RVMTrainData() {

  // initialization only needs to be done for the tuning parameters
  // the remainder must be initialized by the trainer
  //
  alpha_thresh_d = DEF_ALPHA_THRESH;
  min_allowed_weight_d = DEF_MIN_ALLOWED_WEIGHT;
  max_rvm_its_d = DEF_MAX_RVM_ITS;
  max_update_its_d = DEF_MAX_UPDATE_ITS;
  min_theta_d = DEF_MIN_THETA;
  momentum_d = DEF_MOMENTUM;
  max_additions_d = DEF_MAX_ADDITIONS;
  save_restart_d = DEF_SAVE_RESTART;
  load_restart_d = DEF_LOAD_RESTART;
  max_memory_d = DEF_MAX_MEMORY;
  use_subsets_d = DEF_USE_SUBSETS;
  subset_size_d = DEF_SUBSET_SIZE;
  num_samples_d = 0;
  dimA_d = 0;
  last_changed_d = 0;
  num_subsets_d = 0;
  active_subset_d = -1;
}

// method: debug
//
// arguments:
//  const unichar* msg: (input) message to print
//
// return: a boolean value indicating status
//
boolean RVMTrainData::debug(const unichar* msg_a) const {

  // output an information message
  //
  String output;
  output.debugStr(name(), msg_a, L":");
  Console::put(output);
  Console::increaseIndention();
 
  // output the class data
  //
  Float alpha_thresh = alpha_thresh_d;
  alpha_thresh.debug(L"alpha_thresh_d");

  Float min_allowed_weight = min_allowed_weight_d;
  min_allowed_weight.debug(L"min_allowed_weight_d");
 
  Long max_rvm_its = max_rvm_its_d;
  max_rvm_its.debug(L"max_rvm_its_d");

  Long max_update_its = max_update_its_d;
  max_update_its.debug(L"max_update_its_d");

  Float min_theta = min_theta_d;
  min_theta.debug(L"min_theta_d");

  Float momentum = momentum_d;
  momentum.debug(L"momentum_d");

  Long max_additions = max_additions_d;
  max_additions.debug(L"max_additions_d");

  Boolean save_restart = save_restart_d;
  save_restart.debug(L"save_restart_d");
  restart_save_file_d.debug(L"restart_save_file_d");

  Boolean load_restart = load_restart_d;
  load_restart.debug(L"load_restart_d");
  restart_load_file_d.debug(L"restart_load_file_d");
  
  Long max_memory = max_memory_d;
  max_memory.debug(L"max_memory_d");

  Boolean use_subsets = use_subsets_d;
  use_subsets.debug(L"use_subsets_d");

  Long subset_size = subset_size_d;
  subset_size.debug(L"subset_size_d");
  
  // model data
  //
  Long num_samples = num_samples_d;
  num_samples.debug(L"num_samples_d");
  Long dimA = dimA_d;
  dimA.debug(L"dimA_d");
  A_d.debug(L"A_d");             
  phi_d.debug(L"phi_d");           
  curr_weights_d.debug(L"curr_weights_d");  
  last_rvm_weights_d.debug(L"last_rvm_weights_d");
  targets_d.debug(L"targets_d");
 
  // IRLS training quantities
  //
  Long last_changed = last_changed_d;
  last_changed.debug(L"last_changed_d");
  sigma_d.debug(L"sigma_d");          
  B_d.debug(L"B_d");              
  gradient_d.debug(L"gradient_d");       
  hessian_d.debug(L"hessian_d");        
  covar_cholesky_d.debug(L"covar_cholesky_d"); 
  old_irls_weights_d.debug(L"old_irls_weights_d");
                                
  // incremental training quantities
  //
  active_rvs_d.debug(L"active_rvs_d");
  S_d.debug(L"S_d");              
  Q_d.debug(L"Q_d");              
  hyperparams_d.debug(L"hyperparams_d");
  active_params_d.debug(L"active_params_d");    
  weights_d.debug(L"weights_d");        
  last_hyperparams_d.debug(L"last_hyperparams_d");
  twoback_hyperparams_d.debug(L"twoback_hyperparams_d");
  Long num_subsets = num_subsets_d;
  num_subsets.debug(L"num_subsets_d");
  Long active_subset = active_subset_d;
  active_subset.debug(L"active_subset_d");
  subsets_d.debug(L"subsets_d");

  // caching quantities
  //
  cache_index_table_d.debug(L"cache_index_table_d");
  phi_cache_d.debug(L"phi_cache_d");

  // decrease indention
  //
  Console::decreaseIndention();

  // exit gracefully
  //
  return true;
}

// method: assign
//
// arguments:
//  const RVMTrainData& copy: (input) item to assign from
//
// return: boolean value indicating status
//
// this method changes the object to match the input object
//
boolean RVMTrainData::assign(const RVMTrainData& copy_a) {

  alpha_thresh_d = copy_a.alpha_thresh_d;
  min_allowed_weight_d = copy_a.min_allowed_weight_d;
  max_rvm_its_d = copy_a.max_rvm_its_d;
  max_update_its_d = copy_a.max_update_its_d;
  min_theta_d = copy_a.min_theta_d;
  momentum_d = copy_a.momentum_d;
  max_additions_d = copy_a.max_additions_d;

  num_samples_d = copy_a.num_samples_d;
  dimA_d = copy_a.dimA_d;
  last_changed_d = copy_a.last_changed_d;

  save_restart_d = copy_a.save_restart_d;
  load_restart_d = copy_a.load_restart_d;

  max_memory_d = copy_a.max_memory_d;

  use_subsets_d = copy_a.use_subsets_d;
  subset_size_d = copy_a.subset_size_d;
  num_subsets_d = copy_a.num_subsets_d;
  active_subset_d = copy_a.active_subset_d;

  // assign all of the class data
  //
  return (
	A_d.assign(copy_a.A_d) &&
	phi_d.assign(copy_a.phi_d) &&
	curr_weights_d.assign(copy_a.curr_weights_d) &&
	last_rvm_weights_d.assign(copy_a.last_rvm_weights_d) &&
	targets_d.assign(copy_a.targets_d) &&
	sigma_d.assign(copy_a.sigma_d) &&
	B_d.assign(copy_a.B_d) &&
	gradient_d.assign(copy_a.gradient_d) &&
	hessian_d.assign(copy_a.hessian_d) &&
	covar_cholesky_d.assign(copy_a.covar_cholesky_d) &&
	old_irls_weights_d.assign(copy_a.old_irls_weights_d) &&
	S_d.assign(copy_a.S_d) &&
	Q_d.assign(copy_a.Q_d) &&
	hyperparams_d.assign(copy_a.hyperparams_d) &&
	active_params_d.assign(copy_a.active_params_d) &&
	weights_d.assign(copy_a.weights_d) &&
	last_hyperparams_d.assign(copy_a.last_hyperparams_d) &&
	twoback_hyperparams_d.assign(copy_a.twoback_hyperparams_d) &&
	restart_save_file_d.assign(copy_a.restart_save_file_d) &&
	restart_load_file_d.assign(copy_a.restart_load_file_d) &&
	subsets_d.assign(copy_a.subsets_d) &&
	cache_index_table_d.assign(copy_a.cache_index_table_d) &&
	phi_cache_d.assign(copy_a.phi_cache_d) &&
	active_rvs_d.assign(copy_a.active_rvs_d));
}

// method: assignParameters
//
// arguments:
//  const RVMTrainData& copy: (input) item to assign from
//
// return: boolean value indicating status
//
// this method copies only the integral type parameters
//
boolean RVMTrainData::assignParameters(const RVMTrainData& copy_a) {

  alpha_thresh_d = copy_a.alpha_thresh_d;
  min_allowed_weight_d = copy_a.min_allowed_weight_d;
  max_rvm_its_d = copy_a.max_rvm_its_d;
  max_update_its_d = copy_a.max_update_its_d;
  min_theta_d = copy_a.min_theta_d;
  momentum_d = copy_a.momentum_d;
  max_additions_d = copy_a.max_additions_d;

  return true;
}

// method: eq
//
// arguments:
//  const RVMTrainData& arg: (input) item to check
//
// return: boolean value indicating equality
//
// this method checks for equality
//
boolean RVMTrainData::eq(const RVMTrainData& arg_a) const {

  if ((alpha_thresh_d != arg_a.alpha_thresh_d) ||
      (min_allowed_weight_d != arg_a.min_allowed_weight_d) ||
      (max_rvm_its_d != arg_a.max_rvm_its_d) ||
      (max_update_its_d != arg_a.max_update_its_d) ||
      (min_theta_d != arg_a.min_theta_d) ||
      (momentum_d != arg_a.momentum_d) ||
      (max_additions_d != arg_a.max_additions_d) ||
      (num_samples_d != arg_a.num_samples_d) ||
      (dimA_d != arg_a.dimA_d) ||
      (last_changed_d != arg_a.last_changed_d) ||
      (save_restart_d != arg_a.save_restart_d) ||
      (load_restart_d != arg_a.load_restart_d) ||
      (max_memory_d != arg_a.max_memory_d) ||
      (use_subsets_d != arg_a.use_subsets_d) ||
      (subset_size_d != arg_a.subset_size_d) ||
      (num_subsets_d != arg_a.num_subsets_d) ||
      (active_subset_d != arg_a.active_subset_d))  {
    return false;
  }

  // compare all of the class data
  //
  return (
	A_d.eq(arg_a.A_d) &&
	phi_d.eq(arg_a.phi_d) &&
	curr_weights_d.eq(arg_a.curr_weights_d) &&
	last_rvm_weights_d.eq(arg_a.last_rvm_weights_d) &&
	targets_d.eq(arg_a.targets_d) &&
	sigma_d.eq(arg_a.sigma_d) &&
	B_d.eq(arg_a.B_d) &&
	gradient_d.eq(arg_a.gradient_d) &&
	hessian_d.eq(arg_a.hessian_d) &&
	covar_cholesky_d.eq(arg_a.covar_cholesky_d) &&
	old_irls_weights_d.eq(arg_a.old_irls_weights_d) &&
	S_d.eq(arg_a.S_d) &&
	Q_d.eq(arg_a.Q_d) &&
	hyperparams_d.eq(arg_a.hyperparams_d) &&
	active_params_d.eq(arg_a.active_params_d) &&
	weights_d.eq(arg_a.weights_d) &&
	last_hyperparams_d.eq(arg_a.last_hyperparams_d) &&
	twoback_hyperparams_d.eq(arg_a.twoback_hyperparams_d) &&
	restart_save_file_d.eq(arg_a.restart_save_file_d) &&
	restart_load_file_d.eq(arg_a.restart_load_file_d) &&
	subsets_d.eq(arg_a.subsets_d) &&
	cache_index_table_d.eq(arg_a.cache_index_table_d) &&
	phi_cache_d.eq(arg_a.phi_cache_d) &&
	active_rvs_d.eq(arg_a.active_rvs_d));
}

// method: clear
//
// arguments:
//  Integral::CMODE ctype: (input) clear mode
//
// return: a boolean value indicating status
//
// this method resets the data members to the default values
//
boolean RVMTrainData::clear(Integral::CMODE ctype_a) {

  if (ctype_a != Integral::RETAIN) {
    last_changed_d = 0;
    dimA_d = 0;
    num_samples_d = 0;
    alpha_thresh_d = DEF_ALPHA_THRESH;
    min_allowed_weight_d = DEF_MIN_ALLOWED_WEIGHT;
    max_rvm_its_d = DEF_MAX_RVM_ITS;
    max_update_its_d = DEF_MAX_UPDATE_ITS;
    min_theta_d = DEF_MIN_THETA;
    momentum_d = DEF_MOMENTUM;
    max_additions_d = DEF_MAX_ADDITIONS;
    save_restart_d = DEF_SAVE_RESTART;
    load_restart_d = DEF_LOAD_RESTART;
    max_memory_d = DEF_MAX_MEMORY;
    use_subsets_d = DEF_USE_SUBSETS;
    subset_size_d = DEF_SUBSET_SIZE;
    num_subsets_d = 0;
    active_subset_d = -1;
  }

  // assign all of the class data
  //
  return (
	A_d.clear(ctype_a) &&
	phi_d.clear(ctype_a) &&
	curr_weights_d.clear(ctype_a) &&
	last_rvm_weights_d.clear(ctype_a) &&
	targets_d.clear(ctype_a) &&
	sigma_d.clear(ctype_a) &&
	B_d.clear(ctype_a) &&
	gradient_d.clear(ctype_a) &&
	hessian_d.clear(ctype_a) &&
	covar_cholesky_d.clear(ctype_a) &&
	old_irls_weights_d.clear(ctype_a) &&
	S_d.clear(ctype_a) &&
	Q_d.clear(ctype_a) &&
	hyperparams_d.clear(ctype_a) &&
	active_params_d.clear(ctype_a) &&
	weights_d.clear(ctype_a) &&
	last_hyperparams_d.clear(ctype_a) &&
	twoback_hyperparams_d.clear(ctype_a) &&
	restart_save_file_d.clear(ctype_a) &&
	restart_load_file_d.clear(ctype_a) &&
	subsets_d.clear(ctype_a) &&
	cache_index_table_d.clear(ctype_a) &&
	phi_cache_d.clear(ctype_a) &&
	active_rvs_d.clear(ctype_a));
}

//-----------------------------------------------------------------------------
//
// we define non-integral constants in the default constructor
//
//-----------------------------------------------------------------------------

// constants: required constants such as the class name
//
const String RVMTrainData::CLASS_NAME(L"RVMTrainData");

// static instantiations: memory manager and a permanent scratch space
//
MemoryManager RVMTrainData::mgr_d(sizeof(RVMTrainData), RVMTrainData::CLASS_NAME);
