unsigned int getDist(Graph *g, node n1, node n2) { vector<node> nextNodes; TLP_HASH_MAP<node, unsigned int> nodeDepth; MutableContainer<bool> alreadyTreated; bool found = false; alreadyTreated.setAll(false); nextNodes.push_back(n1); nodeDepth[n1] = 0; alreadyTreated.set(n1.id, true); for (unsigned int i = 0; !found && i < nextNodes.size(); ++i) { node current = nextNodes[i]; for (auto v : g->getInOutNodes(current)) { if (alreadyTreated.get(v.id)) continue; alreadyTreated.set(v.id, true); nextNodes.push_back(v); nodeDepth[v] = nodeDepth[current] + 1; if (v == n2) { found = true; break; } } } return nodeDepth[n2]; }
//================================================================= static void dfsAux(Graph *sG, node n, MutableContainer<int> &dfsPre, MutableContainer<int> &dfsPos, list<edge> &dfsEdges, unsigned int &preCount, unsigned int &postCount) { dfsPre.set(n.id, ++preCount); for (auto e : sG->getOutEdges(n)) { node target = sG->target(e); if (dfsPre.get(target.id) == 0) { dfsEdges.push_back(e); dfsAux(sG, target, dfsPre, dfsPos, dfsEdges, preCount, postCount); } } dfsPos.set(n.id, ++postCount); }
void makeBiconnectedDFS(Graph *graph, node from, MutableContainer<int> &low, MutableContainer<int> &depth, MutableContainer<node> &supergraph, unsigned int ¤tDepth, vector<edge> &addedEdges) { node u; depth.set(from.id, currentDepth++); low.set(from.id, depth.get(from.id)); //for every node connected to this one, call this function so it runs on every node. StableIterator<node> itN(graph->getInOutNodes(from)); while (itN.hasNext()) { node to = itN.next(); //if there is a loop, ignore it if (from == to) { continue; } if (!u.isValid()) { u = to; } //if the destination node has not been visited, visit it if (depth.get(to.id) == -1) { supergraph.set(to.id, from); makeBiconnectedDFS(graph, to, low, depth, supergraph, currentDepth, addedEdges); if (low.get(to.id) == depth.get(from.id)) { if (to == u && supergraph.get(from.id).isValid()) addedEdges.push_back(graph->addEdge(to, supergraph.get(from.id))); if (to != u) addedEdges.push_back(graph->addEdge(u, to)); } low.set(from.id, std::min(low.get(from.id), low.get(to.id))); } else { low.set(from.id, std::min(low.get(from.id), depth.get(to.id))); } } }
void dfsAux(Graph *sG, node n, MutableContainer<int>& dfsPre, MutableContainer<int>& dfsPos, list<edge>& dfsEdges) { dfsPre.set(n.id, preCount++); StableIterator<edge> it(sG->getOutEdges(n)); while (it.hasNext()) { edge e = it.next(); node target = sG->target(e); if (dfsPre.get(target.id) == 0) { dfsEdges.push_back(e); dfsAux(sG, target, dfsPre, dfsPos, dfsEdges); } } dfsPos.set(n.id, postCount++); }
// Determines if the given graph is topologically a tree bool TreeTest::isFreeTree(const Graph *graph, node curRoot) { // do a dfs traversal from curRoot; MutableContainer<bool> visited; visited.setAll(false); stack<dfsFreeTreeStruct> dfsLevels; dfsFreeTreeStruct curParams(curRoot, curRoot, graph->getInOutNodes(curRoot)); dfsLevels.push(curParams); while (!dfsLevels.empty()) { curParams = dfsLevels.top(); curRoot = curParams.curRoot; node cameFrom = curParams.cameFrom; Iterator<node> *neighbours = curParams.neighbours; // set neighbours member to nullptr // to avoid twice deletion on exit curParams.neighbours = nullptr; if (!neighbours->hasNext()) { dfsLevels.pop(); } else { visited.set(curRoot.id, true); // loop on remaining neighbours while (neighbours->hasNext()) { node curNode = neighbours->next(); // check self loop if (curNode == curRoot) { return false; } if (curNode != cameFrom) { if (visited.get(curNode.id)) { return false; } // go deeper in the dfs exploration curParams.curRoot = curNode; curParams.cameFrom = curRoot; curParams.neighbours = graph->getInOutNodes(curNode); dfsLevels.push(curParams); break; } } } } return true; } // end isFreeTree
//==================================================== void EdgeExtremityGlyphManager::initGlyphList(Graph **graph, GlGraphInputData* glGraphInputData, MutableContainer< EdgeExtremityGlyph *>& glyphs) { GlyphContext gc = GlyphContext(graph, glGraphInputData); glyphs.setAll(0); static std::list<std::string> plugins = PluginLister::instance()->availablePlugins<EdgeExtremityGlyph>(); for(std::list<std::string>::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { string glyphName = *it; EdgeExtremityGlyph *newGlyph = PluginLister::instance()->getPluginObject<EdgeExtremityGlyph>(glyphName, &gc); glyphs.set(PluginLister::pluginInformation(glyphName).id(), newGlyph); } }
//================================================================= bool biconnectedTest(const Graph *graph, node v, MutableContainer<bool> &mark, MutableContainer<unsigned int> &low, MutableContainer<unsigned int> &dfsNumber, MutableContainer<node> &supergraph, unsigned int &count) { mark.set(v.id,true); dfsNumber.set(v.id,count); low.set(v.id,count); ++count; Iterator<node> *it=graph->getInOutNodes(v); while (it->hasNext()) { node w=it->next(); if (!mark.get(w.id)) { if (dfsNumber.get(v.id)==1) { if (count != 2) { delete it; return false; } } supergraph.set(w.id,v); if (!biconnectedTest(graph,w,mark,low,dfsNumber,supergraph,count)) { delete it; return false; } if (dfsNumber.get(v.id)!=1) { if (low.get(w.id)>=dfsNumber.get(v.id)) { delete it; return false; } else low.set(v.id, std::min(low.get(v.id), low.get(w.id))); } } else if (supergraph.get(v.id)!=w) { low.set(v.id, std::min(low.get(v.id), dfsNumber.get(w.id))); } } delete it; return true; }
bool run() { result->setAllNodeValue(0.0); result->setAllEdgeValue(0.0); bool directed = false; bool norm = false; if ( dataSet!=NULL ) { dataSet->get("directed",directed); dataSet->get("norm", norm); } //Metric is 0 in this case if(graph->numberOfNodes()<=2) return true; Iterator<node> *it = graph->getNodes(); unsigned int count = 0; while(it->hasNext()) { if (pluginProgress->progress(count++,graph->numberOfNodes())!=TLP_CONTINUE) break; node s = it->next(); stack<node> S; TLP_HASH_MAP<node, list<node> > P; MutableContainer<int> sigma; sigma.setAll(0); sigma.set(s.id,1); MutableContainer<int> d; d.setAll(-1); d.set(s.id, 0); queue<node> Q; Q.push(s); while(!Q.empty()) { node v = Q.front(); Q.pop(); S.push(v); Iterator<node> *it2; if (directed) it2 = graph->getOutNodes(v); else it2 = graph->getInOutNodes(v); while (it2->hasNext()) { node w = it2->next(); if (d.get(w.id)<0) { Q.push(w); d.set(w.id, d.get(v.id)+1); } if (d.get(w.id) == d.get(v.id)+1) { sigma.add(w.id, sigma.get(v.id)); P[w].push_back(v); } } delete it2; } MutableContainer<double> delta; delta.setAll(0.0); while(!S.empty()) { node w = S.top(); S.pop(); list<node>::const_iterator itn = P[w].begin(); for (; itn!=P[w].end(); ++itn) { node v = *itn; delta.add(v.id, (double(sigma.get(v.id)) / double(sigma.get(w.id)) * (1.0 + delta.get(w.id)))); edge e = graph->existEdge(v,w,directed); if(e.isValid()) result->setEdgeValue(e, result->getEdgeValue(e) + double(sigma.get(v.id)) / double(sigma.get(w.id)) * (1.0 + delta.get(w.id))); } if (w != s) result->setNodeValue(w, result->getNodeValue(w) + delta.get(w.id)); } } delete it; //Normalization if(norm || !directed) { double n = graph->numberOfNodes(); it = graph->getNodes(); while(it->hasNext()) { node s = it->next(); //In the undirected case, the metric must be divided by two, then if(norm) result->setNodeValue(s,result->getNodeValue(s)/((n-1.0)*(n-2.0))); if(!directed) result->setNodeValue(s,result->getNodeValue(s)/2.0); } delete it; Iterator<edge> *itE = graph->getEdges(); while(itE->hasNext()) { edge e = itE->next(); if(norm) result->setEdgeValue(e,4.0*result->getEdgeValue(e)/(n*n)); if(!directed) result->setEdgeValue(e,result->getEdgeValue(e)/(2.0)); } delete itE; } return pluginProgress->state()!=TLP_CANCEL; }
/* * Algebric criteria to check the plane map... */ bool PlanarityTestImpl::isPlanarEmbedding(Graph *sG) { int n = sG->numberOfNodes(); if (n == 1) return true; int m = sG->numberOfEdges(); unsigned int count = 0; MutableContainer<char> considered; MutableContainer<bool> sens; considered.setAll(0); sens.setAll(false); int fc = 0; // displayMap(sG); for (int k=0; k<2; ++k) { Iterator<edge> *it = sG->getEdges(); while (it->hasNext()) { edge e = it->next(); if (considered.get(e.id)<2) { count = 0; // cerr << "Face : " << fc << " start edge:" << e.id << endl; edge e1 = e; node n, n_tmp; if (sens.get(e.id)) n = sG->target(e1); else n = sG->source(e1); // cerr << "-(" << e1.id << ")->" << n.id << flush; n_tmp = n; do { considered.add(e1.id, 1); EdgeMapIterator it(sG, e1, n); e1 = it.next(); n = sG->opposite(e1,n); if (sG->source(e1) == n) sens.set(e1.id,true); // cerr << "-(" << e1.id << ")->" << n.id << flush; ++count; if (count > sG->numberOfEdges() +1) break; } while ((e1 != e)||(n != n_tmp)); fc++; // cerr << endl; } } delete it; } if (fc != m - n + 2) { //cerr << __PRETTY_FUNCTION__ << " : not ok :( nb faces :" << fc << "!=" << m - n +2 << endl; return false; } return true; }
/** * update is_selectable_visited and is_selectable */ void Ordering::updateNewSelectableNodes(node node_f, node no_tmp2 ,edge, node node_last, vector<Face> v_faces, bool one_face,bool was_visited, bool selection_face) { MutableContainer<bool> tried; tried.setAll(false); node n = node_f; node tmp = no_tmp2; node tmp2 = node() ; unsigned int lim = v_faces.size(); while(n != node_last) { tmp2 = n; if(Gp->deg(n) > 2 && isSelectable(n)) { if(visitedNodes.get(n.id)) is_selectable_visited.set(n.id,true); else is_selectable.set(n.id,true); } else { is_selectable_visited.set(n.id,false); is_selectable.set(n.id,false); } tried.set(n.id,true); n = tmp; tmp = right.get(n.id); } if(Gp->deg(n) > 2 && isSelectable(n)) is_selectable_visited.set(n.id,true); else { is_selectable_visited.set(n.id,false); is_selectable.set(n.id,false); } if(one_face) { if(tmp2 == node()) tmp2 = node_f; Iterator<node> * it_no = Gp->getFaceNodes(Gp->getFaceContaining(tmp2,node_last)); while(it_no->hasNext()) { node no_tmp = it_no->next(); if(!tried.get(no_tmp.id)) { bool on_c = contour.get(no_tmp.id); if(on_c) { bool sel = isSelectable(no_tmp); if(sel) if(visitedNodes.get(no_tmp.id)) is_selectable_visited.set(no_tmp.id,true); else is_selectable.set(no_tmp.id, true); else { is_selectable_visited.set(no_tmp.id,false); is_selectable_visited.set(no_tmp.id,false); } } tried.set(no_tmp.id,true); } } delete it_no; lim--; } if((selection_face && was_visited) || !selection_face) for(unsigned int i = 0; i < lim; ++i) { bool face_sel = false; Face f_tmp = v_faces[i]; if(is_selectable_face.get(f_tmp.id) || is_selectable_visited_face.get(f_tmp.id)) face_sel = true; Iterator<node> * itn = Gp->getFaceNodes(f_tmp); if(face_sel) while(itn->hasNext()) { node no_tmp = itn->next(); is_selectable.set(no_tmp.id,false); is_selectable_visited.set(no_tmp.id,false); tried.set(no_tmp.id,true); } else { while(itn->hasNext()) { node no_tmp = itn->next(); if(!tried.get(no_tmp.id) && (is_selectable_visited.get(no_tmp.id) || is_selectable.get(no_tmp.id))) { if(!isSelectable(no_tmp)) { is_selectable_visited.set(no_tmp.id,false); is_selectable.set(no_tmp.id,false); } } tried.set(no_tmp.id,true); } } delete itn; } }
static void makeBiconnectedDFS(Graph *graph, vector<edge> &addedEdges) { // the graph is already connected // so get any node to begin node from = graph->getOneNode(); if (!from.isValid()) return; MutableContainer<int> low; MutableContainer<int> depth; depth.setAll(-1); MutableContainer<node> supergraph; supergraph.setAll(node()); // dfs loop stack<dfsBiconnectStruct> dfsLevels; dfsBiconnectStruct dfsParams(graph, from); dfsLevels.push(dfsParams); depth.set(from.id, 0); low.set(from.id, 0); while(!dfsLevels.empty()) { dfsParams = dfsLevels.top(); from = dfsParams.from; node u = dfsParams.first; //for every node connected to from Iterator<node>* itN = dfsParams.inOutNodes; while (itN->hasNext()) { node to = itN->next(); //if there is a loop, ignore it if (from == to) { continue; } if (!u.isValid()) { dfsLevels.top().first = u = to; } //if the destination node has not been visited, visit it if (depth.get(to.id) == -1) { supergraph.set(to.id, from); dfsParams.from = to; dfsParams.first = node(); dfsParams.u = u; unsigned int currentDepth = dfsParams.depth + 1; dfsParams.depth = currentDepth; depth.set(to.id, currentDepth); low.set(to.id, currentDepth); dfsParams.inOutNodes = new StableIterator<node>(graph->getInOutNodes(to)); break; } else { low.set(from.id, std::min(low.get(from.id), depth.get(to.id))); } } if (from != dfsParams.from) { dfsLevels.push(dfsParams); continue; } delete itN; // pop the current dfsParams node to = dfsParams.from; from = supergraph.get(to.id); u = dfsParams.u; if (low.get(to.id) == depth.get(from.id)) { if (to == u && supergraph.get(from.id).isValid()) addedEdges.push_back(graph->addEdge(to, supergraph.get(from.id))); if (to != u) addedEdges.push_back(graph->addEdge(u, to)); } low.set(from.id, std::min(low.get(from.id), low.get(to.id))); dfsLevels.pop(); } }
//********************************************************************** bool AcyclicTest::acyclicTest(const Graph *graph, vector<edge> *obstructionEdges) { MutableContainer<bool> visited; MutableContainer<bool> finished; visited.setAll(false); finished.setAll(false); bool result = true; // do a dfs traversal Iterator<node> *it = graph->getNodes(); while (it->hasNext()) { node curNode = it->next(); if (!visited.get(curNode.id)) { stack<node> nodesToVisit; nodesToVisit.push(curNode); stack<Iterator<edge>*> neighboursToVisit; neighboursToVisit.push(graph->getOutEdges(curNode)); while(!nodesToVisit.empty()) { curNode = nodesToVisit.top(); Iterator<edge> *ite = neighboursToVisit.top(); // check if dfs traversal of curNode neighbours is finished if (!ite->hasNext()) { // unstack curNode nodesToVisit.pop(); // delete & unstack neightbours iterator delete neighboursToVisit.top(); neighboursToVisit.pop(); // mark curNode as to be skipped // during further exploration finished.set(curNode.id, true); } else { visited.set(curNode.id, true); // loop on remaining neighbours while (ite->hasNext()) { edge tmp = ite->next(); node neighbour = graph->target(tmp); // check if we are already in the exploration // of the neighbours of neighbour if (visited.get(neighbour.id)) { if (!finished.get(neighbour.id)) { // found a cycle result = false; if (obstructionEdges != NULL) obstructionEdges->push_back(tmp); else { // it is finished if we don't need // to collect obstruction edges break; } } } else { // found a new neighbour to explore // go deeper in our dfs traversal nodesToVisit.push(neighbour); neighboursToVisit.push(graph->getOutEdges(neighbour)); break; } } // it may be finished if we don't need // to collect obstruction edges if ((!result) && (obstructionEdges == NULL)) break; } } // it may be finished if we don't need // to collect obstruction edges if ((!result) && (obstructionEdges == NULL)) { // don't froget to delete remaining iterators while(!neighboursToVisit.empty()) { delete neighboursToVisit.top(); neighboursToVisit.pop(); } break; } } } delete it; return result; }