//----< depth first search from specific node >------------------------ public void walk(CsNode <V, E> node) { // process this node gop.doNodeOp(node); node.visited = true; // visit children do { CsEdge <V, E> childEdge = node.getNextUnmarkedChild(); if (childEdge == null) { return; } else { gop.doEdgeOp(childEdge.edgeValue); walk(childEdge.targetNode); if (node.hasUnmarkedChild() || showBackTrack) { // popped back to predecessor node gop.doNodeOp(node); // more edges to visit so announce } // location and next edge } } while (true); }
// the method for finding SCC public void tarjan(CsNode <V, E> node) { node.dfn_nodenumber = node.low_nodenumber = ++dfn_index; st.Push(node); foreach (var a in node.children) { if (a.targetNode.dfn_nodenumber < 0) { tarjan(a.targetNode); node.low_nodenumber = Math.Min(a.targetNode.low_nodenumber, node.low_nodenumber); } else if (st.Contains(a.targetNode)) { node.low_nodenumber = Math.Min(node.low_nodenumber, a.targetNode.dfn_nodenumber); } } if (node.dfn_nodenumber == node.low_nodenumber) { scc_list.Add("\n SCC: "); // Console.Write("\n SCC: "); CsNode <V, E> w; do { w = st.Pop(); // Console.Write(w.name + " "); scc_list.Add(w.name + " "); } while (w != node); } }
//---------------<Accept the graph from dependnecy analysis>---------------------------// public List <CsNode <string, string> > acceptGraph(List <Tuple <string, string> > graph, List <string> files) { List <CsNode <string, string> > nodes = new List <CsNode <string, string> >(); List <string> scc = new List <string>(); for (int i = 0; i < files.Count; i++) { CsNode <string, string> node = new CsNode <string, string>(files[i]); node.name = Path.GetFileName(files[i]); nodes.Add(node); } int n = graph.Count; for (int i = 0; i < n; i++) { int j = 0; for (j = 0; j < nodes.Count; j++) { if (nodes[j].name == graph[i].Item1) { break; } } for (int k = 0; k < nodes.Count; k++) { if (nodes[k].name == graph[i].Item2 && j < nodes.Count) { nodes[j].addChild(nodes[k], " "); } } } //scc = tarjan(nodes); return(nodes); }
//----------------<implementation of Targan algorithm>---------------------------------- public void Tarjan(CsNode <string, string> node) { node.Dfn = index; node.Low = index; index++; st.Push(node); node.visited = true; foreach (CsEdge <string, string> n in node.children) { if (n.targetNode.visited == false) { Tarjan(n.targetNode); node.Low = Math.Min(node.Low, n.targetNode.Low); } else if (st.Contains(n.targetNode)) { node.Low = Math.Min(node.Low, n.targetNode.Dfn); } } if (node.Dfn == node.Low) { List <CsNode <string, string> > temp = new List <CsNode <string, string> >(); CsNode <string, string> top; do { top = st.Pop(); temp.Add(top); } while (node != top); result.Add(temp); } }
/// <summary> /// Implementation of Tarjan's algorithm /// </summary> /// <param name="node"></param> /// <param name="S"></param> /// <param name="index"></param> /// <param name="lstRes"></param> /// <returns></returns> public HashSet <List <string> > DoTarjan(Dictionary <string, HashSet <CsNode <string, string> > > myGraph, HashSet <CsNode <string, string> > lstNodes) { int index = 0; Stack <CsNode <string, string> > stack = new Stack <CsNode <string, string> >(); HashSet <List <string> > lstSCC = new HashSet <List <string> >(); Action <CsNode <string, string> > StrongConnect = null; StrongConnect = (node) => { node.Index = node.lowlink = index; index++; stack.Push(node); if (myGraph[node.name].Count < 1) { List <string> lstSingleNodeSCC = new List <string>(); lstSingleNodeSCC.Add(node.name); lstSCC.Add(lstSingleNodeSCC); } else { foreach (var adjNode in myGraph[node.name]) { int indTrue = IsPresent(stack, adjNode.name); if (adjNode.Index < 0 && indTrue < 0) { StrongConnect(adjNode); node.lowlink = Math.Min(node.lowlink, adjNode.lowlink); } else if (indTrue > -1) { node.lowlink = Math.Min(node.lowlink, indTrue); } if ((node.lowlink == node.Index) && myGraph[adjNode.name].Count > 0) { List <string> lstSingleSCC = new List <string>(); CsNode <string, string> poppedNode = new CsNode <string, string>("popped"); do { if (stack.Count > 0) { poppedNode = stack.Pop(); lstSingleSCC.Add(poppedNode.name); UpdateNodeIndex(node, poppedNode, lstNodes); } else { break; } } while (poppedNode != node); lstSCC.Add(lstSingleSCC); } } } }; foreach (var node in lstNodes) { if (node.Index < 0) { StrongConnect(node); } } return(lstSCC); }
static void Main(string[] args) { List <string> scc = new List <string>(); List <CsNode <string, string> > nodes = new List <CsNode <string, string> >(); Console.Write("\n Testing Graph class"); Console.WriteLine("\n ======================="); TestGraph t = new TestGraph(); CsNode <string, string> node1 = new CsNode <string, string>("node1"); CsNode <string, string> node2 = new CsNode <string, string>("node2"); CsNode <string, string> node3 = new CsNode <string, string>("node3"); CsNode <string, string> node4 = new CsNode <string, string>("node4"); CsNode <string, string> node5 = new CsNode <string, string>("node5"); node1.addChild(node2, "edge12"); node2.addChild(node1, "edge21"); node2.addChild(node3, "edge23"); node2.addChild(node4, "edge24"); node3.addChild(node1, "edge31"); node5.addChild(node1, "edge51"); node5.addChild(node4, "edge54"); CsGraph <string, string> graph = new CsGraph <string, string>("Fred"); graph.addNode(node1); graph.addNode(node2); graph.addNode(node3); graph.addNode(node4); graph.addNode(node5); nodes.Add(node1); nodes.Add(node2); nodes.Add(node3); nodes.Add(node4); nodes.Add(node5); scc = t.tarjan(nodes); Console.WriteLine("Graph with parent and nodes"); foreach (var node in nodes) { Console.Write("\n {0}", node.name); for (int i = 0; i < node.children.Count; ++i) { Console.Write("\n {0}", node.children[i].targetNode.name); } } Console.WriteLine("SCCs:\n"); foreach (var s in scc) { Console.Write(s); } Console.Read(); }
//-------------<Tarjan's algorithm to find the strongly connected component>---------- public List <string> tarjan(List <CsNode <string, string> > Nodes) { string s1 = null; List <string> scc = new List <string>(); var index = 0; var S = new Stack <CsNode <string, string> >(); void stronglyConnected(CsNode <string, string> v) { v.index = index; v.lowlink = index; index++; S.Push(v); //int i = 1; //scc.Add(i.ToString()); CsNode <string, string> w = null; foreach (var child in v.children) { w = child.targetNode; if (w.index < 0) { stronglyConnected(w); v.lowlink = Math.Min(v.lowlink, w.lowlink); } else if (S.Contains(w)) { v.lowlink = Math.Min(v.lowlink, w.index); } } if (v.lowlink == v.index) { do { w = S.Pop(); s1 = s1 + w.name + ", "; } while (w != v); scc.Add(s1); s1 = null; } } foreach (var v in Nodes) { if (v.index < 0) { stronglyConnected(v); } } return(scc); }
static void Main(string[] args) { Console.Write("\n Testing CsGraph class"); Console.Write("\n ======================="); CsNode <string, string> node1 = new CsNode <string, string>("node1"); CsNode <string, string> node2 = new CsNode <string, string>("node2"); CsNode <string, string> node3 = new CsNode <string, string>("node3"); CsNode <string, string> node4 = new CsNode <string, string>("node4"); CsNode <string, string> node5 = new CsNode <string, string>("node5"); var nodes = new List <CsNode <string, string> >(); //var nodes = new List<Graph<string,string>>(); for (int i = 0; i < 5; i++) { // Here you can give each person a custom name based on a number nodes.Add(new CsNode <string, string>("node" + i)); } node1.addChild(node2, "edge12"); node1.addChild(node3, "edge13"); node2.addChild(node3, "edge23"); node2.addChild(node4, "edge24"); node3.addChild(node1, "edge31"); node5.addChild(node1, "edge51"); node5.addChild(node4, "edge54"); Graph <string, string> graph = new Graph <string, string>("Fred"); graph.addNode(node1); graph.addNode(node2); graph.addNode(node3); graph.addNode(node4); graph.addNode(node5); graph.startNode = node1; Console.Write("\n\n starting walk at {0}", graph.startNode.name); Console.Write("\n not showing backtracks"); graph.walk(); graph.startNode = node2; Console.Write("\n\n starting walk at {0}", graph.startNode.name); graph.showBackTrack = true; Console.Write("\n show backtracks"); graph.setOperation(new demoOperation()); graph.walk(); Console.Write("\n\n"); Console.ReadLine(); }
// show the result of SCC public CsGraph <string, string> show_strong(string[] args) { DepAnalysis test = new DepAnalysis(); test.match(args); CsGraph <string, string> dep_graph = new CsGraph <string, string>("dep_name"); CsNode <string, string> graph_start_node = new CsNode <string, string>("start_graph"); List <CsNode <string, string> > allnode = new List <CsNode <string, string> >(); for (int i = 0; i < args.Length; ++i) { CsNode <string, string> nodes = new CsNode <string, string>(Path.GetFileName(args[i])); graph_start_node = nodes; allnode.Add(nodes); } foreach (var ele in test.depentable) { foreach (var ls in allnode) { if (ls.name == ele.Key) { foreach (var item in ele.Value) { foreach (var ls2 in allnode) { if (ls2.name == item) { ls.addChild(ls2, "XXX"); } } } } } } foreach (var ls in allnode) { dep_graph.addNode(ls); } // dep_graph.showDependencies(); dep_graph.startNode = graph_start_node; // Console.WriteLine("\n\n"); Console.WriteLine("\n----------------------------show strong component -----------------------"); dep_graph.tarjan(); return(dep_graph); }
/// <summary> /// Updates the index value of every node /// </summary> /// <param name="parentNode"></param> /// <param name="childNode"></param> /// <param name="lstNodes"></param> public void UpdateNodeIndex(CsNode <string, string> parentNode, CsNode <string, string> childNode, HashSet <CsNode <string, string> > lstNodes) { foreach (CsNode <string, string> node in lstNodes) { if (node.name == childNode.name || node.name == parentNode.name) { if (node.name == childNode.name) { node.Index = childNode.Index; } else { node.Index = parentNode.Index; } break; } } }
//----< depth first search from specific node >------------------------ public void walk(CsNode <V, E> node) { gop.doNodeOp(node); node.visited = true; do { CsEdge <V, E> childEdge = node.getNextUnmarkedChild(); if (childEdge == null) { return; } else { gop.doEdgeOp(childEdge.edgeValue); walk(childEdge.targetNode); if (node.hasUnmarkedChild() || showBackTrack) { gop.doNodeOp(node); } } } while (true); }
//----< add child vertex and its associated edge value to vertex >----- public void addChild(CsNode <V, E> childNode, E edgeVal) { children.Add(new CsEdge <V, E>(childNode, edgeVal)); }
public CsEdge(CsNode <V, E> node, E value) { targetNode = node; edgeValue = value; }
override public bool doNodeOp(CsNode <string, string> node) { Console.Write("\n -- {0}", node.name); return(true); }
//----< add vertex to graph adjacency list >--------------------------- public void addNode(CsNode <V, E> node) { adjList.Add(node); }
//----< graph.walk() calls this on every node >------------------------ virtual public bool doNodeOp(CsNode <V, E> node) { Console.Write("\n {0}", node.ToString()); return(true); }