// file: lattice.h
//
// this is the header for the lattice class
//

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

// isip include files
//
#ifndef __ISIP_INTEGRAL
#include <integral.h>
#endif

// forward declaration of classes
//
#ifndef __ISIP_LINK_LIST
#include <link_list.h>
#endif

#ifndef __ISIP_WORD
#include <word.h>
#endif

#ifndef __ISIP_LATTICE_NODE
#include <lattice_node.h>
#endif

#ifndef __ISIP_HASH_TABLE
#include <hash_table.h>
#endif

#ifndef __ISIP_LATTICE_PATH
#include <lattice_path.h>
#endif

#ifndef __ISIP_NGRAM
#include <ngram.h>
#endif

#ifndef __ISIP_SUBPATH_MATCH
#include <subpath_match.h>
#endif

// define the constants
//
#ifndef __ISIP_PROB_PRECISION
#define __ISIP_PROB_PRECISION  0.1
#endif

// Lattice: a class that is used to store the N-best word hypothesis
// in the form of a word graph
//
class Lattice {
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:
  
  // node statistics
  //
  int_4 num_arcs_d;                  // number of arcs in the lattice
  int_4 num_nodes_d;                 // number of nodes in the lattice

  // node pointers
  //
  Hash_table* lnode_d;               // hash table of lattice nodes
  Lattice_node* start_node_d;        // start node of the lattice
  
  // lattice generation information
  //
  char_1* lang_model_d;              // language model used for construction
  char_1* utterance_d;               // utterance represented by the lattice
  char_1* model_set_d;               // model set used for scoring acoustics
  char_1* name_d;                    // name of the lattice (used in
                                     // hierarchical grammars)
  Word* null_word_d;
  
  // likelihood scale factors 
  //
  float_4 lm_scale_d;                // language model scale factor
  float_4 word_penalty_d;            // word insertion penalty  
  
  //---------------------------------------------------------------------------
  //
  // public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // required methods
  //
  char_1* name_cc();
  volatile void error_handler_cc(char_1* mname, char_1* msg);
  logical_1 debug_cc(FILE* fp, char_1* message);
  int_4 size_cc();
    
  // destructors/constructors
  //
  ~Lattice();                                            // destructor
  Lattice();                                             // default constructor
  Lattice(int_4 num_nodes, int_4 num_arcs, Hash_table* lnodes);  // overloaded
  Lattice(Lattice& lattice);                             // copy constructor
  
  // methods to set generic information
  //
  logical_1 set_num_arcs_cc(int_4 num_arcs) {
    num_arcs_d = num_arcs;
    return ISIP_TRUE;
  }

  logical_1 set_num_nodes_cc(int_4 num_nodes) {
    num_nodes_d = num_nodes;
    return ISIP_TRUE;
  }
  
  logical_1 set_lang_model_cc(char_1* lang_model_name);  // language model
  logical_1 set_utterance_cc(char_1* utterance_name);    // utterance 
  logical_1 set_model_set_cc(char_1* model_set);         // model set

  logical_1 set_word_penalty_cc(float_4 word_penalty) {
    word_penalty_d = word_penalty;
    return ISIP_TRUE;
  }

  logical_1 set_lm_scale_cc(float_4 lm_scale) {
    lm_scale_d = lm_scale;
    return ISIP_TRUE;
  }
  
  logical_1 set_name_cc(char_1* name);                   // name
  
  // methods to get generic information
  //
  int_4 get_num_arcs_cc() {
    return num_arcs_d;
  }

  int_4 get_num_nodes_cc() {
    return num_nodes_d;
  }
  
  logical_1 get_lang_model_cc(char_1*& lang_model);      // language model
  logical_1 get_utterance_cc(char_1*& utterance);        // utterance 
  logical_1 get_model_set_cc(char_1*& model_set);        // model set

  float_4 get_word_penalty_cc() {
    return word_penalty_d;
  }


  float_4 get_lm_scale_cc() {
    return lm_scale_d;
  }
  
