// file: $isip/class/search/SymbolGraph/sgrp_05.cc // version: $Id: sgrp_05.cc 9346 2003-11-23 16:35:10Z alphonso $ // // isip include files // #include "SymbolGraph.h" // method: eq // // arguments: // const SymbolGraph& obj: (input) inpt object to compare // // return: a bool8 indicating status // // this method compares the input object to this object // bool8 SymbolGraph::eq(const SymbolGraph& graph_a) const { // declare local variables // Vector in_nodes; Vector > in_symbols; Vector, Float, Float> > in_arcs; Vector this_nodes; Vector > this_symbols; Vector, Float, Float> > this_arcs; // compare the scale factors // if (!scale_d.eq(graph_a.scale_d)) { return false; } // compare the symbol penalties // if (!penalty_d.eq(graph_a.penalty_d)) { return false; } // extract the structure of the current list // const_cast(this)->get(this_nodes, this_symbols, this_arcs); // extract the structure of the input list // const_cast(graph_a).get(in_nodes, in_symbols, in_arcs); // compare the nodes lists for quality // if (!this_nodes.eq(in_nodes)) { return false; } // compare the symbols lists for quality // if (!this_symbols.eq(in_symbols)) { return false; } // compare the arcs lists for quality // if (this_arcs.length() != in_arcs.length()) { return false; } for (int32 i=0; i < this_arcs.length(); i++) { // compare the start index // if (!this_arcs(i).first().first().eq(in_arcs(i).first().first())) { return false; } // compare the stop index // if (!this_arcs(i).first().second().eq(in_arcs(i).first().second())) { return false; } // compare the language model score // if (!Integral::almostEqual((float64)this_arcs(i).second(), (float64)in_arcs(i).second())) { return false; } // compare the acoustic model score // if (!Integral::almostEqual((float64)this_arcs(i).third(), (float64)in_arcs(i).third())) { return false; } } // we have reached this far so the graphs have to be equal // return true; } // method: convert // // arguments: // SearchLevel& slevel: (input) search level // DiGraph& digraph: (output) digraph representation // // return: a bool8 indicating status // // this method converts the symbol graph to a digraph representation // bool8 SymbolGraph::convert(SearchLevel& level_a, DiGraph& digraph_a) { // declare local variables // SearchSymbol input_symbol; SearchNode search_node; Queue queue; HashKey hashkey; HashTable, GraphVertex > hashtable; SymbolGraphNode* child_node = (SymbolGraphNode*)NULL; SymbolGraphNode* parent_node = (SymbolGraphNode*)NULL; GraphArc* graph_arc = (GraphArc*)NULL; GraphVertex* child_vertex = (GraphVertex*)NULL; GraphVertex* parent_vertex = (GraphVertex*)NULL; // do we need to do anything? // if ((int32)num_nodes_d < 1) { return true; } // set the allocation mode // queue.setAllocationMode(DstrBase::USER); hashtable.setAllocationMode(DstrBase::USER); // insert the start node into the queue // queue.add(&start_node_d); hashkey.assign(&start_node_d); hashtable.insert(hashkey, digraph_a.getStart()); while (!queue.isEmpty()) { // retrieve the symbol graph start node // parent_node = queue.remove(); if (parent_node == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"convertSymbolGraph", Error::ARG, __FILE__, __LINE__); } // retrieve the digraph start vertex // hashkey.assign(parent_node); if ((parent_vertex = hashtable.get(hashkey)) == (GraphVertex*)NULL) { return Error::handle(name(), L"convertSymbolGraph", Error::ARG, __FILE__, __LINE__); } // get the next child nodes and scores corresponding to the parent // SingleLinkedList& next_nodes = parent_node->getNextNodesList(); SingleLinkedList& lm_scores = parent_node->getLMScoresList(); SingleLinkedList& ac_scores = parent_node->getScoresList(); // loop over all nodes adjacent to the start node // lm_scores.gotoFirst(); ac_scores.gotoFirst(); for (bool8 more = next_nodes.gotoFirst(); more; more = next_nodes.gotoNext()) { // retrieve the next child node // child_node = next_nodes.getCurr(); if (child_node == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"convertSymbolGraph", Error::ARG, __FILE__, __LINE__); } // get the language model and acoustic model scores // Float* val = (Float*)NULL; if ((val = lm_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"convertSymbolGraph", Error::ARG, __FILE__, __LINE__); } float32 lm_score = (float32)(*val); val = (Float*)NULL; if ((val = ac_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"convertSymbolGraph", Error::ARG, __FILE__, __LINE__); } float32 ac_score = (float32)(*val); // when the child node is not the term node // if (child_node != &term_node_d) { // create the corresponding child vertex // child_node->getSymbol(input_symbol); hashkey.assign(child_node); if ((child_vertex = hashtable.get(hashkey)) == (GraphVertex*)NULL) { search_node.setSearchLevel(&level_a); search_node.setSymbol(input_symbol); child_vertex = digraph_a.insertVertex(&search_node); hashtable.insert(hashkey, child_vertex); // add the child node to the queue // queue.add(child_node); } // insert the corresponding transition in the digraph // digraph_a.insertArc(parent_vertex, child_vertex, graph_arc, false, (float32)0.0); // set the auxiliary arc weights // graph_arc->setLanguageWeight((float64)lm_score); graph_arc->setAcousticWeight((float64)ac_score); // print debugging information // if (debug_level_d >= Integral::DETAILED) { String src_str; parent_node->getSymbol(src_str); String dst_str; child_node->getSymbol(dst_str); String output(L"\n-> src: "); output.concat(parent_vertex); output.concat(L" ["); output.concat(src_str); output.concat(L"], dst: "); output.concat(child_vertex); output.concat(L" ["); output.concat(dst_str); output.concat(L"], lm_score: "); output.concat(lm_score); output.concat(L", ac_score: "); output.concat(ac_score); Console::put(output); } } // when the child node is the term node // else { // create the corresponding child vertex // child_vertex = digraph_a.getTerm(); if (!parent_vertex->isAdjacent(child_vertex)) { // insert the corresponding transition in the digraph // digraph_a.insertArc(parent_vertex, child_vertex, graph_arc, false, (float32)0.0); graph_arc->setLanguageWeight((float64)lm_score); graph_arc->setAcousticWeight((float64)ac_score); // print debugging information // if (debug_level_d >= Integral::DETAILED) { String src_str; parent_node->getSymbol(src_str); String dst_str; child_node->getSymbol(dst_str); String output(L"\n-> src: "); output.concat(parent_vertex); output.concat(L" ["); output.concat(src_str); output.concat(L"], dst: "); output.concat(child_vertex); output.concat(L" ["); output.concat(dst_str); output.concat(L"], lm_score: "); output.concat(lm_score); output.concat(L", ac_score: "); output.concat(ac_score); Console::put(output); } } } // move to the next child // lm_scores.gotoNext(); ac_scores.gotoNext(); } } // exit gracefully // return true; } // method: get // // arguments: // Vector& nodes: (output) graph nodes // Vector >& symbols: (output) graph symbols // Vector, Float, Float> >& arcs: (output) graph arcs // // return: a bool8 indicating status // // this method retrieves the internal structure of the graph // bool8 SymbolGraph::get(Vector& nodes_a, Vector >& symbols_a, Vector, Float, Float> >& arcs_a) { // declare local variables // int32 num_nodes = 0; int32 num_arcs = 0; int32 start_index = 0; int32 stop_index = 0; int32 frame_index = 0; String symbol; Long node_index; HashKey hashkey; HashTable, Long> node_lookup; // clear the datastructures to begin with // nodes_a.clear(); symbols_a.clear(); arcs_a.clear(); // set the default capacity // nodes_a.setCapacity((int32)num_nodes_d + 2); arcs_a.setCapacity((int32)num_arcs_d + 2); symbols_a.setCapacity((int32)num_arcs_d + 2); // update the vector length // if (nodes_a.length() < num_nodes + 1) { nodes_a.setLength(num_nodes + 1); } // set up the start node // node_index = 0; frame_index = 0; hashkey.assign(&start_node_d); node_lookup.insert(hashkey, &node_index); nodes_a(num_nodes++) = frame_index; node_index++; // loop over all nodes in the graph and set up the nodes vector // for (bool8 more = nodes_d.gotoFirst(); more; more = nodes_d.gotoNext()) { // get the current parent node // SymbolGraphNode* node = nodes_d.getCurr(); if (node == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } // get and set the symbol and frame of the current node // frame_index = node->getFrameIndex(); // update the vector length // if (nodes_a.length() < num_nodes + 1) { nodes_a.setLength(num_nodes + 1); } hashkey.assign(node); node_lookup.insert(hashkey, &node_index); nodes_a(num_nodes++) = frame_index; node_index++; } // add the children corresponding to the start node // SingleLinkedList& next_nodes = start_node_d.getNextNodesList(); SingleLinkedList& lm_scores = start_node_d.getLMScoresList(); SingleLinkedList& ac_scores = start_node_d.getScoresList(); // loop over all children corresponding to the start node // lm_scores.gotoFirst(); ac_scores.gotoFirst(); for (bool8 more = next_nodes.gotoFirst(); more; more = next_nodes.gotoNext()) { SymbolGraphNode* child = next_nodes.getCurr(); if (child == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } // get the parent start index // start_index = 0; // get the child symbol and stop index // child->getSymbol(symbol); Long* ind = (Long*)NULL; hashkey.assign(child); if ((ind = node_lookup.get(hashkey)) == (Long*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } stop_index = (int32)(*ind); // skip the term nodes // if (child != &term_node_d) { // get the language model and acoustic model scores // Float* val = (Float*)NULL; if ((val = lm_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } float32 lm_score = (float32)(*val); val = (Float*)NULL; if ((val = ac_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } float32 ac_score = (float32)(*val); // update the vector length // if (arcs_a.length() < num_arcs + 1) { arcs_a.setLength(num_arcs + 1); symbols_a.setLength(num_arcs + 1); } symbols_a(num_arcs).first().assign(start_index); symbols_a(num_arcs).second().assign(stop_index); symbols_a(num_arcs).third().assign(symbol); arcs_a(num_arcs).first().first().assign(start_index); arcs_a(num_arcs).first().second().assign(stop_index); arcs_a(num_arcs).second().assign(ac_score); arcs_a(num_arcs).third().assign(lm_score); num_arcs++; } // move to the next child // lm_scores.gotoNext(); ac_scores.gotoNext(); } // loop over all nodes in the graph and set up the arcs vector // for (bool8 more = nodes_d.gotoFirst(); more; more = nodes_d.gotoNext()) { // get the current parent node // SymbolGraphNode* parent = nodes_d.getCurr(); if (parent == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } // get the parent start index // Long* ind = (Long*)NULL; hashkey.assign(parent); if ((ind = node_lookup.get(hashkey)) == (Long*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } start_index = (int32)(*ind); // get the next child nodes and scores corresponding to the parent // SingleLinkedList& next_nodes = parent->getNextNodesList(); SingleLinkedList& lm_scores = parent->getLMScoresList(); SingleLinkedList& ac_scores = parent->getScoresList(); // loop over all children corresponding to the parent // lm_scores.gotoFirst(); ac_scores.gotoFirst(); for (bool8 more1 = next_nodes.gotoFirst(); more1; more1 = next_nodes.gotoNext()) { SymbolGraphNode* child = next_nodes.getCurr(); if (child == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } // get the child symbol and stop index // child->getSymbol(symbol); // skip the term nodes // if (child != &term_node_d) { Long* ind = (Long*)NULL; hashkey.assign(child); if ((ind = node_lookup.get(hashkey)) == (Long*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } stop_index = (int32)(*ind); // get the language model and acoustic model scores // Float* val1 = (Float*)NULL; if ((val1 = lm_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } float32 lm_score = (float32)(*val1); val1 = (Float*)NULL; if ((val1 = ac_scores.getCurr()) == (Float*)NULL) { return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__); } float32 ac_score = (float32)(*val1); // update the vector length // if (arcs_a.length() < num_arcs + 1) { arcs_a.setLength(num_arcs + 1); symbols_a.setLength(num_arcs + 1); } symbols_a(num_arcs).first().assign(start_index); symbols_a(num_arcs).second().assign(stop_index); symbols_a(num_arcs).third().assign(symbol); arcs_a(num_arcs).first().first().assign(start_index); arcs_a(num_arcs).first().second().assign(stop_index); arcs_a(num_arcs).second().assign(ac_score); arcs_a(num_arcs).third().assign(lm_score); num_arcs++; } // move to the next child // lm_scores.gotoNext(); ac_scores.gotoNext(); } } // 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 SymbolGraph::clear(Integral::CMODE cmode_a) { // declare local variables // SymbolGraphNode* node = (SymbolGraphNode*)NULL; // reset the member data // scale_d = DEF_SCALE; penalty_d = DEF_PENALTY; order_d = DEF_ORDER; format_d = DEF_FORMAT; // clear the start node contents // start_node_d.clear(cmode_a); // clear the term node contents // term_node_d.clear(cmode_a); // removes the nodes from the graph // while (!nodes_d.isEmpty()) { nodes_d.removeFirst(node); if (node != (SymbolGraphNode*)NULL) { delete node; node = (SymbolGraphNode*)NULL; } } // exit gracefully // return true; } // method: set // // arguments: // Vector& nodes: (output) graph nodes // Vector >& symbols: (output) graph symbols // Vector, Float, Float> >& arcs: (output) graph arcs // // return: a bool8 indicating status // // this method sets the internal structure of the graph // bool8 SymbolGraph::set(Vector& nodes_a, Vector >& symbols_a, Vector, Float, Float> >& arcs_a) { // declare local variables // int32 num_arcs = 0; int32 num_nodes = 0; int32 start_index = 0; int32 stop_index = 0; int32 frame_index = 0; float32 ac_score = 0.0; float32 lm_score = 0.0; String symbol; SymbolGraphNode** nodes = (SymbolGraphNode**)NULL; SymbolGraphNode* start_node = (SymbolGraphNode*)NULL; SymbolGraphNode* stop_node = (SymbolGraphNode*)NULL; // get the number of nodes and arcs // num_arcs = arcs_a.length(); num_nodes = nodes_a.length(); if (num_nodes < 1) { return false; } // allocate memory // nodes = new SymbolGraphNode*[num_nodes]; // set the start node -- assumed to be at index zero // nodes[0] = &start_node_d; nodes[0]->setParentGraph(this); // loop over all nodes and insert them into the graph // for (int32 i = 1; i < num_nodes; i++) { // get the frame index corresponding to the node // frame_index = (int32)nodes_a(i); // insert the node in the graph // nodes[i] = insertNode(frame_index); nodes[i]->setParentGraph(this); } // loop over all arcs and insert them into the graph // for (int32 i = 0; i < num_arcs; i++) { // get the start and stop indices // start_index = (int32)arcs_a(i).first().first(); if ((start_index < 0) || (start_index > num_nodes - 1)) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } stop_index = (int32)arcs_a(i).first().second(); if ((stop_index < 0) || (stop_index > num_nodes - 1)) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } // get the start and stop nodes // start_node = nodes[start_index]; if (start_node == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } stop_node = nodes[stop_index]; if (stop_node == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } // get the stop symbol // int32 pind = (int32)symbols_a(i).first(); int32 cind = (int32)symbols_a(i).second(); symbol.assign(symbols_a(i).third()); // the symbol indices must match // if ((pind != start_index) || (cind != stop_index)) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } stop_node->setSymbol(symbol); // get the language model and acoustic model scores // ac_score = (float32)arcs_a(i).second(); lm_score = (float32)arcs_a(i).third(); // insert the transition in the graph // if (!start_node->insertNextNode(stop_node, lm_score, ac_score)) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } } // loop over all nodes in the graph // for (int32 i = 0; i < num_nodes; i++) { // when there are no outgoing transitions // if (nodes[i]->getOutgoing() == 0) { // connect the node to the term node // start_node = nodes[i]; stop_node = &term_node_d; // insert the transition in the graph // if (!start_node->insertNextNode(stop_node, 0.0, 0.0)) { return Error::handle(name(), L"set", Error::ARG, __FILE__, __LINE__); } } } // free memory // delete [] nodes; nodes = (SymbolGraphNode**)NULL; // exit gracefully // return true; } // method: compact // // arguments: // SymbolGraph& new_graph: (output) reduced graph representation // // return: a bool8 indicating status // // this method reduces the size of the symbol graph into a more compact form // bool8 SymbolGraph::compact(SymbolGraph& new_graph_a) { // do we need to do anything? // if ((int32)num_nodes_d < 1) { return true; } // initialize the nodes for the new symbol graph // SymbolGraphNode** new_lnodes = new SymbolGraphNode*[(int32)num_nodes_d + 1]; // define a map into the new symbol graph // int32* map_list = new int32[(int32)num_nodes_d + 1]; for (int32 i = 0; i < (int32)num_nodes_d + 1; i++) { map_list[i] = -1; new_lnodes[i] = (SymbolGraphNode*)NULL; } // clear the input graph before we begin // new_graph_a.clear(); // set the scale and penalty // new_graph_a.scale_d = scale_d; new_graph_a.penalty_d = penalty_d; // set the order and format // new_graph_a.format_d = format_d; new_graph_a.order_d = order_d; // place the start node at the first position in the new lattice // array, update the map and increment count // new_lnodes[0] = new_graph_a.getStart(); map_list[start_node_d.getNodeIndex()] = 0; // link all descendants of the lattice node // new_lnodes[0]->insertNode(&start_node_d, new_lnodes, map_list); // free allocated memory // delete [] map_list; delete [] new_lnodes; // exit gracefully // return true; } // method: prune // // arguments: none // // return: a bool8 indicating status // // this method prunes the symbol graph removing all nodes that are // not referenced // bool8 SymbolGraph::prune() { // declare local variables // SymbolGraphNode* node = (SymbolGraphNode*)NULL; // loop over all nodes in the list // bool8 more = nodes_d.gotoFirst(); while (more) { node = nodes_d.getCurr(); // remove the node if necessary // if (node->getRefCount() < 1) { if (!removeNode(node)) { return Error::handle(name(), L"prune", Error::ARG, __FILE__, __LINE__); } more = nodes_d.gotoFirst(); } else { more = nodes_d.gotoNext(); } } // exit gracefully // return true; } // method: insertNode // // arguments: // int32 frame: (input) frame index of the node // const String& symbol: (input) symbol index of the node // // return: a bool8 indicating status // // this method insert a new node in the symbol graph with the input // frame and symbol index // SymbolGraphNode* SymbolGraph::insertNode(int32 frame_a, const String& symbol_a) { // declear local variables // SymbolGraphNode* new_node = (SymbolGraphNode*)NULL; // create the new node to be inserted in the graph // new_node = new SymbolGraphNode(frame_a, symbol_a); // set the parent graph to be this // new_node->setParentGraph(this); // append the newly created object to the end of the list // nodes_d.insertLast(new_node); // increment the node counter // num_nodes_d++; // set the node index // new_node->setNodeIndex(num_nodes_d); // return a reference to the object just created // return new_node; } // method: removeNode // // arguments: // SymbolGraphNode* obj: (input) node to be removed from the graph // // return: a bool8 indicating status // // this method the specified node from the graph // bool8 SymbolGraph::removeNode(SymbolGraphNode* obj_a) { // declare local variables // SymbolGraphNode* ptr = (SymbolGraphNode*)NULL; // error checking // if (obj_a == (SymbolGraphNode*)NULL) { return Error::handle(name(), L"removeNode", Error::ARG, __FILE__, __LINE__); } // are any other nodes referencing this node? // if (obj_a->getRefCount() > 0) { return Error::handle(name(), L"removeNode", Error::ARG, __FILE__, __LINE__); } // find the current object in the list // if (nodes_d.find(obj_a)) { // decrement the node count // num_nodes_d--; // remove the object from the list // nodes_d.remove(ptr); // pointers should match // if (ptr != obj_a) { return Error::handle(name(), L"removeNode", Error::ARG, __FILE__, __LINE__); } // loop over all nodes in the previous list and decrement their reference // counts // SingleLinkedList& prev_list = obj_a->getPrevNodesList(); for (bool8 more = prev_list.gotoFirst(); more; more = prev_list.gotoNext()) { // decrement the arc count // num_arcs_d--; // decrement the previous nodes ref count // prev_list.getCurr()->decrementRefCount(); } // delete the object // delete obj_a; } // exit gracefully // return true; }