// file: $isip/class/pr/PhoneticDecisionTree/pdt_06.cc
// version: $Id: pdt_06.cc 8769 2002-11-01 17:54:41Z parihar $
//

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

// method: load method
//
boolean PhoneticDecisionTree::load(const Attributes& attributes_a,
				   PhoneticDecisionTreeNode& pdtnode_a) {

  boolean res;
  
  res = attributes_d.assign(attributes_a);
  res = pdt_rootnode_d.assign(pdtnode_a);

  // exit gracefully
  //
  return res;
}  

// method: loadTrain
//
// arguments:
//  Vector<ContextMap>& context_map: (input) ContextMaps
//  long& left_context: (input) left context length
//  long& right_context: (input) right context length
//  Vector<SearchSymbol>& upper_symbol_table: (input) symbol-table above the
//                                            lowest level (phones)
//  Vector<SearchSymbol>& contextless_symbol_table: (input) symbol-table with
//                                                  no context (phones)
//  Vector<DiGraph<SearchNode> >& sub_graphs: (input) Subgraphs for the
//                                            ContextMaps
//  Vector<SearchSymbol>& symbol_table: (input) Symbol Table (states)
//  HashTable<SearchSymbol, Long>& symbol_hash: (input) Mapping from symbols
//                                              to StatisticalModels
//  Vector<StatisticalModel>& stat_models: (input) Pool of StatisticalModels
//  Filename& ques_ans_file: (input) file for phonetic questions and answers
//  HashTable<SearchSymbol, Long>& tied_symbol_hash: (output) mapping of tied
//                                                   search-symbols to stat
//                                                   models
//  Vector<StatisticalModel>& tied_stat_models: (input) Pool of tied
//                                              StatisticalModels
//
// return: a boolean value indicating status
//
// this method computes loads the necessary variables needed for
// PhoneticDecisionTree class to train a decision-tree
//
boolean PhoneticDecisionTree::loadTrain(Vector<ContextMap>& context_map_a,
					long& left_context_a,
					long& right_context_a,
					Vector<SearchSymbol>&
					upper_symbol_table_a,
					Vector<SearchSymbol>&
					contextless_symbol_table_a,
					Vector<DiGraph<SearchNode> >&
					sub_graphs_a,
					Vector<SearchSymbol>&
					symbol_table_a,
					HashTable<SearchSymbol,Long>&
					symbol_hash_a,
					Vector<StatisticalModel>&
					stat_models_a,
					Filename& ques_ans_file_a,
					HashTable<SearchSymbol, Long>&
					tied_symbol_hash_a,
					Vector<StatisticalModel>&
					tied_stat_models_a) {

  // local variables
  //
  Data data;
  boolean res = true;    
  
  // add the central-phone and state indices as the first two
  // attributes. note that the PhoneticDecisionTree is first split
  // using the central-symbol (phone) attribute, then using the
  // symbol-position (state) and then recursively using the phonetic
  // questions. this way we have n*m number of sub-trees.
  //
  Attribute temp_attribute;
  String temp_cph;
  temp_cph.assign(CPH);
  String temp_pos;
  temp_pos.assign(POS);
  SingleLinkedList<String> temp_all_cph;
  SingleLinkedList<String> temp_all_pos;
    
  // get central phones that have context, don't include the last two
  // symbols - NO_LEFT_CONTEXT and NO_RIGHT_CONTEXT
  //
  if (!getCentralSymbols(upper_symbol_table_a, contextless_symbol_table_a,
			 temp_all_cph)) {
    return Error::handle(name(), L"loadTrain", ERR, __FILE__, __LINE__);
  }
  
  // get the positions of the models
  //
  long context_len = (long)1 + left_context_a + right_context_a;
  
  for (long l = 0; l < context_len; l++) {
    String temp_pos;
    temp_pos.assign(l);
    temp_all_pos.insert(&temp_pos);
  }
  
  // set the central and position attributes
  //
  temp_attribute.assign(temp_cph, temp_all_cph);
  attributes_d.insert(&temp_attribute);
  temp_attribute.assign(temp_pos, temp_all_pos);
  attributes_d.insert(&temp_attribute);
  
  // get all possible answers and questions for phonetic-decision-trees
  //
  SingleLinkedList<Pair<Long, String> > questions;
  HashTable<String, String>  answers;
  if (!readQuestionAnswer(ques_ans_file_a, questions, answers)) {
    return Error::handle(name(), L"loadTrain", ERR, __FILE__, __LINE__);
  }

  // find the statistical models that are already tied, we 'll not tie
  // these using the state-tying procedure
  //  
    
  // loop-over all the context-maps and pool the
  // statistical-models. check if all the context-maps have the same
  // length as expected
  //
  if (!poolStatisticalModel(context_map_a, contextless_symbol_table_a,
			    sub_graphs_a, symbol_table_a, symbol_hash_a,
			    stat_models_a, context_len, questions, answers,
			    data, tied_symbol_hash_a, tied_stat_models_a)) {
    return Error::handle(name(), L"loadTrain", ERR, __FILE__, __LINE__);
  }
  
  // add the data to the data at the root node
  //
  pdt_rootnode_d.setDataPoints(data);
  
  // exit gracefully
  //
  return res;
}

// method: loadTest
//
// arguments:
//  Filename phonetic_dt_file: (input) file with the input decisiontree
//
// return: a boolean value indicating status
//
// this method loads the DecisionTree
//
boolean PhoneticDecisionTree::loadTest(Filename& phonetic_dt_file_a) {

  // local variables
  //
  boolean res = true;
  
  // load the decision-tree in binary format
  //
  if (phonetic_dt_file_a.length() == 0) { 
    return Error::handle(name(), L"loadTest - invalid decision-tree file", ERR, __FILE__, __LINE__);
  }
  
  // open the decision-tree sof file
  //
  Sof in_sof;
  if(!in_sof.open(phonetic_dt_file_a, File::READ_ONLY, File::BINARY)) {
    return Error::handle(phonetic_dt_file_a, L"open", ERR, __FILE__, __LINE__);
  }
  
  // read the decision-tree from an sof file
  //
  read(in_sof, long(0));
  
  // close the input sof file
  //
  in_sof.close();
  
  // exit gracefully
  //
  return res;
}
