// file: $isip/class/search/SearchLevel/SearchLevel.h
// version: $Id: SearchLevel.h 10570 2006-05-13 23:51:06Z may $
//

// make sure definitions are only made once
//
#ifndef ISIP_SEARCH_LEVEL
#define ISIP_SEARCH_LEVEL

// isip include files:
//
#ifndef ISIP_SEARCH_SYMBOL
#include <SearchSymbol.h>
#endif

#ifndef ISIP_STATISTICAL_MODEL
#include <StatisticalModel.h>
#endif

#ifndef ISIP_MIXTURE_MODEL
#include <MixtureModel.h>
#endif

#ifndef ISIP_GAUSSIAN_MODEL
#include <GaussianModel.h>
#endif

#ifndef ISIP_NGRAM_MODEL
#include <NGramModel.h>
#endif

#ifndef ISIP_DI_GRAPH
#include <DiGraph.h>
#endif

#ifndef ISIP_NAME_MAP
#include <NameMap.h>
#endif

#ifndef ISIP_CONTEXT_MAP
#include <ContextMap.h>
#endif

#ifndef ISIP_HASHTABLE
#include <HashTable.h>
#endif

#ifndef ISIP_FILENAME
#include <Filename.h>
#endif

#ifndef ISIP_SDB
#include <Sdb.h>
#endif

#ifndef ISIP_STRING
#include <String.h>
#endif

#ifndef ISIP_BOOLEAN
#include <Boolean.h>
#endif

#ifndef ISIP_FLOAT
#include <Float.h>
#endif

#ifndef ISIP_LONG
#include <Long.h>
#endif

// forward class definitions
//
class SearchNode;
class Context;

// SearchLevel: this class represents a particular level in the search
// hierarchy for a hierarchical search engine. each level has the following
// characteristics:
//
//   a) a beam pruning threshold
//   b) an instance pruning threshold
//   c) ability to hold context-dependent models with arbitrary left and right
//      contexts
//   d) ability to hold N-symbol context probabilities with arbitrary left
//      contexts + backoffs
//   e) maintain or discard old search tokens. for instance, once a higher
//      level symbol is completed, it may no longer be necessary to maintain
//      the lower level units that generated that symbol.
//
class SearchLevel {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  //----------------------------------------
  //
  // other important constants
  //
  //----------------------------------------
  
  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  static const String DEF_PARAM;
  static const String PARAM_DELIM1;
  static const String PARAM_DELIM2;
  static const String PARAM_DELIM3;      

  static const String PARAM_LEVEL_TAG;
  static const String PARAM_LEVEL_INDEX;  
  static const String PARAM_SYMBOL;
  static const String PARAM_NONSPEECH_BOUNDARY_SYMBOL;
  static const String PARAM_NONSPEECH_INTERNAL_SYMBOL;  
  static const String PARAM_DUMMY_SYMBOL;
  static const String PARAM_EXCLUDE_SYMBOL;
  static const String PARAM_NSYMBOL_EXCLUDE_SYMBOL;
  static const String PARAM_SPENALTY_EXCLUDE_SYMBOL;  
  static const String PARAM_CONTEXTLESS_SYMBOL;
  static const String PARAM_SKIP_SYMBOL;    
  static const String PARAM_MODEL;
  static const String PARAM_STAT_HASH;
  static const String PARAM_STAT;
  static const String PARAM_STAT_OCCUPANCY;
  static const String PARAM_NON_ADAPT_SYMBOL;

  static const String PARAM_USE_ACOUSTIC_SCORE;
  static const String PARAM_ACOUSTIC_SCALE;  
  static const String PARAM_USE_SYMBOL_GRAPH;
  static const String PARAM_HISTORY_PATHS;
  static const String PARAM_USE_NSYMBOL;
  static const String PARAM_NSYMBOL_ORDER;
  static const String PARAM_LM_SCALE;
  static const String PARAM_TR_SCALE;  
  static const String PARAM_SYMBOL_PENALTY;  
  static const String PARAM_NSYMBOL_MODEL;
  
