// file: ht_prune_0.cc
//

// isip include files
//
#include "hmm_train.h"
#include "hmm_train_constants.h"

// method: token_prune_cc
//
// arguments:
//  Train_Link_list** token_list : (input) the token linked list
//  int_4* active : (input) the list of active phones
//  int_4 num_act : (input) the number of phones
//  float_8 beam_a : (input) the beam score
//  int_4*& ndel_a : (output) the number of traces deleted
//
// return: a logical_1 to indicate status
//
// this method performs beam pruning at each active token and updates
// the marker position
//
logical_1 token_prune_cc(Train_Link_list** token_list_a, int_4* active_a,
			 int_4 num_act_a, float_8 beam_a, int_4*& ndel_a) {
  
  // dummy variables
  //
  Train_Link_list* trlist = (Train_Link_list*)NULL;
  Train_Link_node* node = (Train_Link_node*)NULL;
  Train_Link_node* mark = (Train_Link_node*)NULL;
  Train_Link_node* prev_mark = (Train_Link_node*)NULL;  

  Train_Token* tok = (Train_Token*)NULL;
  Train_Trace* tr = (Train_Trace*)NULL;

  Train_Lex_tree* lextree = (Train_Lex_tree*)NULL;
  Train_Lex_node* lexnode = (Train_Lex_node*)NULL;
  
  // memory manager
  //
  Train_Memory_manager* manager = Train_Link_list::get_manager_cc();
  
  // loop over all the active phones
  //
  for (int_4 pp = 0; pp < num_act_a; pp++) {

    // make sure the token list exists
    //
    if (token_list_a[active_a[pp]] != (Train_Link_list*)NULL) {
    
      // loop over all the active tokens --- each corresponds to an
      // active state for this phone
      //
      for (Train_Link_node* tok_node = token_list_a[active_a[pp]]->get_head_cc();
	   tok_node != (Train_Link_node*)NULL; tok_node = tok_node->get_next_cc()) {
      
	// get the corresponding token
	//
	tok = (Train_Token*)(tok_node->get_item_cc());
	
	// get all the traces in this token
	//
	trlist = tok->get_trace_list_cc();

	// set previous marker to start of current traces
	//
	prev_mark = trlist->get_head_cc();
	mark = tok->get_marker_cc();
	if (mark != (Train_Link_node*)NULL) {
	  prev_mark = mark->get_next_cc();
	}
  	
	// loop over all the newly created traces
	//
	for (Train_Link_node* nd = prev_mark; nd != (Train_Link_node*)NULL; nd = node) {

	  // set the next node
	  //
	  node = nd->get_next_cc();
	  
	  // get the trace in this node
	  //
	  tr = (Train_Trace*)(nd->get_item_cc());
	  
	  // perform beam pruning if required
	  //
	  if (beam_a > tr->get_score_cc()) {
	    
	    // delete the trace
	    //
	    manager->delete_cc(tr);
	    trlist->remove_cc(nd);
	    
	    // increment deletion count
	    //
	    ndel_a[HT_STATE_LEVEL]++;
	  }
	  
	  // otherwise update the lexical tree status
	  //
	  else {
	    lexnode = tr->get_lex_node_cc();
	    lextree = (Train_Lex_tree*)(lexnode->get_tree_cc());
	    if (lextree != (Train_Lex_tree*)NULL) {
	      if (lextree->get_status_cc() == ISIP_FALSE) {
		lextree->set_status_cc(ISIP_TRUE);
	      }
	      lextree = (Train_Lex_tree*)NULL;
	    }
	  } // end else
	} // end for loop over newly created traces link nodes
      
	// set the final marker positions for this token
	//	
	prev_mark = trlist->get_head_cc();
	if (mark != (Train_Link_node*)NULL) {
	  prev_mark = mark->get_next_cc();
	}
	tok->set_prev_marker_cc(prev_mark);
	tok->set_marker_cc(trlist->get_curr_cc());
      }
    }
  } // end loop over all phones
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
