// file: $isip/class/search/HierarchicalSearch/hsrch_08.cc
//

// isip include files
//
#include "HierarchicalSearch.h"

// method: clear
//
// arguments:
//  Integral::CMODE cmode: (input) clear mode
//
// return: a boolean value indicating status
//
// clear the contents of the search
//
boolean HierarchicalSearch::clear(Integral::CMODE cmode_a) {

  // clear all of the data members
  //
  features_d.clear(cmode_a);
  //h_digraph_d->clear(cmode_a);

  max_trace_scores_d.clear(cmode_a);
  max_instance_scores_d.clear(cmode_a);  

  // clear the lexical tree list
  //
  lex_tree_list_d.clear(Integral::FREE);

  // clear the trace lists
  //
  clearTraceStorage();

  // clear the instance lists
  //
  clearInstanceStorage();  

  // clear the history pool
  //
  if (history_pool_d.length() > 0) {
    history_pool_d.clear();
  }
  
  // clear the context pool
  //
  if (context_pool_d.length() > 0) {
    context_pool_d.clear();
  }

  // clear the n-symbol cache
  //
  if (nsymbol_cache_d.length() > 0) {
    nsymbol_cache_d.clear();
  }
  
  // clear the trellis before starting
  //
  if (search_mode_d == TRAIN) {
    trellis_d.clear();
  }

  // clear the trellis before starting
  //
  if (context_generation_mode_d) {
    context_hash_d.clear();
    context_list_d.clear();
  }
  
  // clear the frame number
  //
  current_frame_d = DEF_START_FRAME;
  context_level_d = DEF_CONTEXT_LEVEL;
  
  // exit gracefully
  //
  return true;
}

// method: clearTraceStorage
//
// arguments: none
//
// return: logical error status
//
// clear the trace storage
//
boolean HierarchicalSearch::clearTraceStorage() {

  // define local variables
  //
  Trace* tmp_trace;

  long num_levels = trace_lists_d.length();
  
  // use the trace_valid_hyps_d list as temporary storage
  //
  for (long i = 0; i < num_levels; i++) {
    while (!trace_lists_d(i).isEmpty()) {
      trace_lists_d(i).removeFirst(tmp_trace);
      trace_valid_hyps_d.insertLast(tmp_trace);
    }
  }

  // loop over all traces in the valid hypotheses list
  //
  while (!trace_valid_hyps_d.isEmpty()) {
    
    // remove this trace from the list. if it is not referenced, then delete it
    // 
    trace_valid_hyps_d.removeFirst(tmp_trace);

    if (tmp_trace->getRefCount() < 1) {
      Trace::deleteTrace(tmp_trace, true, true);	
    }
    else {
      trace_valid_hyps_d.insertLast(tmp_trace);
    }
  }

  // exit gracefully
  //
  return true;
}

// method: clearInstanceStorage
//
// arguments: none
//
// return: logical error status
//
// clear the instance storage
//
boolean HierarchicalSearch::clearInstanceStorage() {

  // define local variables
  //
  Instance* tmp_instance;

  long num_levels = instance_lists_d.length();
  
  // use the instance_valid_hyps_d list as temporary storage
  //
  for (long i = 0; i < num_levels; i++) {
    while (!instance_lists_d(i).isEmpty()) {
      instance_lists_d(i).removeFirst(tmp_instance);
      instance_valid_hyps_d.insertLast(tmp_instance);
    }
  }

  // loop over all instances in the valid hypotheses list
  //
  while (!instance_valid_hyps_d.isEmpty()) {
    
    // remove this instance from the list. if not referenced, then delete it
    // 
    instance_valid_hyps_d.removeFirst(tmp_instance);

    if (tmp_instance->getRefCount() < 1) {
	Instance::deleteInstance(tmp_instance, true, true);	
    }
    else {
      instance_valid_hyps_d.insertLast(tmp_instance);
    }
  }

  // exit gracefully
  //
  return true;
}

// method: clearValidHypsTrace
//
// arguments: none
//
// return: logical error status
//
// clear the traces stored in the valid hypothesis list
//
boolean HierarchicalSearch::clearValidHypsTrace() {
    
  // define local variables
  //
  Trace* tmp_trace;
  
  // use the trace_valid_hyps_d list as temporary storage
  //
  while (trace_valid_hyps_d.removeFirst(tmp_trace)) {
    if (tmp_trace != (Trace*)NULL) {
      Trace::deleteTrace(tmp_trace, true, true);
    }
  }
  
  // exit gracefully
  //
  return true;
}

// method: clearValidHypsInstance
//
// arguments: none
//
// return: logical error status
//
// clear the instances stored in the valid hypothesis list
//
boolean HierarchicalSearch::clearValidHypsInstance() {

   // define local variables
  //
  Instance* tmp_instance;
  
  // use the trace_instance_valid_hyps_d list as temporary storage
  //
  while (instance_valid_hyps_d.removeFirst(tmp_instance)) {
    if (tmp_instance != (Instance*)NULL) {
      Instance::deleteInstance(tmp_instance, true, true);
    }
  }
 
  // exit gracefully
  //
  return true;
}

// method: clearSearchNodesTraceLists
//
// arguments: none
//
// return: logical error status
//
// clear the list of traces from all the search nodes
//
boolean HierarchicalSearch::clearSearchNodesTraceLists() {
    
  // define local variables
  //
  long num_levels = h_digraph_d->length();

  // loop over all search levels
  //
  for (long i=0; i < num_levels; i++) {

    // get the subgraphs at this level
    //
    Vector<DiGraph<SearchNode> >& subgraphs =
      (*h_digraph_d)(i).getSubGraphs();

    // loop over each subgraph
    //
    long num_graphs = subgraphs.length();
    for (long j=0; j < num_graphs; j++) {

      // clear the start node traces
      //
      subgraphs(j).getStart()->getItem()->clearTraceList();

      // clear the terminal node traces
      //
      subgraphs(j).getTerm()->getItem()->clearTraceList();      
      
      // loop over the vertices in each subgraph
      //
      for (boolean more_vertices = subgraphs(j).gotoFirst();
	   more_vertices;
	   more_vertices = subgraphs(j).gotoNext()) {
	subgraphs(j).getCurr()->getItem()->clearTraceList();
      }
    }
  }
  
  // exit gracefully
  //
  return true;
}

// method: clearSearchNodesInstanceLists
//
// arguments: none
//
// return: logical error status
//
// clear the list of instance from all the search nodes
//
boolean HierarchicalSearch::clearSearchNodesInstanceLists() {
    
  // define local variables
  //
  long num_levels = h_digraph_d->length();

  // loop over all search levels
  //
  for (long i=0; i < num_levels; i++) {

    // get the subgraphs at this level
    //
    Vector<DiGraph<SearchNode> >& subgraphs =
      (*h_digraph_d)(i).getSubGraphs();

    // loop over each subgraph
    //
    long num_graphs = subgraphs.length();
    for (long j=0; j < num_graphs; j++) {

      // clear the start node traces
      //
      subgraphs(j).getStart()->getItem()->clearInstanceList();

      // clear the terminal node traces
      //
      subgraphs(j).getTerm()->getItem()->clearInstanceList();      
      
      // loop over the vertices in each subgraph
      //
      for (boolean more_vertices = subgraphs(j).gotoFirst();
	   more_vertices;
	   more_vertices = subgraphs(j).gotoNext()) {
	subgraphs(j).getCurr()->getItem()->clearInstanceList();
      }
    }
  }
  
  // exit gracefully
  //
  return true;
}