  static const String PARAM_USE_CONTEXT;
  static const String PARAM_CONTEXT_MAPPING;  
  static const String PARAM_USE_LEXICAL_TREE;
  static const String PARAM_LEFT_CONTEXT_LENGTH;
  static const String PARAM_RIGHT_CONTEXT_LENGTH;
  
  static const String PARAM_USE_BEAM;
  static const String PARAM_BEAM_THRESHOLD;

  static const String PARAM_USE_INSTANCE;
  static const String PARAM_INSTANCE_THRESHOLD;   

  static const String PARAM_WRITE_SYMBOL_OCCUPANCY;
  static const String PARAM_SYMBOL_OCCUPANCY_FILE;

  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------  

  // define default value(s) of the class data
  //
  static const long DEF_TAG = -1;  
  static const long DEF_LEVEL_INDEX = 0;

  // symbol graph rescoring parameters
  //
  static const boolean DEF_USE_ACOUSTIC_SCORE = false;
  static const float DEF_ACOUSTIC_SCALE = 1.0;
  
  // symbol graph generation parameters
  //
  static const boolean DEF_USE_SYMBOL_GRAPH = false;
  static const long DEF_HISTORY_PATHS = 10;
  
  // beam pruning parameters
  //
  static const boolean DEF_BEAM_PRUNE = false;
  static const float DEF_BEAM_THRESHOLD = 300.0;
 
  // instance pruning parameters
  // 
  static const boolean DEF_INSTANCE_PRUNE = false;
  static const long DEF_INSTANCE_THRESHOLD = 3000;
  
  // context modes parameters
  //
  static const boolean DEF_USE_CONTEXT = false;  
  static const boolean DEF_USE_LEXICAL_TREE = false;  
  static const long DEF_LEFT_CONTEXT = 0;
  static const long DEF_RIGHT_CONTEXT = 0;
  
  // n-symbol modes parameters
  //
  static const boolean DEF_RESCORE_MODE = false;
  static const boolean DEF_USE_NSYMBOL = false;
  static const long DEF_NSYMBOL_ORDER = 0;
  static const float DEF_SYMBOL_PENALTY = 0.0;
  static const float DEF_LM_SCALE = 1.0;
  static const float DEF_TR_SCALE = 1.0;

  // symbol occupancy parameters
  //
  static const boolean DEF_WRITE_SYMBOL_OCCUPANCY = false;
  
  // num of mixtures 
  //
  static const long DEF_NUM_OF_MIXTURES = 1;

  //---------------------------------------
  //
  // error codes
  //
  //---------------------------------------

  static const long ERR = (long)90800;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // level number
  //
  Long level_index_d;
  
  // level tag
  //
  String level_tag_d;
  
  // num of mixtures 
  //
  Long num_of_mixtures_d;
  
  // type of the statistical model
  //
  StatisticalModel::TYPE stat_model_type_d;
  
  // symbols at this level,
  //   eg. if this is word level, symbols are all the words
  //   if phone level, symbols are all the phones
  //
  Vector<SearchSymbol> symbol_table_d;
  
  // non-speech boundary symbols at this level,
  //   symbols that are inserted at transcription ends in the training process
  //
  Vector<SearchSymbol> nonspeech_boundary_symbol_table_d;

  // non-speech internal symbols at this level,
  //   symbols that are inserted between each symbol in the training process
  //
  Vector<SearchSymbol> nonspeech_internal_symbol_table_d;    

  // dummy symbols at this level,
  //   symbols that act as mere place holders in the decoding process
  //
  Vector<SearchSymbol> dummy_symbol_table_d;

  // exclude symbols at this level,
  //   symbols that are excluded from the final hypothesis
  //
  Vector<SearchSymbol> exclude_symbol_table_d;

