void nimbleGraph::getDependenciesOneNode(vector<int> &deps, int CgraphID, bool downstream, unsigned int recursionDepth, bool followLHSinferred) { if(recursionDepth > graphNodeVec.size()) { PRINTF("ERROR: getDependencies has recursed too far. Something must be wrong.\n"); return; } #ifdef _DEBUG_GETDEPS PRINTF(" Entering recursion for node %i\n", CgraphID); #endif graphNode *thisGraphNode = graphNodeVec[CgraphID]; int numChildren = thisGraphNode->numChildren; int i(0); graphNode *thisChildNode; int thisChildCgraphID; #ifdef _DEBUG_GETDEPS PRINTF(" Starting to iterate through %i children of node %i\n", numChildren, CgraphID); #endif for(; i < numChildren; i++) { thisChildNode = thisGraphNode->children[i]; if(thisChildNode->touched) continue; if(!followLHSinferred) { if(thisChildNode->type == LHSINFERRED) continue; } thisChildCgraphID = thisChildNode->CgraphID; #ifdef _DEBUG_GETDEPS PRINTF(" Adding child node %i\n", thisChildCgraphID); #endif deps.push_back(thisChildNode->CgraphID); /* LHSINFERRED nodes may be included here and will be stripped in R before final return - could be cleaner*/ thisChildNode->touched = true; if(downstream | (thisChildNode->type != STOCH)) { #ifdef _DEBUG_GETDEPS PRINTF(" Recursing into child node %i\n", thisChildCgraphID); #endif getDependenciesOneNode(deps, thisChildCgraphID, downstream, recursionDepth + 1); } } #ifdef _DEBUG_GETDEPS PRINTF(" Done iterating through %i children of node %i\n", numChildren, CgraphID); #endif }
void nimbleGraph::getDependenciesOneNode(vector<int> &deps, int CgraphID, bool downstream, unsigned int recursionDepth) { if(recursionDepth > graphNodeVec.size()) { PRINTF("ERROR: getDependencies has recursed too far. Something must be wrong.\n"); return; } #ifdef _DEBUG_GETDEPS PRINTF(" Entering recursion for node %i\n", CgraphID); #endif graphNode *thisGraphNode = graphNodeVec[CgraphID]; int numChildren = thisGraphNode->numChildren; int i(0); graphNode *thisChildNode; int thisChildCgraphID; #ifdef _DEBUG_GETDEPS PRINTF(" Starting to iterate through %i children of node %i\n", numChildren, CgraphID); #endif for(; i < numChildren; i++) { thisChildNode = thisGraphNode->children[i]; if(thisChildNode->touched) continue; thisChildCgraphID = thisChildNode->CgraphID; #ifdef _DEBUG_GETDEPS PRINTF(" Adding child node %i\n", thisChildCgraphID); #endif deps.push_back(thisChildNode->CgraphID); thisChildNode->touched = true; if(downstream | (thisChildNode->type != STOCH)) { #ifdef _DEBUG_GETDEPS PRINTF(" Recursing into child node %i\n", thisChildCgraphID); #endif getDependenciesOneNode(deps, thisChildCgraphID, downstream, recursionDepth + 1); } } #ifdef _DEBUG_GETDEPS PRINTF(" Done iterating through %i children of node %i\n", numChildren, CgraphID); #endif }
vector<int> nimbleGraph::getDependencies(const vector<int> &Cnodes, const vector<int> &Comit, bool downstream) { // assume on entry that touched = false on all nodes // Cnodes and Comit are C-indices (meaning they start at 0) int n = Comit.size(); int i; vector<int> ans; // touch omit nodes #ifdef _DEBUG_GETDEPS int iDownstream = static_cast<int>(downstream); PRINTF("debugging output for getDependencies with %i nodes, %i omits, and downstream = %i. C indices (graphIDs) shown are 0-based\n", Cnodes.size(), Comit.size(), iDownstream); #endif for(i = 0; i < n; i++) { graphNodeVec[ Comit[i] ]->touched = true; #ifdef _DEBUG_GETDEPS PRINTF("touching %i to omit\n", Comit[i]); #endif } n = Cnodes.size(); graphNode *thisGraphNode; int thisGraphNodeID; for(i = 0; i < n; i++) { thisGraphNodeID = Cnodes[i]; thisGraphNode = graphNodeVec[ thisGraphNodeID ]; #ifdef _DEBUG_GETDEPS PRINTF("Working on input node %i\n", thisGraphNodeID); #endif if(!thisGraphNode->touched) { #ifdef _DEBUG_GETDEPS PRINTF(" Adding node %i to ans and recursing\n", thisGraphNodeID); #endif ans.push_back(thisGraphNodeID); thisGraphNode->touched = true; getDependenciesOneNode(ans, thisGraphNodeID, downstream, 1); } else { #ifdef _DEBUG_GETDEPS PRINTF(" Node %i was already touched.\n", thisGraphNodeID); #endif if((thisGraphNode->type == STOCH) & !downstream) { /* In this case the input node was already touched, so it is a dependency */ /* of something earlier on the input list. But since it was on the input list */ /* we still need to get its dependencies. But if downstream is TRUE (==1), then */ /* its dependencies will have already been pursued so we don't need to */ #ifdef _DEBUG_GETDEPS PRINTF(" But is stochastic and downstream is false, so we are recursing into its dependencies.\n"); #endif getDependenciesOneNode(ans, thisGraphNodeID, downstream, 1); } } } // untouch nodes and omit n = Comit.size(); for(i = 0; i < n; i++) { graphNodeVec[ Comit[i] ]->touched = false; } n = ans.size(); for(i = 0; i < n; i++) { graphNodeVec[ ans[i] ]->touched = false; } std::sort(ans.begin(), ans.end()); return(ans); }
vector<int> nimbleGraph::getDependencies(const vector<int> &Cnodes, const vector<int> &Comit, bool downstream) { // assume on entry that touched = false on all nodes // Cnodes and Comit are C-indices (meaning they start at 0) int n = Comit.size(); int i; vector<int> ans; // touch omit nodes #ifdef _DEBUG_GETDEPS int iDownstream = static_cast<int>(downstream); PRINTF("debugging output for getDependencies with %i nodes, %i omits, and downstream = %i. C indices (graphIDs) shown are 0-based\n", Cnodes.size(), Comit.size(), iDownstream); #endif for(i = 0; i < n; i++) { graphNodeVec[ Comit[i] ]->touched = true; #ifdef _DEBUG_GETDEPS PRINTF("touching %i to omit\n", Comit[i]); #endif } n = Cnodes.size(); graphNode *thisGraphNode; int thisGraphNodeID; vector<int>::const_iterator omitFinder; for(i = 0; i < n; i++) { thisGraphNodeID = Cnodes[i]; // Need to check Comit // the touching of all Comit nodes still blocks them in the recursion // but for the input nodes, we need to check if they are in Comit because // being touched could also occur from another input node omitFinder = std::find(Comit.begin(), Comit.end(), thisGraphNodeID); if(omitFinder != Comit.end()) continue; // it was in omits thisGraphNode = graphNodeVec[ thisGraphNodeID ]; #ifdef _DEBUG_GETDEPS PRINTF("Working on input node %i\n", thisGraphNodeID); #endif if(!thisGraphNode->touched) { #ifdef _DEBUG_GETDEPS PRINTF(" Adding node %i to ans and recursing\n", thisGraphNodeID); #endif /* LHSINFERRED means e.g. x[1:10] ~ dmnorm() and x[2:3] is used on a RHS. So x[2:3] is LHSINFERRED. IT's not a real node for calculation (no nodeFunction), but it is a vertex in the graph */ if(thisGraphNode->type != LHSINFERRED) { ans.push_back(thisGraphNodeID); thisGraphNode->touched = true; } else { /* need to include nodeFunctionNode and its non-LHSINFERRED children*/ /* the current LHSINFERRED node will not be touched or included */ graphNode* nodeFunctionNode = thisGraphNode->nodeFunctionNode; if(!nodeFunctionNode->touched) { int nodeFunctionNodeID = nodeFunctionNode->CgraphID; ans.push_back(nodeFunctionNodeID); nodeFunctionNode->touched = true; getDependenciesOneNode(ans, nodeFunctionNodeID, downstream, 1, false); } } getDependenciesOneNode(ans, thisGraphNodeID, downstream, 1); } else { #ifdef _DEBUG_GETDEPS PRINTF(" Node %i was already touched.\n", thisGraphNodeID); #endif if((thisGraphNode->type == STOCH) & !downstream) { /* In this case the input node was already touched, so it is a dependency */ /* of something earlier on the input list. But since it was on the input list */ /* we still need to get its dependencies. But if downstream is TRUE (==1), then */ /* its dependencies will have already been pursued so we don't need to */ #ifdef _DEBUG_GETDEPS PRINTF(" But is stochastic and downstream is false, so we are recursing into its dependencies.\n"); #endif getDependenciesOneNode(ans, thisGraphNodeID, downstream, 1); } } } // untouch nodes and omit n = Comit.size(); for(i = 0; i < n; i++) { graphNodeVec[ Comit[i] ]->touched = false; } n = ans.size(); for(i = 0; i < n; i++) { graphNodeVec[ ans[i] ]->touched = false; } std::sort(ans.begin(), ans.end()); return(ans); }