// file: $isip/util/speech/isip_model_converter/imc_lat_1.cc
// version: $Id: imc_lat_1.cc 8977 2003-01-12 06:37:52Z jelinek $
//
// isip include files
//
#include "isip_model_converter.h"

// method: create_loop_grammar_cc
//
// arguments:
//  String& exclude_filename : (input) file containing models to exclude
//  HashTable<String, Ulong>& lex_hash : (input) lexicon
//  Vector<DiGraph<Ulong> >& wrd_graph_a : (output) loop grammar
//
// return: a logical flag to indicate success
//
// this method creates a loop grammar containing all the words from
// the lexicon, just the words in exclude file are excluded
//
boolean create_loop_grammar_cc(String& exclude_filename_a,
			       HashTable<String, Ulong>& lex_hash_a,
			       Vector<DiGraph<Ulong> >& wrd_graph_a) {

  // vector containing true or false value for each word in lexicon.
  // if word is to be excluded from loop grammar, corresponding
  // element of this vector is set to true
  //
  Vector<Boolean> is_word_excluded(lex_hash_a.getNumItems());
  is_word_excluded.setRange(0, lex_hash_a.getNumItems(), false);

  // open the file with words that should be excluded from lexicon
  //
  File exclude_file;
  if (!exclude_file.open(exclude_filename_a)) {
    String out(L"error opening");
    out.concat(exclude_filename_a);
    Console::put(out);
    Integral::exit();
  }

  // read words from a file and note them to be excluded
  //
  String line;
  while(exclude_file.get(line)) {
    line.trim();
    line.debug(L"line:");
    if (!lex_hash_a.containsKey(line)) {
      String out(L"Warning: Word not in the lexicon:");
      out.concat(line);
    }
    else {
      Ulong* p_index = lex_hash_a.get(line);
      ulong index = (ulong) *(p_index);
      is_word_excluded(index) = true;
    }
  }

  // close the file
  //
  exclude_file.close();

  // get the index of !SENT_START and !SENT_END
  // set them as excluded
  //
  Ulong* temp_index = lex_hash_a.get(L"!SENT_START");
  ulong sent_start_hash_index = (ulong)(*temp_index);
  is_word_excluded(sent_start_hash_index) = true;
  long sent_start_graph_index = 0;

  temp_index = lex_hash_a.get(L"!SENT_END");
  ulong sent_end_index = (ulong)(*temp_index);
  is_word_excluded(sent_end_index) = true;
  long sent_end_graph_index = 1;

  temp_index = lex_hash_a.get(L"!DUMMY");  
  ulong dummy_index = (ulong)(*temp_index);
  is_word_excluded(dummy_index) = true;

  // count the number of excluded words
  //
  long num_excluded = 0;
  for (long i = 0; i < is_word_excluded.length(); i++) {
    if (is_word_excluded(i)) {
      num_excluded++;
    }
  }
  
  // prepare a word graph
  //
  wrd_graph_a.setLength(1);
  
  // add vertices for !SENT_START and !SENT_END
  //
  Ulong* p_ss = new Ulong(sent_start_hash_index);
  GraphVertex<Ulong>* p_vss = wrd_graph_a(0).insertVertex(p_ss);
  Ulong* p_se = new Ulong(sent_end_index);
  GraphVertex<Ulong>* p_vse = wrd_graph_a(0).insertVertex(p_se);

  // add vertices for all words that are not excluded
  //
  Ulong* p = NULL;
  for (long i = 0; i < lex_hash_a.getNumItems(); i++) {
    if (!is_word_excluded(i)) {
      p = new Ulong(i);
      wrd_graph_a(0).insertVertex(p);
    }
  }

  // add vertex for !DUMMY symbol
  //
  Ulong* p_dum = lex_hash_a.get(L"!DUMMY");
  p = new Ulong(*p_dum);
  wrd_graph_a(0).insertVertex(p);
  p = new Ulong(*p_dum);
  wrd_graph_a(0).insertVertex(p);

  // add arcs
  //
  // from start to SS
  //
  wrd_graph_a(0).insertArc(wrd_graph_a(0).getStart(), p_vss, true, 0);

  // from SS to first dummy
  //
  wrd_graph_a(0).insertArc(sent_start_graph_index,
			   lex_hash_a.getNumItems() - num_excluded + 2,
			   true, 0);

  // from first dummy to all
  //
  long j = 0;
  for (long i = 0; i < lex_hash_a.getNumItems(); i++) {
    if (!is_word_excluded(i)) {
      long start = lex_hash_a.getNumItems() - num_excluded + 2;
      long term = j + 2;
      wrd_graph_a(0).insertArc(start, term, true, 0);
      ++j;
    }
  }

  // from all to second dummy
  //
  j = 0;
  for (long i = 0; i < lex_hash_a.getNumItems(); i++) {
    if (!is_word_excluded(i)) {
      long start = j + 2;
      long term = lex_hash_a.getNumItems() - num_excluded + 3;
      wrd_graph_a(0).insertArc(start, term, true, 0);
      ++j;
    }
  }

  // from second dummy to first dummy
  //
  long start = lex_hash_a.getNumItems() - num_excluded + 3;
  long term = lex_hash_a.getNumItems() - num_excluded + 2;
  wrd_graph_a(0).insertArc(start, term, true, 0);

  // from second dummy to SE
  //
  wrd_graph_a(0).insertArc(lex_hash_a.getNumItems() - num_excluded + 3,
			   sent_end_graph_index, true, 0);

  // from SE to term
  wrd_graph_a(0).insertArc(p_vse, wrd_graph_a(0).getTerm(), true, 0);

  // from all to dummy
  //
  return true;
}