  // nsymbol exclude symbols at this level,
  //   symbols that are excluded from the nsymbol computation
  //
  Vector<SearchSymbol> nsymbol_exclude_symbol_table_d;

  // symbol penalty exclude symbols at this level,
  //   symbols that are excluded from the symbol penalty application
  //
  Vector<SearchSymbol> spenalty_exclude_symbol_table_d;    

  // context less symbols at this level,
  //   symbols that are context-independent throughout the decoding process
  //
  Vector<SearchSymbol> contextless_symbol_table_d;

  // skip symbols at this level,
  //   symbols that are context-independent and cannot be a context for
  //   any other symbol
  //
  Vector<SearchSymbol> skip_symbol_table_d;  

  // non adapt symbols at this level,
  //   symbols that are will not be adpated during statistical
  //   model adaptation
  //
  Vector<SearchSymbol> non_adapt_symbol_table_d;
  
  // symbol to statistical model mapping at this level,
  // hashtable of symbol and its index in the stat_models_d
  // this is for finding the index of a statistical model (value)
  // corresponding to a symbol (key)
  //   
  HashTable<SearchSymbol, Long> symbol_hash_d;

  // statistical models at this level,
  // statistical modesl have a unique index that can be cross referenced
  // via the hashtable of symbol symbol_hash_d
  //
  Vector<StatisticalModel> stat_models_d;

  // subgraph of the symbols at this level,
  // if this is the word level, the sub_graphs will be the phone network(s),
  // if this is the phone level, the sub_graphs will be the HMM(s)
  //
  Vector<DiGraph<SearchNode> > sub_graphs_d;

  // temporary set of graphs that are read from and written to an Sof file,
  // these graphs are used to construct the actual subgraph of symbols at
  // this particular level, this object must be member data accessible by
  // the write method of this class in order to calculate the correct
  // sof size for writing to a binary file
  //
  Vector< DiGraph<Ulong> > tmp_graphs_d;
  
  // variables related to language and acoustic model rescoring at this level
  //
  Boolean use_rescore_d;
  Boolean use_acoustic_score_d;
  Float acoustic_scale_d;  
  
  // variables related to evaluation of n-symbol probabilities at this level,
  //  order 1 is equivalent to prob{Symbol(n)}
  //  order 2 is equivalent to prob{Symbol(n) | Symbol(n-1)}
  //  order 3 is equivalent to prob{Symbol(n) | Symbol(n-1), Symbol(n-2)}
  //  likewise for orders 4, 5, 6, ..., N
  //
  Boolean use_nsymbol_d;
  Long nsymbol_order_d;

  // variables related to symbol graph generation
  //
  Boolean use_symbol_graph_d;
  Long history_paths_d;

  // member variable that computes the n-symbol probability of a sequence
  //
  Filename nsymbol_file_d;
  NGramModel nsymbol_model_d;
  
  // member variables related to the scale and symbol insertion penalty
  // 
  Float tr_scale_d; 
  Float lm_scale_d;
  Float symbol_penalty_d;  

  // variables related to context dependency at this level,
  // member variables related to generation of context-dependent expansion of
  // models for evaluation
  //
  Boolean use_context_d;  
  Long left_context_d;
  Long right_context_d;  

  // member variable that associates a context with a subgraph index
  //
  Vector<ContextMap> context_map_d;
  HashTable<Context, Ulong> context_hash_d;

  // member variables related to generation of lexical tree expansion of
  // models for evaluation
  //
  Boolean use_lexical_tree_d;  

  // variables related to prunning at this level at this level,  
  // member variables related to beam pruning. if the flag is set to true,
  // beam pruning will be employed at this level with the given beam threshold
  //
  Boolean use_beam_prune_d;
  Float beam_threshold_d;

  // member variables related to instance pruning. if the flag is set to
  // true, instance pruning will be employed at this level with only the
  // given number of instances maintained.
  //
  Boolean use_instance_prune_d;
  Long instance_threshold_d;
  
