// file: ht_prune_1.cc
//

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

// method: trace_prune_cc
//
// arguments:
//  Train_Link_list** trace_list : (input) the trace linked list
//  Train_Link_node** marker : (input) the trace position marker
//  int_4* active : (input) list of active units
//  int_4 num_act : (input) number of active units
//  float_8 beam : (input) the pruning beam threshold
//  int_4 level : (input) the trace level
//  int_4& ndel : (output) the number of traces deleted
//
// return: a logical_1 to indicate status
//
// this method checks all active traces and removes those that are
// below the pruning beam width
//
logical_1 trace_prune_cc(Train_Link_list** trace_list_a, Train_Link_node** marker_a,
			 int_4* active_a, int_4 num_act_a, float_8 beam_a,
			 int_4 level_a, int_4& ndel_a) {

  // dummy variables
  //
  float_8 score = HT_DEFAULT_SCORE;
  Train_Trace* tr = (Train_Trace*)NULL;
  Train_Link_node* nd = (Train_Link_node*)NULL;
  Train_Link_node* node = (Train_Link_node*)NULL;

  Train_Lattice_node* latnode = (Train_Lattice_node*)NULL;
  Train_Lex_tree* lextree = (Train_Lex_tree*)NULL;
  
  // memory manager
  //
  Train_Memory_manager* manager = Train_Link_list::get_manager_cc();
  
  // loop over all active traces
  //
  for (int_4 nn = 0; nn < num_act_a; nn++) {

    // set the marker node
    //
    nd = marker_a[active_a[nn]];
    
    // loop over all active traces for this frame
    //
    while (nd != (Train_Link_node*)NULL) {

      // get the next node
      //
      node = nd->get_next_cc();      
      
      // get the trace in this node
      //
      tr = (Train_Trace*)(nd->get_item_cc());
      score = tr->get_score_cc();

      // compare this trace with the beam score
      //
      if (beam_a > score) {

	// mark trace for deletion
	//
	//	tr->incr_ref_path_cc((int_4)-1);
	
	// check if marker needs to be reset
	//
	if (nd == marker_a[active_a[nn]]) {
	  marker_a[active_a[nn]] = node;
	}
	
	// delete the trace
	//
	manager->delete_cc(tr);
	trace_list_a[active_a[nn]]->remove_cc(nd);
	
	// increment deletion count
	//
	ndel_a++;
      }

      // otherwise mark the lexical tree as active if this is word-level
      //
      else if (level_a == HT_WORD_LEVEL) {
	latnode = tr->get_lat_node_cc();
        lextree = latnode->get_lex_tree_cc();
	if (lextree != (Train_Lex_tree*)NULL) {
	  if (lextree->get_status_cc() == ISIP_FALSE) {
	    lextree->set_status_cc(ISIP_TRUE);
	  }
	}
      } // end else
      
      // update node pointer
      //
      nd = node;
    }
  }

  // exit gracefully
  //
  return ISIP_TRUE;
}
