//// file: $isip/class/search/LexicalTree/lex_07.cc
// version: $Id: lex_07.cc 8818 2002-11-19 22:32:57Z parihar $
//

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

// method: factorLexicalTree
//
// arguments:
// const GVLexicalNode*& start_vert_a: (input) the starting vertex 
// const HashTable<Long, Float>* & ngram_a: (input) used in ngram only
// const long history_a: (input) use in ngram only, the history for current
//                       ngram
//
// return: the max probability from the start vertext
//
// this method factor the language model probabilities on the lexical tree
//
float LexicalTree::factorLexicalTree(GVLexicalNode* lex_vert_a,
				     const HashTable<Long, Float>* ngram_a,
				     long history_a) {
  
  // algorithm for this method:
  // self-explain
  //
  // IF: algo == UNFACTORED
  //     return 0;
  // IF: algo == DI_GRAPH && impl == ALWAYS_MAX
  //     put the probability on the weight of the arc
  //
  // IF: algo == NGRAM && impl == ALWAYS_MAX
  //     the ngram probability shouldn't put on the arc, otherwise we will
  //     destroy the pronuciation probability, we just return  a
  //     value dynmically
  //     
  
  GVLexicalNode* succ_vert = (GVLexicalNode*)NULL;
  GALexicalNode* curr_arc  = (GALexicalNode*)NULL;

  boolean more_arcs = false;
  float tmp_weight;
  float max_weight = (float)Integral::MIN_LOG_VALUE;

  // IF: algo == UNFACTORED
  //
  if ( algorithm_d == UNFACTORED )
    return 0;

  // IF: algo == DI_GRAPH && impl == ALWAYS_MAX
  //
  if ( algorithm_d == DI_GRAPH && implementation_d == ALWAYS_MAX ){

    LexicalNode* curr_node = (LexicalNode*)lex_vert_a->getItem();
    
    // loop throught all successors
    //
    for ( more_arcs = lex_vert_a->gotoFirst(); more_arcs;
	  more_arcs = lex_vert_a->gotoNext() ) {

      // get current arc
      //
      curr_arc = lex_vert_a->getCurr();
      
      // get the successor
      //
      succ_vert = curr_arc->getVertex();
      LexicalNode* succ_node = (LexicalNode*)succ_vert->getItem();

      // if it is a NULL node
      //
      if (succ_node == (LexicalNode*)NULL){
	Error::handle(name(), L"factor: invalid lexical tree node",
		      Error::NULL_ARG, __FILE__,
		      __LINE__);
	return 0;
      }
      else if ( lex_vert_a->isStart() ){
	
	// get the maxium recursively
	//
	tmp_weight = factorLexicalTree(succ_vert);

	// set the weight on the arc
	//
	curr_arc->setWeight(tmp_weight);
	curr_arc->setEpsilon(false);

      }
      // if we reach the end of the pronuciation
      //
      else if ( succ_node->getSearchLevel()->getLevelIndex()
		!= curr_node->getSearchLevel()->getLevelIndex() ){

	// get the probability at the end of each pronuciation
	//
	tmp_weight = curr_arc->getWeight();
      }
      else {
	
	// get the maxium recursively
	//
	tmp_weight = factorLexicalTree(succ_vert);

	// set the weight on the arc
	//
	curr_arc->setWeight(tmp_weight);
	curr_arc->setEpsilon(false);
      }

      // set the max weight
      //
      if ( tmp_weight > max_weight )
	max_weight = tmp_weight;

    }

    // return
    //
    return max_weight;

  }
  else {

    // not implemented yet
    //
    Error::handle(name(), L"factor", Error::NOT_IMPLEM, __FILE__,
		  __LINE__);
  }
    
  // exit gracefully
  //
  return 0;
}