  // member variable related to symbol occupancies. the symbol
  // occupancies will be written to the file only when the flag is
  // true
  //
  Filename symbol_occupancy_file_d;
  Boolean write_symbol_occupancy_d;
  
  // define a static debug level
  //
  static Integral::DEBUG debug_level_d;
  
  // define a static memory manager
  //
  static MemoryManager mgr_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // debug methods
  //
  boolean debug(const unichar* message) const;

  // method: setDebug
  //
  static boolean setDebug(Integral::DEBUG debug_level) {
    debug_level_d = debug_level;
    return true;
  }

  // destructor/constructor(s)
  //
  ~SearchLevel();
  SearchLevel();
  SearchLevel(const SearchLevel& copy_level);
  
  // assign methods
  //
  boolean assign(const SearchLevel& copy_level);

  // sofSize methods
  //
  long sofSize() const;

  // method: read
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME);

  // method: write
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const;

  // method: readData
  //
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT, boolean param = true,
                   boolean nested = false);

  // method: writeData
  //
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // equality methods
  //
  boolean eq(const SearchLevel& compare_level) const;
  
  // method: new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }

  // clear methods
  //
  boolean clear(Integral::CMODE ctype = Integral::DEF_CMODE);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------

  // other read and write methods
  //
  boolean readLevelTag(Sof& sof, SofParser& parser);
  boolean readSymbols(Sof& sof, SofParser& parser);
  boolean readNonSpeechSymbols(Sof& sof, SofParser& parser);
  boolean readDummySymbols(Sof& sof, SofParser& parser);
  boolean readExcludeSymbols(Sof& sof, SofParser& parser);
  boolean readNSymbolExcludeSymbols(Sof& sof, SofParser& parser);
  boolean readSPenaltyExcludeSymbols(Sof& sof, SofParser& parser);
  boolean readContextLessSymbols(Sof& sof, SofParser& parser);
  boolean readSkipSymbols(Sof& sof, SofParser& parser);
  boolean readNonAdaptSymbols(Sof& sof, SofParser& parser);
  boolean readSubGraphs(Sof& sof, SofParser& parser);
  boolean readContextMapping(Sof& sof, SofParser& parser);

  boolean readConfig(Sof& sof, long tag, const String& cname = CLASS_NAME);
  
  boolean write(Sof& sof);  
  boolean writeLevelTag(Sof& sof) const;
  boolean writeSymbols(Sof& sof) const;
  boolean writeNonSpeechSymbols(Sof& sof) const;
  boolean writeContextLessSymbols(Sof& sof) const;
  boolean writeSkipSymbols(Sof& sof) const;      
  boolean writeDummySymbols(Sof& sof) const;
  boolean writeExcludeSymbols(Sof& sof) const;
  boolean writeNSymbolExcludeSymbols(Sof& sof) const;
  boolean writeSPenaltyExcludeSymbols(Sof& sof) const;
  boolean writeNonAdaptSymbols(Sof& sof) const;  
  boolean writeSubGraphs(Sof& sof) const;
  boolean writeStatisticalModels(Sof& sof) const;
  boolean writeAccumulators(Sof& sof) const;  
  boolean writeContextMapping(Sof& sof) const;

  boolean writeConfig(Sof& sof, long tag, const String& cname = CLASS_NAME) const;  

  // load and store methods
  //
  boolean load(Sof& sof, long tag = DEF_TAG);  
  boolean loadLevelTag(Sof& sof, long tag = DEF_TAG);
  boolean loadSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadNonSpeechSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadContextLessSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadSkipSymbols(Sof& sof, long tag = DEF_TAG);      
  boolean loadDummySymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadNSymbolExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadSPenaltyExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean loadNonAdaptSymbols(Sof& sof_a, long tag_a);
  
  boolean loadSubGraphs(Sof& sof, long tag = DEF_TAG);
  boolean loadStatisticalModels(Sof& sof, long tag = DEF_TAG);
  boolean loadContextMapping(Sof& sof, long tag = DEF_TAG);
  boolean loadNSymbolModel(Sof& sof, long tag = DEF_TAG);
  boolean loadNSymbolModel(long tag = DEF_TAG);

  boolean loadTransitionAccumulators(Sof& sof, long tag = DEF_TAG);
  boolean loadEmissionAccumulators(Sof& sof, long tag = DEF_TAG);  
  
  boolean loadOccupancies();
  
  boolean store(Sof& sof, long tag = DEF_TAG);  
  boolean storeLevelTag(Sof& sof, long tag = DEF_TAG);
  boolean storeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeNonSpeechSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeContextLessSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeSkipSymbols(Sof& sof, long tag = DEF_TAG);      
  boolean storeDummySymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeNSymbolExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeSPenaltyExcludeSymbols(Sof& sof, long tag = DEF_TAG);
  boolean storeNonAdaptSymbols(Sof& sof, long tag = DEF_TAG);  
  boolean storeSubGraphs(Sof& sof, long tag = DEF_TAG);
  boolean storeStatisticalModels(Sof& sof, long tag = DEF_TAG);
  boolean createStatisticalModels(Sof& sof, long tag = DEF_TAG);
  boolean storeAccumulators(Sof& sof, long tag = DEF_TAG);  
  boolean storeContextMapping(Sof& sof, long tag = DEF_TAG);

  boolean storeTransitionAccumulators(Sof& sof, long tag = DEF_TAG);
  boolean storeEmissionAccumulators(Sof& sof, long tag = DEF_TAG);
  
  boolean storeOccupancies();
  
  // method to generate the context map for the search level
  //
  boolean generateContextMapping(long left_order,
				 long right_order,
				 long num_levels,
				 Filename& context_list,
				 SearchLevel& level,
				 boolean wint_flag = false);
  
  boolean createCopy(long num_levels,
		     SearchSymbol& central_symbol,
		     ContextMap& context_map,
		     SearchLevel& level);
  
  // method: parseSymbols
  //
  boolean parseSymbols(String& symbols_string,
		       Vector<SearchSymbol>& symbols_vec);
  
  // method: convertDigraphs
  //
  boolean convertDigraphs();

  // method: convertSubgraphs
  //
  Vector< DiGraph<Ulong> > convertSubgraphs() const;  
  
  // method: readDataNonSpeechInternalSymbol
  //
  boolean readDataNonSpeechInternalSymbol(SofParser& parser, Sof& sof);

  // method: convertContexts
  //
  boolean convertContexts();
  
  // method: subGraphSize
  //
  long subGraphSize() const;

  // method: getLevelTag
  //
  String& getLevelTag() const {
    return (String&)level_tag_d;
  }

  // method: setLevelTag
  //
  boolean setLevelTag(String& arg) {
    return level_tag_d.assign(arg);
  }

  // method: getLmScale
  //
  float getLmScale() const {
    return lm_scale_d;
  }
  
  // method: setLmScale
  //
  boolean setLmScale(float scale) {
    return (lm_scale_d = scale);
  }

  // method: getTrScale
  //
  float getTrScale() const {
    return tr_scale_d;
  }
  
  // method: setTrScale
  //
  boolean setTrScale(float scale) {
    return (tr_scale_d = scale);
  }
  
  // method: getSymbolPenalty
  //
  float getSymbolPenalty() const {
    return symbol_penalty_d;
  }
  
  // method: setSymbolPenalty
  //  
  boolean setSymbolPenalty(float penalty) {
    return (symbol_penalty_d = penalty);
  }
  
  // method: getNumSubGraphs
  //
  long getNumSubGraphs() {
    return sub_graphs_d.length();
  }
  
  // set the sub graphs
  //
  boolean setNumSubGraphs(long num);

  // method: getSubGraphs
  //
  Vector<DiGraph<SearchNode> >& getSubGraphs() {
    return sub_graphs_d;
  }

  // method: setSubGraphs
  //
  boolean setSubGraphs(Vector<DiGraph<SearchNode> >& sub_graphs) {
    return sub_graphs_d.assign(sub_graphs);
  }

  // method: setTempGraphs
  //
  boolean setTempGraphs(Vector<DiGraph<Ulong> >& tmp_graphs) {
    return tmp_graphs_d.assign(tmp_graphs);
  }
  
  // method: getSubGraph
  //
  DiGraph<SearchNode>& getSubGraph(long index) {
    return sub_graphs_d(index);
  }

  // method: setSubGraph
  //
  boolean setSubGraph(long index, DiGraph<SearchNode>& arg) {
    if (index < sub_graphs_d.length()) {
      sub_graphs_d(index) = arg;
      return true;
    }
    return false;
  }
  
  // method: getStatisticalModels
  //
  Vector<StatisticalModel>& getStatisticalModels() {
    return stat_models_d;
  }

  // method: setStatisticalModels
  //
  boolean setStatisticalModels(long index, StatisticalModel& arg) {
    if (index < stat_models_d.length()) {
      stat_models_d(index) = arg;
      return true;
    }
    return false;
  }  

  // method: getSymbolHashTable
  //
  HashTable<SearchSymbol, Long>& getSymbolHashTable() {
    return symbol_hash_d;
  }

  // method: setSymbolHashTable
  //
  boolean setSymbolHashTable(HashTable<SearchSymbol, Long>& arg) {
    symbol_hash_d = arg;
    return true;
  }  

  // method: getLevelIndex
  //
  long getLevelIndex() const {
    return level_index_d;
  }
  
  // method: setLevelIndex
  //
  boolean setLevelIndex(long num) {
    level_index_d = num;
    return true;
  }

  // method: getContextMap
  //
  Vector<ContextMap>& getContextMap() {
    return context_map_d;
  }
    
  // method: setContextMap
  //
  boolean setContextMap(Vector<ContextMap>& arg) {
    context_map_d = arg;
    return true;
  }
    
  // beam pruning methods
  //
  boolean setBeam(float beam_threshold);

  // method: setBeam
  //
  boolean setBeam(boolean use_beam_prune = DEF_BEAM_PRUNE,
		  float beam_threshold = DEF_BEAM_THRESHOLD) {
    use_beam_prune_d = use_beam_prune;
    return setBeam(beam_threshold);
  }

  // method: useBeam
  //
  boolean useBeam() const {
    return use_beam_prune_d;
  }

  // method: getBeamThreshold
  //
  float getBeamThreshold() const {
    return beam_threshold_d;
  }

  // method: useSymbolGraph
  //
  boolean useSymbolGraph() const {
    return use_symbol_graph_d;
  }

  // method: getHistoryPaths
  //
  long getHistoryPaths() const {
    return history_paths_d;
  }  
  
  // instance pruning methods
  //
  boolean setInstance(boolean use_instance_prune = DEF_INSTANCE_PRUNE,
		      long instance_threshold = DEF_INSTANCE_THRESHOLD);
  boolean setInstance(long instance_threshold);

  // method: useInstance
  //
  boolean useInstance() const {
    return use_instance_prune_d;
  }

  // method: getInstanceThreshold
  //
  long getInstanceThreshold() const {
    return instance_threshold_d;
  }
  
  // context dependency methods
  //
  boolean setContext(long left_context, long right_context);
  
  // method: useContext
  //
  boolean useContext() const {
    return use_context_d;
  }
  
  // method: useLexicalTree
  //
  boolean useLexicalTree() const {
    return use_lexical_tree_d;
  }
  
  // method: getLeftContext
  //
  long getLeftContext() const {
    return left_context_d;
  }

  // method: getRightContext
  //
  long getRightContext() const {
    return right_context_d;
  }

  // method: useRescore
  //
  boolean useRescore() const {
    return use_rescore_d;
  }

  // method: useAcousticScore
  //
  boolean useAcousticScore() const {
    return use_acoustic_score_d;
  }  

  // method: getAcousticScale
  //
  float getAcousticScale() const {
    return acoustic_scale_d;
  }  
  
  // method: setRescore
  //
  boolean setRescore(boolean arg) {
    return (use_rescore_d = arg);
  }  
  
  // n-symbol methods
  //
  boolean setNSymbol(long nsymbol_order);  
  boolean setNSymbol(boolean use_nsymbol = DEF_USE_NSYMBOL,
		     long nsymbol_order = DEF_NSYMBOL_ORDER);

  // method: useNSymbol
  //
  boolean useNSymbol() const {
    return use_nsymbol_d;
  }

  // method: getNSymbolOrder
  //
  long getNSymbolOrder() const {
    return nsymbol_order_d;
  }

  // method: getNSymbolModel
  //
  NGramModel& getNSymbolModel() {
    return nsymbol_model_d;
  }  
  
  // symbol table methods
  //
  long getSymbolIndex(const SearchSymbol& input_symbol) const;

  // method: setSymbolTable
  //
  boolean setSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return symbol_table_d.assign(symbol_list);
  }

  // method: getSymbolTable
  //
  Vector<SearchSymbol>& getSymbolTable() {
    return symbol_table_d;
  }

  // method: setNonSpeechBoundarySymbolTable
  //
  boolean setNonSpeechBoundarySymbolTable(Vector<SearchSymbol>& symbol_list) {
    return nonspeech_boundary_symbol_table_d.assign(symbol_list);
  }

  // method: getNonSpeechBoundarySymbolTable
  //
  Vector<SearchSymbol>& getNonSpeechBoundarySymbolTable() {
    return nonspeech_boundary_symbol_table_d;
  }

  // method: setNonSpeechInternalSymbolTable
  //
  boolean setNonSpeechInternalSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return nonspeech_internal_symbol_table_d.assign(symbol_list);
  }

  // method: getNonSpeechInternalSymbolTable
  //
  Vector<SearchSymbol>& getNonSpeechInternalSymbolTable() {
    return nonspeech_internal_symbol_table_d;
  }
  
  // method: setDummySymbolTable
  //
  boolean setDummySymbolTable(Vector<SearchSymbol>& symbol_list) {
    return dummy_symbol_table_d.assign(symbol_list);
  }  

  // method: getDummySymbolTable
  //
  Vector<SearchSymbol>& getDummySymbolTable() {
    return dummy_symbol_table_d;
  }

  // method: setExcludeSymbolTable
  //
  boolean setExcludeSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return exclude_symbol_table_d.assign(symbol_list);
  }  

  // method: setNSymbolExcludeSymbolTable
  //
  boolean setNSymbolExcludeSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return nsymbol_exclude_symbol_table_d.assign(symbol_list);
  }  

  // method: setSPenaltyExcludeSymbolTable
  //
  boolean setSPenaltyExcludeSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return spenalty_exclude_symbol_table_d.assign(symbol_list);
  }  

  // method: getExcludeSymbolTable
  //
  Vector<SearchSymbol>& getExcludeSymbolTable() {
    return exclude_symbol_table_d;
  }

  // method: getNSymbolExcludeSymbolTable
  //
  Vector<SearchSymbol>& getNSymbolExcludeSymbolTable() {
    return nsymbol_exclude_symbol_table_d;
  }  

  // method: getSPenaltyExcludeSymbolTable
  //
  Vector<SearchSymbol>& getSPenaltyExcludeSymbolTable() {
    return spenalty_exclude_symbol_table_d;
  }
  
  // method: setContextLessSymbolTable
  //
  boolean setContextLessSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return contextless_symbol_table_d.assign(symbol_list);
  }

  // method: getContextLessSymbolTable
  //
  Vector<SearchSymbol>& getContextLessSymbolTable() {
    return contextless_symbol_table_d;
  }

  // method: setSkipSymbolTable
  //
  boolean setSkipSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return skip_symbol_table_d.assign(symbol_list);
  }

  // method: getSkipSymbolTable
  //
  Vector<SearchSymbol>& getSkipSymbolTable() {
    return skip_symbol_table_d;
  }  

  // method: setNonAdaptSymbolTable
  //
  boolean setNonAdaptSymbolTable(Vector<SearchSymbol>& symbol_list) {
    return non_adapt_symbol_table_d.assign(symbol_list);
  }  

  // method: getNonAdaptSymbolTable
  //
  Vector<SearchSymbol>& getNonAdaptSymbolTable() {
    return non_adapt_symbol_table_d;
  }
  
  // method: setContextHash
  //
  boolean setContextHash(HashTable<Context, Ulong> context_hash) {
    return context_hash_d.assign(context_hash);
  }
  
  // method: getContextHash
  //
  HashTable<Context, Ulong>& getContextHash() {
    return context_hash_d;
  }

  // method: getSymbol
  //
  boolean getSymbol(SearchSymbol& output_symbol, long index) const {
    return ( isValidSymbol(index) &&
	     output_symbol.assign(symbol_table_d(index)) );
  }

  // method: isValidSymbol
  //
  boolean isValidSymbol(long index) const {
    return ((index >= 0) && (index < symbol_table_d.length()));
  }

  // method: isNonSpeechBoundarySymbol
  //
  boolean isNonSpeechBoundarySymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    nonspeech_boundary_symbol_table_d.contains(&symbol_table_d(index)));
  }

  // method: isNonSpeechInternalSymbol
  //
  boolean isNonSpeechInternalSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    nonspeech_internal_symbol_table_d.contains(&symbol_table_d(index)));
  }  

  // method: isDummySymbol
  //
  boolean isDummySymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    dummy_symbol_table_d.contains(&symbol_table_d(index)));
  }  

  // method: isExcludeSymbol
  //
  boolean isExcludeSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    exclude_symbol_table_d.contains(&symbol_table_d(index)));
  }

  // method: isNSymbolExcludeSymbol
  //
  boolean isNSymbolExcludeSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    nsymbol_exclude_symbol_table_d.contains(&symbol_table_d(index)));
  }    

  // method: isSPenaltyExcludeSymbol
  //
  boolean isSPenaltyExcludeSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    spenalty_exclude_symbol_table_d.contains(&symbol_table_d(index)));
  }
  
  // method: isContextLessSymbol
  //
  boolean isContextLessSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    contextless_symbol_table_d.contains(&symbol_table_d(index)));
  }  

  // method: isSkipSymbol
  //
  boolean isSkipSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    skip_symbol_table_d.contains(&symbol_table_d(index)));
  }  

  // method: isNonAdaptSymbol
  //
  boolean isNonAdaptSymbol(long index) const {
    return (((index >= 0) && (index < symbol_table_d.length())) &&
	    non_adapt_symbol_table_d.contains(&symbol_table_d(index)));
  }
  
  // method: writeSymbolOccupancy
  //
  boolean writeSymbolOccupancy() const {
    return write_symbol_occupancy_d;
  }
  
  // method to lookup a graph of a context dependent model
  //
  Ulong* getSubGraphIndex(const Context& context);

  // method to map the statistical models to the search nodes
  //
  boolean connectStatisticalModels();
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

};

// include the search node class here circumvent the circular dependency
//
#ifndef ISIP_SEARCH_NODE
#include <SearchNode.h>
#endif

#ifndef ISIP_CONTEXT
#include <Context.h>
#endif

// end of include file
//
#endif
