// file: $isip/class/sp/Recipe/rcp_05.cc // version: $Id: rcp_05.cc 9061 2003-04-01 02:06:52Z duncan $ // // isip include files // #include "Recipe.h" #include #include #include #include #include // method: findComponent // // arguments: // SingleLinkedList& comp: (output) the component we find // const FrontEndBase& fend: (input) the FrontEndBase we use // const String& coef_name: (input) coefficient name // // return: a bool8 value indicating status // // determine the sequence of processes to apply from the available inputs, // desired output, and graph of recipes. // bool8 Recipe::findComponent(SingleLinkedList& comp_a, const FrontEndBase& fend_a, const String& coef_name_a) { // check the arguments // if (coef_name_a.length() < 1) { return Error::handle(name(), L"findComponent", ERR, __FILE__, __LINE__); } // create an input vector // Vector inputs(1); inputs(0).assign(coef_name_a); // find the component // return findComponent(comp_a, fend_a, inputs); } // method: findComponent // // arguments: // SingleLinkedList& comp: (output) the recipe we find // const FrontEndBase& fend: (input) the FrontEndBase we use // Vector& inputs: (input) coefficients we need // // return: a bool8 value indicating status // // determine from the available inputs, desired output, and graph of // recipes a sequence of processes to apply // bool8 Recipe::findComponent(SingleLinkedList& comp_a, const FrontEndBase& fend_a, Vector& inputs_a) { // check the debug level // if (debug_level_d >= Integral::ALL) { recipe_d.debug(L"recipe"); } // set all nodes to white // recipe_d.setColor(Integral::WHITE); // visit the name of the output // for (int32 i = inputs_a.length() - 1; i >= 0; i--) { if (!reverseVisitDfs(fend_a, inputs_a(i))) { comp_a.debug(L"comp_a"); fend_a.debug(L"fend_a"); inputs_a.debug(L"inputs_a"); return Error::handle(name(), L"findComponent", ERR_NOPATH, __FILE__, __LINE__); } } // invert the color of all nodes. right now only black nodes are // needed to produce the output for the given inputs. // for (bool8 more_nodes = recipe_d.gotoFirst(); more_nodes; more_nodes = recipe_d.gotoNext()) { GraphVertex* v = (GraphVertex*)recipe_d.getCurr(); if (recipe_d.getColor(v) == Integral::BLACK) { recipe_d.setColor(v, Integral::WHITE); } else { recipe_d.setColor(v, Integral::BLACK); } } // perform a partial topological sort of the Components // return recipe_d.topologicalSort(comp_a, true); } // method: reverseVisitDfs // // arguments: // const FrontEndBase& fend: (input) the FrontEndBase we use // const String& name: (input) needed coefficient name // // return: a bool8 value indicating status: can we produce the named feature? // // determine a path back to all input names from the specified // name. mark all nodes along this path as black, mark intermeadiate // nodes as gray. this allows for a depth-first-search, though it is // backwards through the graph so less efficient. // bool8 Recipe::reverseVisitDfs(const FrontEndBase& fend_a, const String& name_a) { // if the name is an available input, of course it can be found // if (fend_a.isNameInput(name_a)) { return true; } // local variables // bool8 found = false; bool8 unavailable = false; // loop over all vertices // for (bool8 more_nodes = recipe_d.gotoFirst(); more_nodes; more_nodes = recipe_d.gotoNext()) { GraphVertex* v = (GraphVertex*)recipe_d.getCurr(); // dfs lets us skip over gray vertices // if (recipe_d.getColor(v) == Integral::GREY) { continue; } // is the output of this vertex our desired node? // if (v->getItem()->getOutputName().ne(name_a)) { continue; } // if this is a black node then it already has a path back, good news // if (recipe_d.getColor(v) == Integral::BLACK) { // make sure we don't have multiple paths // if (found) { return Error::handle(name(), L"reverseVisitDfs", ERR_MPATH, __FILE__, __LINE__); } found = true; } // if this is a white node then we should evaluate it // else { // mark the node as seen but not complete // recipe_d.setColor(v, Integral::GREY); // get the needed input names // // Vector input_names; // v->getItem()->getPreName(input_names); unavailable = false; // loop through each input // for (int32 i = 0; i < v->getItem()->getNumInputs(); i++) { if (!reverseVisitDfs(fend_a, v->getItem()->getInputName(i))) { unavailable = true; break; } } // if all paths back were available, this is a good node // if (!unavailable) { recipe_d.setColor(v, Integral::BLACK); // make sure we don't have multiple paths // if (found) { return Error::handle(name(), L"reverseVisitDfs", ERR_MPATH, __FILE__, __LINE__); } found = true; } } } // return if the path back to input was found // return found; } // method: delayComponent // // arguments: // Vector< SingleLinkedList >& dcomp: (output) delayed list // FtrBuffer& buf: (output) feature buffer // FrontEndBase& fend: (input) the FrontEndBase we use // SingleLinkedList& temp_list: (input) list to delay // // return: a bool8 value indicating status // // determine from the available inputs, desired output, and graph of // recipes a sequence of processes to apply // bool8 Recipe::delayComponent(Vector< SingleLinkedList >& dcomp_a, FtrBuffer& buf_a, FrontEndBase& fend_a, SingleLinkedList& temp_list_a) { // loop over the input list // int32 lag = 0; while (!temp_list_a.isEmpty()) { // set the length // if (lag >= dcomp_a.length()) { dcomp_a.setLength(lag + 1); } // loop over all recipes in the list: // the incremement is at the bottom of the code // for (bool8 more_nodes = temp_list_a.gotoFirst(); more_nodes; ) { // declare some temporary variables // Component* algo = temp_list_a.getCurr(); bool8 found_algo = true; bool8 found_input; Long needed_lag = 0; // get the inputs for this algorithm // int32 num_inputs = algo->getNumInputs(); // loop over all inputs for this Component // for (int32 i = 0; found_algo && (i < num_inputs); i++) { found_input = false; int32 algo_lead_pad = (int32)Integral::max(0, algo->getLeadingPad()); // if the coefficient is an input, it has no lag itself // if (fend_a.isNameInput(algo->getInputName(i)) && ((algo->getInputOffset(i) + algo_lead_pad) <= lag)) { if (debug_level_d >= Integral::DETAILED) { String str; str.assign(algo->getOutputName()); str.concat(L":"); str.concat(L"this is an input"); algo->getInputName(i).debug((unichar*)str); } found_input = true; needed_lag.max(algo->getInputOffset(i) + algo_lead_pad); continue; } // if the coefficient is not an input, determine what lag it // has. we are interested in finding the input coefficient // with the largest lag. to find the lag of the coefficient we // will loop through the vector and determine at what point // the coefficient is output (ie, a postName for a Component). // for (int32 j = 0; (!found_input) && (j <= lag); j++) { // sanity check // if (j >= dcomp_a.length()) { return Error::handle(name(), L"delayComponent", ERR, __FILE__, __LINE__); } // loop through all Components at this delay point to find if // our target coefficient is the output // for (bool8 m2 = dcomp_a(j).gotoFirst(); m2; m2 = dcomp_a(j).gotoNext()) { // create a pointer to a Component // Component* j_algo = dcomp_a(j).getCurr(); // get the output name // if (algo->getInputName(i).eq(j_algo->getOutputName()) && ((algo->getInputOffset(i) + algo_lead_pad) <= (lag - j))) { found_input = true; needed_lag.max(lag); } } } if (!found_input) { found_algo = false; } } // move algorithm from temp_list to proper position // if (found_algo) { // see if there are more nodes // if ((algo = temp_list_a.getNext()) != (Component*)NULL) { more_nodes = true; } else { more_nodes = false; } // remove the component // temp_list_a.remove(algo); if (debug_level_d >= Integral::DETAILED) { String num; num.assign(needed_lag); num.concat(L": about to add an algorithm"); num.insert(L"delayComponent", 0); algo->debug((unichar*)num); } // insert the component // dcomp_a(needed_lag).gotoLast(); algo->init(); dcomp_a(needed_lag).insert(algo); if (debug_level_d >= Integral::DETAILED) { String num; num.assign(needed_lag); num.concat(L": added algorithm"); dcomp_a(needed_lag).debug((unichar*)num); } } else { more_nodes = temp_list_a.gotoNext(); } } lag++; } // loop over all remaining components // int32 needed_size = dcomp_a.length(); for (int32 i = dcomp_a.length() - 1; i >= 0; i--) { if (dcomp_a(i).length() == 0) { needed_size--; } else { break; } } dcomp_a.setLength(needed_size); // set the output to use the full file-size // Long len = fend_a.getNumFrames(); buf_a.addOrInitLength(buf_a.getCoefName(), len + needed_size); if (debug_level_d >= Integral::ALL) { buf_a.getLength().debug(L"coef_length, step A"); } // loop over all components // for (int32 i = 0; i < needed_size; i++) { for (bool8 more = dcomp_a(i).gotoFirst(); more; more = dcomp_a(i).gotoNext()) { Component* algo = dcomp_a(i).getCurr(); int32 trailing_pad = (int32)Integral::max(algo->getTrailingPad(), 0); int32 num_inputs = algo->getNumInputs(); for (int32 j = 0; j < num_inputs; j++) { buf_a.setLengthToMax(algo->getInputName(j), needed_size + trailing_pad + 1); } } } if (debug_level_d >= Integral::ALL) { buf_a.getLength().debug(L"coef_length, step B"); } // process delays // Vector keys; buf_a.getLength().keys(keys); for (int32 i = keys.length() - 1; i >= 0; i--) { int32 delay = buf_a.getLength(keys(i)); if (debug_level_d >= Integral::ALL) { Long d(delay); d.debug((unichar*)keys(i)); } if ((delay < 0) || (delay > 999999)) { keys(i).debug(L"this has negative delay"); return Error::handle(name(), L"delayComponent", Error::ARG, __FILE__, __LINE__); } buf_a.getBuffer(keys(i))(0).setCapacity(2 * delay + 1); } if (debug_level_d >= Integral::DETAILED) { buf_a.getLength().debug(L"buf_d.length_d"); } // exit gracefully // return true; } // method: readGraph // // arguments: // Sof& sof: (input) sof file object // int32 graph_tag: (input) tag of graph // // return: a bool8 value indicating status // // this method reads in the Component graph from the input file. the // input file should contain a DiGraph for all the graph // connections, each int32 is an index to an Algorithm object in the // file. // bool8 Recipe::readGraph(Sof& sof_a, int32 graph_tag_a) { // declare local variables // DiGraph index_graph; SingleLinkedList algos(DstrBase::USER); // first read the graph that defines the connections // if (!index_graph.read(sof_a, graph_tag_a)) { return Error::handle(name(), L"readGraph", Error::READ, __FILE__, __LINE__, Error::WARNING); } // declare space to hold the graph // SingleLinkedList node_indices(DstrBase::USER); SingleLinkedList< Triple< Pair, Float, Boolean> > topo; index_graph.get(node_indices, topo); // sanity check -- the nodes should be consecutive integers // int32 count = 0; for (bool8 m = node_indices.gotoFirst(); m; m = node_indices.gotoNext()) { if (node_indices.getCurr()->ne(count++)) { return Error::handle(name(), L"readGraph", ERR, __FILE__, __LINE__); } } // bool8 values to represent if the node has parents // bool8 no_parents[count + 1]; for (int32 i = 0; i < count + 1; i++) { no_parents[i] = true; // initialization to no parents } // iterate over all vertices in the list to test if a node has parents // for (bool8 more = topo.gotoFirst(); more; more = topo.gotoNext()) { // retrieve the destination vertex position of the current arc // the node located in second place always has parents // Long dst_pos = topo.getCurr()->first().second(); no_parents[(int32)dst_pos] = false; } // provide some debug information // if (debug_level_d > Integral::BRIEF) { // declare local variables // String value; for (int32 i = 0; i < count; i++) { if (no_parents[i]) { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (**no** parent)"); Console::put(value); } else { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (parents exist)"); Console::put(value); } } Console::put(L"\n"); } // bool8 values to represent if the node has a child // bool8 no_child[count + 1]; for (int32 i = 0; i < count + 1; i++) no_child[i] = true; // initialization to no child // iterate over all vertices in the list to test if a node has a child // for (bool8 more = topo.gotoFirst(); more; more = topo.gotoNext()) { // retrieve the destination vertex position of the current arc // the node located in first place always has a child // Long dst_pos = topo.getCurr()->first().first(); no_child[(int32)dst_pos] = false; } // print out debug information // if (debug_level_d > Integral::BRIEF) { // declare local variables // String value; for (int32 i = 0; i < count; i++) { if (no_child[i]) { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (**no** child)"); Console::put(value); } else { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (children exist)"); Console::put(value); } } Console::put(L"\n"); } // count how many end points in the graph // int32 number_no_child = 0; for (int32 i = 0; i < count; i++) { if (no_child[i]) { number_no_child++; } } // now read in the Algorithms themselves -- put them into a // hashtable based on the tag number. // for (bool8 m = node_indices.gotoFirst(); m; m = node_indices.gotoNext()) { // declare a pointer to the current algorithm // int32 tag = *(node_indices.getCurr()); Algorithm algo; if (!algo.read(sof_a, tag)) { return Error::handle(name(), L"readGraph", Error::READ, __FILE__, __LINE__, Error::WARNING); } Component* recipe = new Component(); recipe->setAlgorithm(algo); algos.insertLast(recipe); } // add one node as dummy output point // Component* recipeA = new Component(); Algorithm algo; if (number_no_child == 1) { algo.setType(Algorithm::COEFFICIENT_LABEL); } else { algo.setType(Algorithm::CONNECTION); } recipeA->setAlgorithm(algo); String str(DUMMY_OUTPUT_NAME); recipeA->setOutputName(str); algos.insertLast(recipeA); // link all the end points to dummy output point // float32 delay = 0.0; for (int32 i = 0; i < count; i++) { if (no_child[i]) { Float float32_00(delay); Boolean bool_00(false); Pair pair_00(i, count); Triple< Pair, Float, Boolean> triple(pair_00, float32_00, bool_00); topo.insert(&triple); delay += 1; } } no_parents[count] = false; // now create the Component graph // recipe_d.clear(); recipe_d.setAllocationMode(DstrBase::USER); recipe_d.assign(algos, topo); // now expand the sub-graphs // while (expandSubGraphs(sof_a)); recipe_d.setAllocationMode(DstrBase::SYSTEM); algos.clear(); topo.clear(); recipe_d.get(algos, topo); // reorganize the node status after read the sub graph // count = 0; for (bool8 m = algos.gotoFirst(); m; m = algos.gotoNext()) { count++; } for (int32 i = 0; i < count; i++) { no_parents[i] = true; // initialization to no parents } // iterate over all vertices in the list to test if a node has parents // for (bool8 more = topo.gotoFirst(); more; more = topo.gotoNext()) { // retrieve the destination vertex position of the current arc // the node located in second place always has parents // Long dst_pos = topo.getCurr()->first().second(); no_parents[(int32)dst_pos] = false; } // provide some debug information // if (debug_level_d > Integral::BRIEF) { // declare local variables // String value; for (int32 i = 0; i < count; i++) { if (no_parents[i]) { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (**no** parent)"); Console::put(value); } else { value.assign(i); value.assign(L"node #"); value.concat(i); value.concat(L": (parents exist)"); Console::put(value); } } Console::put(L"\n"); } // to check if the number of input for components is correct // if (!checkInputs()) { return Error::handle(name(), L"readGraph", ERR, __FILE__, __LINE__); } // set the color // recipe_d.makeColorHash(Integral::WHITE); // search for input file type // int32 node_count = 0; String dummy_input_point; for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { Component* rcp = (Component*)(recipe_d.getCurr()->getItem()); if (no_parents[node_count] && rcp->getAlgorithm().getType() == Algorithm::COEFFICIENT_LABEL) { CoefficientLabel::TYPE ctype = rcp->getAlgorithm().getCLabelType(); if (ctype == CoefficientLabel::INPUT) { dummy_input_point.assign(rcp->getAlgorithm().getCLabelVariable()); if (dummy_input_point.length() > 0) { dummy_input_point.insert(INPUT_PREFIX, 0); } } } node_count++; } node_count = 0; // now mark all data buffers as black and set the input and output names // for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { Component* rcp = (Component*)(recipe_d.getCurr()->getItem()); if (no_parents[node_count] && rcp->getAlgorithm().getType() != Algorithm::COEFFICIENT_LABEL) { recipe_d.setColor(recipe_d.getCurr(), Integral::BLACK); if (dummy_input_point.length() > 0) { rcp->setInputName(0, dummy_input_point); } else { String str(SAMPLED_DATA_NAME); rcp->setInputName(0, str); } } if (rcp->getAlgorithm().getType() == Algorithm::COEFFICIENT_LABEL) { recipe_d.setColor(recipe_d.getCurr(), Integral::BLACK); CoefficientLabel::TYPE ctype = rcp->getAlgorithm().getCLabelType(); if (ctype != CoefficientLabel::OUTPUT) { String str(rcp->getAlgorithm().getCLabelVariable()); if (str.length() > 0) { str.insert(INPUT_PREFIX, 0); rcp->setInputName(0, str); } } if (ctype != CoefficientLabel::INPUT) { String str(rcp->getAlgorithm().getCLabelVariable()); if (str.length() > 0) { str.insert(OUTPUT_PREFIX, 0); rcp->setOutputName(str); } } } node_count++; } // loop through and move input & output names from the data buffers // for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { // if this node is black, propagate the input name forward // GraphVertex* gv = (GraphVertex*)recipe_d.getCurr(); if ((recipe_d.getColor(gv) == Integral::BLACK) && (gv->getItem()->getOutputName().length() > 0)) { String vname(gv->getItem()->getOutputName()); for (bool8 a = gv->gotoFirst(); a; a = gv->gotoNext()) { GraphArc* ga = gv->getCurr(); GraphVertex* dst = ga->getVertex(); int32 weight = (int32)ga->getWeight(); dst->getItem()->setInputName(weight, vname); } continue; } for (bool8 a = gv->gotoFirst(); a; a = gv->gotoNext()) { GraphArc* ga = gv->getCurr(); GraphVertex* dst = ga->getVertex(); // if the destination node is black, propagate the output name // backwards // if (recipe_d.getColor(dst) == Integral::BLACK) { int32 weight = (int32)ga->getWeight(); // make sure this arc has an input name // if (dst->getItem()->getNumInputs() > weight) { String vname(dst->getItem()->getInputName(weight)); // make sure the name was not empty // if (vname.length() > 0) { gv->getItem()->setOutputName(vname); } } } } } // now place dummy names on all other connections // int32 dummy_nc = 0; for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { GraphVertex* gv = (GraphVertex*)recipe_d.getCurr(); // declare local dummy name for output data // String dummy_name; dummy_name.assign(DUMMY_DATA_NAME); bool8 has_name = false; // give output name to each component // there are two cases: // if output name exists, directly using it // else assign a name to it // if (gv->getItem()->getOutputName().length() == 0) { dummy_name.concat(dummy_nc++); gv->getItem()->setOutputName(dummy_name); } else { dummy_name.assign(gv->getItem()->getOutputName()); has_name = true; } // propagate the output name as input name to components which // just follow the current component // for (bool8 a = gv->gotoFirst(); a; a = gv->gotoNext()) { GraphArc* ga = gv->getCurr(); GraphVertex* dst = ga->getVertex(); // put a dummy name on both the output of the current node and // the input of the next node // int32 weight = (int32)ga->getWeight(); if ((dst->getItem()->getNumInputs() > weight) && (dst->getItem()->getInputName(weight).length() != 0) && (dst->getItem()->getInputName(weight).ne(dummy_name))) { dst->getItem()->debug(L"dst recipe"); gv->getItem()->debug(L"cur recipe"); dummy_name.debug(L"dummy_name"); String out_value; out_value.concat(L"weight = %ld\n"); out_value.concat(weight); Console::put(out_value); return Error::handle(name(), L"readGraph", ERR, __FILE__, __LINE__); } if (!has_name) { dst->getItem()->setInputName(weight, dummy_name); } else { if ((dst->getItem()->getNumInputs() <= weight) || (dst->getItem()->getInputName(weight).ne(dummy_name))) { dst->getItem()->debug(L"recipe"); dummy_name.debug(L"dummy_name"); return Error::handle(name(), L"readGraph", ERR, __FILE__, __LINE__); } } } } // exit gracefully // return true; } // method: expandSubGraphs // // arguments: // Sof& sof: (input) open sof file // // return: whether or not any sub-graphs are expanded this pass // // loop through the vertices and expand sub-graphs // bool8 Recipe::expandSubGraphs(Sof& sof_a) { // declare a status flag // bool8 res = false; // loop over all components // for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { GraphVertex* gv = (GraphVertex*)recipe_d.getCurr(); if (gv->getItem()->getAlgorithm().getType() == Algorithm::ALGORITHM_CONTAINER) { // set the flag so we know that a sub-graph was expanded this // pass // res = true; // record the tag of the sub graph // int32 gtag = gv->getItem()->getAlgorithm().getContainerGraphTag(); // now we need to replace the container object with two // coefficient label algorithms. all of the inputs to the // container will go to the first coefficient label, so we can // quickly do this by just changing the type of the container // object to a coefficient label (this means all incomming arcs // will not need to be changed). We will then make a new // coefficient label and move all of the arcs currently // emminating from the container to the new coefficient label. // Component* rcp = new Component(); Algorithm algo; algo.setType(Algorithm::COEFFICIENT_LABEL); rcp->setAlgorithm(algo); // insert our new coefficient label into the graph // GraphVertex* src = recipe_d.insertVertex(rcp); for (bool8 a = gv->gotoFirst(); a; a = gv->gotoNext()) { GraphArc* ga = gv->getCurr(); // first add a new arc // recipe_d.insertArc(src, ga->getVertex(), ga->getEpsilon(), ga->getWeight()); // now delete the current arc // recipe_d.removeArc(gv, ga->getVertex()); } // change the container object to a coefficient label // gv->getItem()->setAlgorithm(algo); // now read in the sub-graph // GraphVertex* sub_input = (GraphVertex*)NULL; GraphVertex* sub_output = (GraphVertex*)NULL; readSubGraph(sub_input, sub_output, sof_a, gtag); // now add arcs from the first coefficient label to the sub-graph input // recipe_d.insertArc(gv, sub_input); recipe_d.insertArc(sub_output, src); } } return res; } // method: readSubGraph // // arguments: // GraphVertex*& sub_input: (output) container's input vertex // GraphVertex*& sub_output: (output) container's output vertex // Sof& sof: (input) Sof file // int32 graph_tag: (input) tag for graph to read // // return: a bool8 value indicating status // // this method reads a sub-graph from the file. it is very similar to // the readGraph method, except it does not delete the current // entries. upon read, it expands the sub-graph into the current // graph. // bool8 Recipe::readSubGraph(GraphVertex*& sub_input_a, GraphVertex*& sub_output_a, Sof& sof_a, int32 graph_tag_a) { // initialize output parameters // sub_input_a = (GraphVertex*)NULL; sub_output_a = (GraphVertex*)NULL; // local variables // DiGraph index_graph; SingleLinkedList algos(DstrBase::USER); // first read the graph that defines the connections // if (!index_graph.read(sof_a, graph_tag_a)) { return Error::handle(name(), L"readSubGraph", Error::READ, __FILE__, __LINE__, Error::WARNING); } SingleLinkedList node_indices(DstrBase::USER); SingleLinkedList< Triple< Pair, Float, Boolean> > topo; index_graph.get(node_indices, topo); // sanity check -- the nodes should be consecutive integers // int32 count = graph_tag_a; for (bool8 m = node_indices.gotoFirst(); m; m = node_indices.gotoNext()) { if (node_indices.getCurr()->ne(count++)) { return Error::handle(name(), L"readSubGraph", ERR, __FILE__, __LINE__); } } // now read in the Algorithms themselves -- put them into a // hashtable based on the tag number. // for (bool8 m = node_indices.gotoFirst(); m; m = node_indices.gotoNext()) { int32 tag = *(node_indices.getCurr()); Algorithm algo; if (!algo.read(sof_a, tag)) { return Error::handle(name(), L"readSubGraph", Error::READ, __FILE__, __LINE__, Error::WARNING); } // subtract the graph tag from the index so that the indices will // range from 0 to n (the same range as the list) // node_indices.getCurr()->assign(tag - graph_tag_a); Component* recipe = new Component; recipe->setAlgorithm(algo); algos.insertLast(recipe); } recipe_d.setAllocationMode(DstrBase::USER); // declare local variables for the graph copy // int32 src = 0; int32 dst = 0; float32 weight = 0.0; bool8 epsilon = false; // create vertices for the input data. we will also catch the input // and output coefficient buffer at this time. // GraphVertex* vertices[algos.length()]; for (int i = 0; i < algos.length(); i++) { algos.gotoPosition(i); vertices[i] = recipe_d.insertVertex(algos.getCurr()); if (algos.getCurr()->isCoefficientLabel(CoefficientLabel::INPUT)) { if (sub_input_a != (GraphVertex*)NULL) { return Error::handle(name(), L"readSubGraph", ERR, __FILE__, __LINE__); } sub_input_a = vertices[i]; } if (algos.getCurr()->isCoefficientLabel(CoefficientLabel::OUTPUT)) { if (sub_output_a != (GraphVertex*)NULL) { return Error::handle(name(), L"readSubGraph", ERR, __FILE__, __LINE__); } sub_output_a = vertices[i]; } } // loop over all elements in the arc list // for (bool8 more = topo.gotoFirst(); more; more = topo.gotoNext()) { // define the source and destination objects // GraphVertex* src_vertex; GraphVertex* dst_vertex; // determine the parameters of the arc // weight = (float32)topo.getCurr()->second(); epsilon = (bool8)topo.getCurr()->third(); src = (int32)topo.getCurr()->first().first(); dst = (int32)topo.getCurr()->first().second(); // check if the source is the start vertex // if ((src == DiGraph::START_INDEX) || (src == DiGraph::TERM_INDEX) || (dst == DiGraph::START_INDEX) || (dst == DiGraph::TERM_INDEX) || (src >= algos.length()) || (dst >= algos.length())) { return Error::handle(name(), L"readSubGraph", ERR, __FILE__, __LINE__); } src_vertex = vertices[src]; dst_vertex = vertices[dst]; // insert an arc from the source to the destination vertices // recipe_d.insertArc(src_vertex, dst_vertex, epsilon, weight); } recipe_d.setAllocationMode(DstrBase::SYSTEM); // exit gracefully // return true; } // method: checkInputs // // arguments: none // // return: a bool8 value indicating status // // this method tests the graph to make sure only Connection objects // have multiple inputs // bool8 Recipe::checkInputs() { // loop over all components // for (bool8 m = recipe_d.gotoFirst(); m; m = recipe_d.gotoNext()) { GraphVertex* gv = (GraphVertex*)recipe_d.getCurr(); for (bool8 a = gv->gotoFirst(); a; a = gv->gotoNext()) { GraphArc* ga = gv->getCurr(); Algorithm::TYPES type = ga->getVertex()->getItem()->getAlgorithm().getType(); if ((ga->getWeight() != 0.0) && (type != Algorithm::CONNECTION) && (type != Algorithm::MATH) && (type != Algorithm::CORRELATION)) { ga->getVertex()->getItem()->getAlgorithm().debug(L"algo"); return Error::handle(name(), L"checkInputs", ERR, __FILE__, __LINE__); } } } // exit gracefully // return true; }