// file: $isip/class/search/SymbolGraphNode/sgrpn_05.cc // version: $Id: sgrpn_05.cc 9373 2003-12-22 22:07:43Z alphonso $ // // isip include files // #include "SymbolGraphNode.h" // method: insertNode // // arguments: // SymbolGraphNode* node: (input) node to add to next node list // SymbolGraphNode** lnode: (input) array of symbol graph nodes // int32*& map_list: (input / output) the map from the old graph to new // // return: a bool8 indicating status // // this method adds the input node to the next list // bool8 SymbolGraphNode::insertNode(SymbolGraphNode* node_a, SymbolGraphNode** lnode_a, int32*& map_list_a) { // declare local variables // Float* val = (Float*)NULL; SymbolGraphNode* temp_node = (SymbolGraphNode*)NULL; float32 lm_score = 0.0; float32 ac_score = 0.0; // get list of possible next words from the lattice node // SingleLinkedList& next_list = node_a->getNextNodesList(); // get the corresponding transition scores // SingleLinkedList& lm_scores = node_a->getLMScoresList(); SingleLinkedList& ac_scores = node_a->getScoresList(); // loop through all the next words // lm_scores.gotoFirst(); ac_scores.gotoFirst(); for (bool8 more = next_list.gotoFirst(); more; more = next_list.gotoNext()) { // set the language and acoustic scores // if ((val = lm_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"insertNextNode", Error::ARG, __FILE__, __LINE__); } lm_score = (float32)(*val); val = (Float*)NULL; if ((val = ac_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"insertNextNode", Error::ARG, __FILE__, __LINE__); } ac_score = (float32)(*val); // get the symbol graph node // temp_node = next_list.getCurr(); // add the nodes to the new symbol graph // if (!insertNode(temp_node, lm_score, ac_score, lnode_a, map_list_a)) { return Error::handle(name(), L"insertNextNode", Error::ARG, __FILE__, __LINE__); } // move to the next transition // lm_scores.gotoNext(); ac_scores.gotoNext(); } // exit gracefully // return true; } // method: insertNode // // arguments: // SymbolGraphNode* node: (input) node to add to next node list // float32 lm_score: (input) the lm score associated with this transition // float32 ac_score: (input) the ac score associated with this transition // SymbolGraphNode** lnode: (input) array of symbol graph nodes // int32*& map_list: (input / output) the map from the old graph to new // // return: a bool8 indicating status // // this method adds the input node to the next list // bool8 SymbolGraphNode::insertNode(SymbolGraphNode* node_a, float32 lm_score_a, float32 ac_score_a, SymbolGraphNode** lnode_a, int32*& map_list_a) { // define local variables // bool8 flag = false; bool8 self_loop = false; String symbol; String next_symbol; SymbolGraphNode* term_node = (SymbolGraphNode*)NULL; SymbolGraphNode* next_node = (SymbolGraphNode*)NULL; SymbolGraphNode* nxt_nd = (SymbolGraphNode*)NULL; // special case: when the input node is a term node // term_node = node_a->getParentGraph()->getTerm(); if (node_a == term_node) { term_node = parent_graph_d->getTerm(); if (!next_nodes_d.contains(term_node)) { insertNextNode(term_node, lm_score_a, ac_score_a); } // exit gracefully // return true; } // get the node index corresponding to the input node // int32 index = node_a->node_index_d; // get the symbol to be inserted in the new symbol graph // node_a->getSymbol(symbol); // if this reduced graph node has any next nodes // if (!next_nodes_d.isEmpty()) { // loop through all the next symbols for this reduced graph node // next_nodes_d.setMark(); for (bool8 more = next_nodes_d.gotoFirst(); more; more = next_nodes_d.gotoNext()) { // get the current symbol graph node // next_node = next_nodes_d.getCurr(); // check if a node corresponding to the input word already // exists in the compact lattice // next_node->getSymbol(next_symbol); if (symbol.eq(next_symbol)) { // check if this is creating a self loop in the future // self_loop = false; // get the next nodes of the input node // SingleLinkedList& next_list = node_a->getNextNodesList(); if (!next_list.isEmpty()) { // loop over all next nodes // for (bool8 more1 = next_list.gotoFirst(); more1; more1 = next_list.gotoNext()) { // get the next nodes // nxt_nd = next_list.getCurr(); // check if this is mapped to the current next_node // if (next_node->node_index_d == map_list_a[nxt_nd->node_index_d]) { self_loop = true; break; } } // end for loop } // end if next nodes list is not null // now check if this node needs to be created or is already covered // if (self_loop == false) { // check if the input node is already covered --- if not merge // it with the current node // if (map_list_a[index] == (int32)-1) { // update the map list for mapping from old lattice to the new // one // map_list_a[index] = next_node->node_index_d; // move on to the next level of lattice nodes for the input // node // next_node->insertNode(node_a, lnode_a, map_list_a); // set the flag and quit loop // flag = true; break; } // otherwise stop processing this trail here, as these two are // the same node // else if (map_list_a[index] == next_node->node_index_d) { // set the flag and quit loop // flag = true; break; } } // end if this is no self loop } // end if word equals next_node word } // end for loop next_nodes_d.gotoMark(); } // end if next_nodes_d is not NULL // otherwise there is no lattice node at this level containing the // current word // if (flag == false) { // if the node has not been created already // if (map_list_a[index] == (int32)-1) { // create a new next node // next_node = parent_graph_d->insertNode(0, symbol); // set this as the new next node and add it to the current node // int32 node_count = next_node->getNodeIndex(); lnode_a[node_count] = next_node; map_list_a[index] = node_count; insertNextNode(next_node, lm_score_a, ac_score_a); // get list of possible next words from the lattice node // next_node->insertNode(node_a, lnode_a, map_list_a); } // otherwise the node exists and there is no need to create a new // node, just point it to the corresponding existing instance // else { // get the next node and set up the arc // next_node = lnode_a[map_list_a[index]]; insertNextNode(next_node, lm_score_a, ac_score_a); } } // exit gracefully // return true; } // method: insertNextNode // // arguments: // SymbolGraphNode*& node: (input) node to be added to the next list // float32 lm_score: (input) language model score // float32 ac_score: (input) acoustic model score // // return: a bool8 indicating status // // this method adds the input node to the next list // bool8 SymbolGraphNode::insertNextNode(SymbolGraphNode*& node_a, float32 lm_score_a, float32 ac_score_a) { // declare local variables // Float lm_score(lm_score_a); Float ac_score(ac_score_a); // verify that the current node is valid // if (node_a == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"insertNextNode", Error::ARG, __FILE__, __LINE__); } // add the node to the next nodes list // next_nodes_d.insertLast(node_a); // add the corresponding language and acoustic model scores // lm_scores_d.insertLast(&lm_score); ac_scores_d.insertLast(&ac_score); parent_graph_d->incrementArcs(); num_arcs_out_d++; // exit gracefully // return true; } // method: clear // // arguments: // Integral::CMODE cmode_a: (input) clear mode // // return: a bool8 value indicating status // // this method clears the reference to the internal data. // bool8 SymbolGraphNode::clear(Integral::CMODE cmode_a) { // clear the data members // frame_index_d = DEF_FRAME_INDEX; node_index_d = DEF_NODE_INDEX; reference_count_d = DEF_REFERENCE_COUNT; score_d = DEF_SCORE; num_arcs_in_d = DEF_IN_DEGREE; num_arcs_out_d = DEF_OUT_DEGREE; // clear the lists // symbol_d.clear(cmode_a); prev_nodes_d.clear(cmode_a); next_nodes_d.clear(cmode_a); prev_scores_d.clear(cmode_a); prevlm_scores_d.clear(cmode_a); lm_scores_d.clear(cmode_a); ac_scores_d.clear(cmode_a); // exit gracefully // return true; } // method: getScores // // arguments: // SymbolGraphNode* node: (input) destination node // float32& lm_score: (output) language model score // float32& ac_score: (output) acoustic model score // // return: a bool8 indicating status // // this method retrieves the language and acoustic mode score // bool8 SymbolGraphNode::getScores(SymbolGraphNode* node_a, float32& lm_score_a, float32& ac_score_a) { // revert to the previous positions // next_nodes_d.setMark(); lm_scores_d.setMark(); ac_scores_d.setMark(); // loop over all nodes adjacent to the this // lm_scores_d.gotoFirst(); ac_scores_d.gotoFirst(); for (bool8 more = next_nodes_d.gotoFirst(); more; more = next_nodes_d.gotoNext()) { if (next_nodes_d.getCurr() == node_a) { lm_score_a = (float32)(*lm_scores_d.getCurr()); ac_score_a = (float32)(*ac_scores_d.getCurr()); break; } lm_scores_d.gotoNext(); ac_scores_d.gotoNext(); } // revert to the previous positions // next_nodes_d.gotoMark(); lm_scores_d.gotoMark(); ac_scores_d.gotoMark(); // exit gracefully // return true; } // method: insertPrevNode // // arguments: // SymbolGraphNode*& node: (input) node to be added to the previous list // float32 score: (input) path score // int32 max_hist: (input) maximum history limit // float32 lm_score: (input) language model score // // return: a bool8 indicating status // // this method adds the input node to the previous list // bool8 SymbolGraphNode::insertPrevNode(SymbolGraphNode*& node_a, float32 score_a, int32 max_hist_a, float32 lm_score_a) { // declare local variables // float32 score = 0.0; bool8 inserted_node = false; Float ac_score(score_a); Float lm_score(lm_score_a); SymbolGraphNode* node = (SymbolGraphNode*)NULL; SymbolGraphNode* tmp_ptr = (SymbolGraphNode*)NULL; // verify that the current node is valid // if (node_a == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"insertPrevNode", Error::ARG, __FILE__, __LINE__); } // is the current node already present in the previous list? // if (prev_nodes_d.find(node_a)) { if (prev_nodes_d.getCurr() != node_a) { return Error::handle(name(), L"insertPrevNode", Error::ARG, __FILE__, __LINE__); } // update score if necessary // inserted_node = true; int32 pos = prev_nodes_d.getPosition(); prev_scores_d.gotoPosition(pos); prevlm_scores_d.gotoPosition(pos); score = (float32)(*prev_scores_d.getCurr()); if (score_a > score) { prev_scores_d.getCurr()->assign(ac_score); prevlm_scores_d.getCurr()->assign(lm_score); } } // loop over the previous list and compare // else { bool8 more_nodes = prev_nodes_d.gotoFirst() & prev_scores_d.gotoFirst() & prevlm_scores_d.gotoFirst(); while (more_nodes) { node = prev_nodes_d.getCurr(); score = (float32)(*prev_scores_d.getCurr()); // insert the input node // if (score_a > score) { inserted_node = true; prev_nodes_d.insert(node_a, true); prev_scores_d.insert(&ac_score, true); prevlm_scores_d.insert(&lm_score, true); node_a->incrementRefCount(); parent_graph_d->incrementArcs(); num_arcs_in_d++; break; } // any more nodes left? // more_nodes = prev_nodes_d.gotoNext() & prev_scores_d.gotoNext() & prevlm_scores_d.gotoNext(); } } // make sure we inserted the node // if (!inserted_node && ((int32)num_arcs_in_d < max_hist_a)) { prev_nodes_d.insertLast(node_a); prev_scores_d.insertLast(&ac_score); prevlm_scores_d.insertLast(&lm_score); node_a->incrementRefCount(); parent_graph_d->incrementArcs(); num_arcs_in_d++; } // when the length of the previous list exceeds the history limit we need // remove a node // if ((int32)num_arcs_in_d > max_hist_a) { // remove the last node in the list // prev_nodes_d.removeLast(tmp_ptr); prev_scores_d.removeLast(); prevlm_scores_d.removeLast(); tmp_ptr->decrementRefCount(); parent_graph_d->decrementArcs(); num_arcs_in_d--; } // set the best score for the symbol node // if (!prev_scores_d.isEmpty()) { score_d = (float32)(*prev_scores_d.getFirst()); } // exit gracefully // return true; }