// file: $isip/class/search/SearchLevel/slev_08.cc // version: $Id: slev_08.cc 10570 2006-05-13 23:51:06Z may $ // // isip include files // #include "SearchLevel.h" // method: convertSubgraphs // // arguments: // // return: a bool8 indicating status // // this method converts the subgraphs used by the recognizer to the // digraphs that are written to a file // Vector< DiGraph > SearchLevel::convertSubgraphs() const { // make sure the symbol table has been loaded // int32 index = 0; int32 dst_index = 0; bool8 is_eps = false; int32 num_graphs = sub_graphs_d.length(); int32 num_symbols = symbol_table_d.length(); if (num_symbols == 0) { // please load symbol table first // Error::handle(name(), L"writeSubGraphs", SearchLevel::ERR, __FILE__, __LINE__); } // declare a Vector of Graph to be written to file // Ulong tmp_item; SearchNode* snode; GraphArc* dst_arc; GraphVertex* dst_vertex; Vector< DiGraph > tmp_graphs; Vector >sub_graphs; // convert each Graph > to Graph // sub_graphs.assign(sub_graphs_d); tmp_graphs.setLength(sub_graphs.length()); for (int32 k = 0; k < num_graphs; k++) { // set the properties of graphs // int32 num_vertices = sub_graphs(k).length() + 2; tmp_graphs(k).setWeighted(sub_graphs(k).isWeighted()); // insert all vertices corresponding the current graph index // index = 0; GraphVertex* vertices[num_vertices]; GraphVertex* tmp_vertices[num_vertices]; // add the start vertices to the arrays // vertices[index] = sub_graphs(k).getStart(); tmp_vertices[index++] = tmp_graphs(k).getStart(); // add the rest of the vertices to the arrays // for (bool8 more = sub_graphs(k).gotoFirst(); more; more = sub_graphs(k).gotoNext()) { // get the current vertex // vertices[index] = const_cast* >(sub_graphs(k).getCurr()); // get the search node corresponding to the vertex // snode = vertices[index]->getItem(); // insert a vertex in the Graph for the current vertex // using the symbol ID of the vertex as the node item // tmp_item.assign(snode->getSymbolId()); tmp_vertices[index++] = tmp_graphs(k).insertVertex(&tmp_item); } // add the term vertices to the arrays // vertices[num_vertices - 1] = sub_graphs(k).getTerm(); tmp_vertices[num_vertices - 1] = tmp_graphs(k).getTerm(); // connect all vertices corresponding to the current graph index // for (int32 i = 0; i < num_vertices; i++) { bool8 arcs_remain = vertices[i]->gotoFirst(); while (arcs_remain) { // get the destination vertex // dst_arc = vertices[i]->getCurr(); dst_vertex = dst_arc->getVertex(); is_eps = dst_arc->getEpsilon(); // find the destination vertex // dst_index = -1; for (int32 j = 0; j < num_vertices; j++) { if (dst_vertex == vertices[j]) { dst_index = j; break; } } // error - when we cannot find a destination index // if (dst_index == -1) { Error::handle(name(), L"writeSubGraphs", Error::ARG, __FILE__, __LINE__); } // connect the vertices in the Graph // if (!tmp_graphs(k).insertArc(tmp_vertices[i], tmp_vertices[dst_index], is_eps, (float64)dst_arc->getWeight())) { Error::handle(name(), L"writeSubGraphs", Error::ARG, __FILE__, __LINE__); } arcs_remain = vertices[i]->gotoNext(); } } } // clear the pointers in the copy of sub_graphs_d so that data // of sub_graphs_d doesn't get deleted when method finishes // sub_graphs.setLength(0, true); // return the new digraphs // return tmp_graphs; } // method: convertContexts // // arguments: // //return: a bool8 value indicating status // bool8 SearchLevel::convertContexts() { // make sure the symbol table has been read // int32 num_symbols = symbol_table_d.length(); if (num_symbols < 1) { return Error::handle(name(), L"readContextMapping", Error::ARG, __FILE__, __LINE__); } // when there is a context mapping table at this level // if (context_map_d.length() > 0) { SearchSymbol start_symbol; SearchSymbol term_symbol; start_symbol.assign(SearchSymbol::NO_LEFT_CONTEXT); term_symbol.assign(SearchSymbol::NO_RIGHT_CONTEXT); // add start and terminal search symbol to the symbol table // if (!symbol_table_d.contains(&start_symbol)) { symbol_table_d.concat(start_symbol); } if (!symbol_table_d.contains(&term_symbol)) { symbol_table_d.concat(term_symbol); } // set up start and terminal search node for each subgraph // for (int32 i = 0; i < sub_graphs_d.length(); i++) { // start vertex // SearchNode* snode_p = new SearchNode(); snode_p->setSearchLevel(this); snode_p->setSymbol(SearchSymbol::NO_LEFT_CONTEXT); sub_graphs_d(i).getStart()->setItem(snode_p); // terminal vertex // snode_p = new SearchNode(); snode_p->setSearchLevel(this); snode_p->setSymbol(SearchSymbol::NO_RIGHT_CONTEXT); sub_graphs_d(i).getTerm()->setItem(snode_p); } // insert all context pairs into the context mapping hash table // int32 total_context_length = left_context_d + right_context_d + 1; // check the context length // if (context_map_d.length() > 0 ) { if (context_map_d(0).getContext().length() != total_context_length) { total_context_length = context_map_d(0).getContext().length(); } } Context context(total_context_length); // loop over all context pairs // for (int32 i = 0; i < context_map_d.length(); i++) { // loop over the symbols in the context // for (int32 j = 0; j < total_context_length; j++) { SearchSymbol ss(context_map_d(i).getContext()(j)); int32 symbol_id = getSymbolIndex(ss); // check whether the symbol is valid // if (symbol_id == -1) { ss.debug(L"symbol"); return Error::handle(name(), L"readContextMapping", Error::ARG, __FILE__, __LINE__); } else { context.assignAndAdvance(symbol_id); } } // insert a context specification into the hash table // Ulong index = context_map_d(i).getContextIndex(); // check if the context is already in the table // Ulong* existing_index = context_hash_d.get(context); // if this context is not in the table yet, insert it // if (existing_index == NULL) { context_hash_d.insert(context, &index); } // if the context is already in the table, then check whether // the index of the model is the same as the one from table // else { // if indices are different, explain conflict and return error // if (!existing_index->eq(index)) { context.debug(L"Context:"); String out; out.concat(L" is already in context mapping table with the index: "); out.concat(*existing_index); out.concat(L"\n while new index is: "); out.concat(index); Console::put(out); return Error::handle(name(), L"readContextMapping", Error::ARG, __FILE__, __LINE__); } // otherwise indices are not conflicting, just print a warning // else { context.debug(L"Warning: This context is already in the table:"); } } } // output the debugging information // if (debug_level_d >= Integral::ALL) { context_hash_d.debug(L"context hash table:"); } } // when there is NO context mapping table at this level // else { // symbols will be mapped to the model with the same index at lower level // Context dummy(1); for (ulong i = 0; i < (ulong)num_symbols; i++) { Ulong i_l(i); dummy.assignAndAdvance(i_l); // check if the context is already in the table // Ulong* existing_index = context_hash_d.get(dummy); // if this context is not in the table yet, insert it // if (existing_index == NULL) { context_hash_d.insert(dummy, &i_l); } } if (debug_level_d >= Integral::ALL) { context_hash_d.debug(L"dummy context hash table:"); } } // exit gracefully // return true; } // method: convertDigraphs // // arguments: // //return: a bool8 value indicating status // // this method converts the digraphs in tmp_graphs_d to the subgraphs // used by the recognizer // bool8 SearchLevel::convertDigraphs() { // define the initial symbol index // int32 symbol_index = -1; // clear the current subgraphs // sub_graphs_d.clear(Integral::RELEASE); // define the number of symbols in the symbol table // int32 num_symbols = symbol_table_d.length(); // variable for graphs conversion // int32 num_vertices; GraphVertex** snode_vert = (GraphVertex**)NULL; SearchNode** snode = (SearchNode**)NULL; // set the number of sub graphs and allocation mode // int32 num_graphs = tmp_graphs_d.length(); setNumSubGraphs(num_graphs); // convert each Graph to Graph > // for (int32 k = 0; k < num_graphs; k++) { // get the number of vertices from the input graph // num_vertices = tmp_graphs_d(k).length() + 2; // declare a graph of SearchNode and a local holder of those temporary // GraphVertex // snode_vert = new GraphVertex*[num_vertices]; snode = new SearchNode*[num_vertices]; GraphVertex* tmp_vert[num_vertices]; // set the properties of graphs // sub_graphs_d(k).setWeighted(tmp_graphs_d(k).isWeighted()); // index all the vertices so that they can be referenced easily // tmp_vert[0] = tmp_graphs_d(k).getStart(); // loop through the list of vertices and index them // tmp_graphs_d(k).gotoFirst(); for (int32 i = 1; i < num_vertices - 1; i++) { tmp_vert[i] = const_cast* >(tmp_graphs_d(k).getCurr()); tmp_graphs_d(k).gotoNext(); } // the last vertex is the terminal node // tmp_vert[num_vertices - 1] = tmp_graphs_d(k).getTerm(); // create a list of SearchNode Vertices // set the items properly // snode_vert[0] = sub_graphs_d(k).getStart(); snode_vert[num_vertices - 1] = sub_graphs_d(k).getTerm(); for (int32 i = 1; i < num_vertices - 1; i++) { // set its item // Ulong* tmp_item = tmp_vert[i]->getItem(); snode[i] = new SearchNode(); snode[i]->setSearchLevel(this); symbol_index = (int32)(*tmp_item); // check if this index is in the range of symbols // if (symbol_index < 0 || symbol_index >= num_symbols ) { return Error::handle(name(), L"readSubGraphs:: invalid symbol index", SearchLevel::ERR, __FILE__, __LINE__); } snode[i]->setSymbolId(symbol_index); } // add the vertices to the graph // for (int32 i = 1; i < num_vertices - 1; i++) { snode_vert[i] = sub_graphs_d(k).insertVertex(snode[i]); } // connect the vertices with arcs to complete the graph // for (int32 i = 0; i < num_vertices; i++) { // get the vertex // GraphVertex* tmp_start_vert = tmp_vert[i]; // get the list of arcs for this vertex // bool8 arcs_remain = tmp_start_vert->gotoFirst(); while (arcs_remain) { // declare temporary arcs and vertices // int32 dest_index = -1; GraphArc* tmp_arc = tmp_start_vert->getCurr(); GraphVertex* dest_vertex = tmp_arc->getVertex(); bool8 is_eps = tmp_arc->getEpsilon(); // find the index of the destination vertex // for (int32 j = 0; j < num_vertices; j++) { if (dest_vertex == tmp_vert[j]) { dest_index = j; break; } } if (dest_index == -1) { return Error::handle(name(), L"readSubGraphs -- Vertex not in list of Vertices", SearchLevel::ERR, __FILE__, __LINE__); } // connect the vertices in the searchnode graph // sub_graphs_d(k).insertArc(snode_vert[i], snode_vert[dest_index], is_eps, (float64)tmp_arc->getWeight()); // goto the next arc // arcs_remain = tmp_start_vert->gotoNext(); } } //finally check if the number of vertices are same in the converted graph // if (sub_graphs_d(k).length() != tmp_graphs_d(k).length()) { return Error::handle(name(), L"readSubGraphs:: different number of vertices after conversion", SearchLevel::ERR, __FILE__, __LINE__); } // clean memory created by the tmp_graphs_d // //tmp_graphs_d(k).clear(Integral::FREE); delete [] snode_vert; delete [] snode; } // end convert all the sub_graphs // exit gracefully // return true; } // method: loadNSymbolModel // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // // return: a bool8 value indicating status // // this method reads context mapping information from an Sof file // bool8 SearchLevel::loadNSymbolModel(Sof& sof_a, int32 tag_a) { // if no tag is specified, the tag should be this level number // if (tag_a == DEF_TAG) { tag_a = (int32)level_index_d; } // make sure the symbol table has been loaded // int32 num_symbols = symbol_table_d.length(); if (num_symbols < 1) { return Error::handle(name(), L"loadNSymbolModel", Error::ARG, __FILE__, __LINE__); } // setup the symbol table // Vector symbol_table(num_symbols); for (int32 i = 0; i < num_symbols; i++) { symbol_table(i).assign(symbol_table_d(i)); } // set the language model order // nsymbol_model_d.setOrder(nsymbol_order_d); // load the nsymbol model // if (!nsymbol_model_d.load(sof_a, tag_a, symbol_table)) { return Error::handle(name(), L"loadNSymbolModel", Error::ARG, __FILE__, __LINE__); } // exit gracefully // return true; } // method: storeContextMapping // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // // return: a bool8 value indicating status // // this method reads context mapping information from an Sof file // bool8 SearchLevel::storeContextMapping(Sof& sof_a, int32 tag_a) { // if no tag is specified, the tag should be this level number // if (tag_a == DEF_TAG) { tag_a = (int32)level_index_d; } // write the context map at this level // context_map_d.write(sof_a, tag_a, PARAM_CONTEXT_MAPPING); // gracefully exit // return true; } // method: loadContextMapping // // arguments: // Sof& sof: (input) sof file object // int32 tag: (input) sof object instance tag // // return: a bool8 value indicating status // // this method reads context mapping information from an Sof file // bool8 SearchLevel::loadContextMapping(Sof& sof_a, int32 tag_a) { // if no tag is specified, the tag should be this level number // if (tag_a == DEF_TAG) { tag_a = (int32)level_index_d; } // make sure the symbol table has been loaded // int32 num_symbols = symbol_table_d.length(); if (num_symbols < 1) { return Error::handle(name(), L"loadContextMapping", Error::ARG, __FILE__, __LINE__); } // read the context map at this level // context_map_d.read(sof_a, tag_a, PARAM_CONTEXT_MAPPING); // when there is a context mapping table at this level // if (context_map_d.length() > 0) { // add start and terminal search symbol to the symbol table // symbol_table_d.concat(SearchSymbol::NO_LEFT_CONTEXT); symbol_table_d.concat(SearchSymbol::NO_RIGHT_CONTEXT); // set up start and terminal search node for each subgraph // for (int32 i = 0; i < sub_graphs_d.length(); i++) { // start vertex // SearchNode* snode_p = new SearchNode(); snode_p->setSearchLevel(this); snode_p->setSymbol(SearchSymbol::NO_LEFT_CONTEXT); sub_graphs_d(i).getStart()->setItem(snode_p); // terminal vertex // snode_p = new SearchNode(); snode_p->setSearchLevel(this); snode_p->setSymbol(SearchSymbol::NO_RIGHT_CONTEXT); sub_graphs_d(i).getTerm()->setItem(snode_p); } // insert all context pairs into the context mapping hash table // int32 total_context_length = left_context_d + right_context_d + 1; // check the context length // if (context_map_d.length() > 0 ) { if (context_map_d(0).getContext().length() != total_context_length) { total_context_length = context_map_d(0).getContext().length(); } } Context context(total_context_length); // loop over all context pairs // for (int32 i = 0; i < context_map_d.length(); i++) { // loop over the symbols in the context // for (int32 j = 0; j < total_context_length; j++) { SearchSymbol ss(context_map_d(i).getContext()(j)); int32 symbol_id = getSymbolIndex(ss); // check whether the symbol is valid // if (symbol_id == -1) { ss.debug(L"symbol"); return Error::handle(name(), L"loadContextMapping", Error::ARG, __FILE__, __LINE__); } else { context.assignAndAdvance(symbol_id); } } // insert a context specification into the hash table // Ulong index = context_map_d(i).getContextIndex(); // check if the context is already in the table // Ulong* existing_index = context_hash_d.get(context); // if this context is not in the table yet, insert it // if (existing_index == NULL) { context_hash_d.insert(context, &index); } // if the context is already in the table, then check whether // the index of the model is the same as the one from table // else { // if indices are different, explain conflict and return error // if (!existing_index->eq(index)) { context.debug(L"Context:"); String out; out.concat(L" is already in context mapping table with the index: "); out.concat(*existing_index); out.concat(L"\n while new index is: "); out.concat(index); Console::put(out); return Error::handle(name(), L"loadContextMapping", Error::ARG, __FILE__, __LINE__); } // otherwise indices are not conflicting, just print a warning // else { context.debug(L"Warning: This context is already in the table:"); } } } // output the debugging information // if (debug_level_d >= Integral::ALL) { context_hash_d.debug(L"context hash table:"); } } // when there is NO context mapping table at this level // else { // symbols will be mapped to the model with the same index at lower level // Context dummy(1); for (ulong i = 0; i < (ulong)num_symbols; i++) { Ulong i_l(i); dummy.assignAndAdvance(i_l); context_hash_d.insert(dummy, &i_l); } if (debug_level_d >= Integral::ALL) { context_hash_d.debug(L"dummy context hash table:"); } } // exit gracefully // return true; } // method: getSubGraphIndex // // arguments: // const Context& context: (input) context containing symbol indices // // return: pointer to an index of the model of the input context // Ulong* SearchLevel::getSubGraphIndex(const Context& context_a) { return context_hash_d.get(context_a); }