  char_1* get_name_cc() {
    return name_d;
  }

  // methods to set/get start lattice node information
  //
  logical_1 set_start_node_cc(Lattice_node* lat_node) {
    start_node_d = lat_node;
    return ISIP_TRUE;
  }
  Lattice_node* get_start_node_cc() {
    return start_node_d;
  }

  // methods to set/get lattice node hash table information
  //
  logical_1 set_lnodes_cc(Hash_table* lnodes) {
    lnode_d = lnodes;
    return ISIP_TRUE;
  }
  Hash_table* get_lnodes_cc() {
    return lnode_d;
  }
  
  // method to set/get individual lattice nodes
  //
  logical_1 set_lat_node_cc(Lattice_node* lnode);
  logical_1 get_lat_node_cc(Lattice_node* lnode, Hash_cell*& lcell);
  
  // read methods for lattice
  //
  logical_1 read_lattice_cc(FILE* fp_lattice, Hash_table* lexicon);
  logical_1 read_trans_cc(char_1* trans_str, Hash_table* lexicon);

  // write methods for the lattice
  //
  logical_1 write_lattice_cc(FILE* fp_lattice,
			     logical_1 probflag = ISIP_FALSE,
			     logical_1 prob_flag = ISIP_FALSE,
			     logical_1 allprob_flag = ISIP_FALSE);

  // method to reduce the original lattice to a more efficient format
  //
  logical_1 reduce_lattice_cc(Lattice*& new_lattice);
  
  // re-assign the node indices
  //
  logical_1 index_nodes_cc();

  // method to update the lattice lm scores using the given ngram lm
  //
  logical_1 update_scores_cc(Ngram* ngram, int_4 order);
  
  // dynamic programming based lattice error computation for the
  // utterance
  //
  logical_1 error_rate_cc(char_1*& utterance, int_4& nref, int_4& corr,
			  int_4& subs, int_4& dels, int_4& ins,
			  Hash_table* lexicon);

  // search the lattice for subpaths exactly matching a sequence of words
  //
  logical_1 find_subpaths_cc(char_1* search_words, Hash_table* lexicon, 
			     int_4& num_results, Link_list*& results);

  // merge two sets of subpath results. this function is used to remove duplicate
  // subpath results
  //
  int_4 merge_subpath_results_cc(Link_list*& results, Link_list*& merge_results);

  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // lattice building methods
  //
  logical_1 init_nodes_cc(Lattice_node** lnodes);

  // arrange the lattice nodes in a hash table in order
  //
  logical_1 lat_arrange_cc(Lattice_node**& lnodes);

  // method to break the reference transcription into a word index
  // list
  //
  Word** get_ref_words_cc(int_4& num, Hash_table* lexicon);

  // method to insert a path node in a link list
  //
  logical_1 add_path_cc(Link_list*& list, Link_node* marker,
			Lattice_path* lpath);

  // method to grow paths and compare with reference
  //
  int_4 grow_paths_cc(int_4 nref, Word** words, Link_list* holder,
		      Link_list** lists, Link_node** markers,
		      Lattice_path*& best);

  logical_1 correct_path_cc(Lattice_path* stpath, int_4 nref, Word** words,
			    Link_list* holder, Lattice_path*& best);

  logical_1 correct_subpath_cc(Lattice_path* stpath, Word** words,
			       Lattice_path*& best, int_4 nref, 
			       int_4 idx_a = (int_4)0);

  // back-track to output the best aligned path
  //
  logical_1 backtrack_cc(Lattice_path* best, Word** words, int_4 nref,
			 char_1*& utterance, int_4& corr, int_4& subs,
			 int_4& dels, int_4& ins);

  // get the likelihood score of a path
  //
  logical_1 path_likelihood_cc(Lattice_node* lnode, Lattice_path* prev_lpath,
			       float_4& score);

  // method to free memory in path lists
  //
  logical_1 free_list_cc(Link_list* list);
};

// stop of file
// 
#endif
