// file: tr_lat_comp_0.cc
//

// isip include files
//
#include "train_lattice.h"
#include "train_lattice_constants.h"

// method: reduce_Train_Lattice_cc
//
// arguments:
//  Train_Lattice*& new_lat: (output) the new compact reduced Train_Lattice 
//
// return: a logical_1 indicating status
//
// this method reduces the Train_Lattice to a compact Train_Lattice
//
logical_1 Train_Lattice::reduce_lattice_cc(Train_Lattice*& new_lat_a) {
  
  // define some local variables
  //
  Train_Lattice_node* temp_node;
  int_4 node_count = (int_4)0;

  // memory manager
  //
  Train_Memory_manager* manager = Train_Link_list::get_manager_cc();
  
  // initialize the Train_Lattice nodes of the new Train_Lattice to the size of
  // the original Train_Lattice
  //
  Train_Lattice_node** new_lnodes = new Train_Lattice_node*[num_nodes_d];
  
  // define a map into the new Train_Lattice from each node in the original
  // Train_Lattice
  //
  int_4* map_list = new int_4[num_nodes_d];
  for (int_4 i = 0; i < num_nodes_d; i++) {
    map_list[i] = (int_4)-1;
  }
  
  // create the new Train_Lattice
  //
  if (new_lat_a != (Train_Lattice*)NULL) {
    delete new_lat_a;
    new_lat_a = (Train_Lattice*)NULL;
  }
  new_lat_a = new Train_Lattice();
  
  // set some Train_Lattice parameters
  //
  new_lat_a->lm_scale_d = lm_scale_d;
  new_lat_a->word_penalty_d = word_penalty_d;

  // copy the character strings
  //
  if (lang_model_d != (unsigned char*)NULL) {
    new_lat_a->set_lang_model_cc(lang_model_d);
  }
  if (utterance_d != (unsigned char*)NULL) {
    new_lat_a->set_utterance_cc(utterance_d);
  }
  if (model_set_d != (unsigned char*)NULL) { 
    new_lat_a->set_model_set_cc(model_set_d);
  }

  // set the start node of the new Train_Lattice to be the same as the start
  // node of the original Train_Lattice
  //
  Train_Lattice_node* new_lstart = manager->new_lat_cc();
  new_lstart->set_word_cc(start_node_d->get_word_cc());
  new_lat_a->start_node_d = new_lstart;
  
  // place the start node at the first position in the new Train_Lattice
  // array, update the map and increment count
  //
  new_lnodes[0] = new_lstart;
  map_list[start_node_d->get_node_index_cc()] = (int_4)0;
  node_count++;
  
  // get list of possible next Train_Words from the Train_Lattice node
  //
  Train_Link_list* next_list = start_node_d->get_next_nodes_cc();
  float_8* lscore = start_node_d->get_lm_scores_cc();
  float_8* ascore = start_node_d->get_ac_scores_cc();

  int_4 lcount = (int_4)0;
  float_8 acscore = (float_8)0;
  float_8 lmscore = (float_8)0;
  
  // loop through all the next Train_Words
  //
  for (Train_Link_node* node = next_list->get_head_cc();
       node != (Train_Link_node*)NULL; node = node->get_next_cc()) {
    
    // if no lm scores found in the original Train_Lattice
    //
    if (lscore == (float_8*)NULL) {
      lmscore = 0;
    }
    else {
      lmscore = lscore[lcount];
    }

    // if no acoustic scores found in the original Train_Lattice
    //
    if (ascore == (float_8*)NULL) {
      acscore = 0;
    }
    else {
      acscore = ascore[lcount];
    }

    // get the Train_Lattice node
    //
    temp_node = (Train_Lattice_node*)(node->get_item_cc());
    
    // add a corresponding node to the reduced Train_Lattice
    //
    new_lstart->add_node_cc(temp_node, lmscore, acscore,
			    new_lnodes, map_list, node_count);
    
    // increment count
    //
    lcount++;
  }

  // set the number of nodes in the Train_Lattice
  //
  new_lat_a->num_nodes_d = node_count;

  // hash the nodes for the reduced Train_Lattice
  //
  for (int_4 i = 0; i < node_count; i++) {
    new_lat_a->set_lat_node_cc(new_lnodes[i]);
  }
  
  // clean up memory
  //
  delete [] new_lnodes;
  delete map_list;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
