/// <summary> /// We build a spanning tree by following the DFS, the tree induces an order on vertices /// measured by the distance from the tree root. The feedback set will consist of edges /// directed against this order. /// </summary> /// <param name="graph"></param> /// <returns></returns> static internal IEnumerable <IEdge> GetFeedbackSet(BasicGraphOnEdges <TEdge> graph) { if (graph != null && graph.NodeCount > 0 && graph.Edges.Count > 0) { Set <IEdge> feedbackSet = new Set <IEdge>(); VertStatus[] status = new VertStatus[graph.NodeCount]; //will be Unvisited at the beginning #if SHARPKIT //http://code.google.com/p/sharpkit/issues/detail?id=367 arrays are not default initialised for (int i = 0; i < status.Length; i++) { status[i] = VertStatus.NotVisited; } #endif for (int vertex = 0; vertex < graph.NodeCount; vertex++) { if (status[vertex] == VertStatus.Visited) { continue; } System.Diagnostics.Debug.Assert(status[vertex] != VertStatus.InStack); Stack <IEnumerator <TEdge> > enumStack = new Stack <IEnumerator <TEdge> >(); //avoiding the recursion Stack <int> vertexStack = new Stack <int>(); //avoiding the recursion IEnumerator <TEdge> outEnum = graph.OutEdges(vertex).GetEnumerator(); Push(enumStack, vertexStack, status, vertex, outEnum); while (enumStack.Count > 0) { Pop(enumStack, vertexStack, status, out vertex, out outEnum); while (outEnum.MoveNext()) { TEdge e = outEnum.Current; if (e.Source == e.Target) { continue; } VertStatus targetStatus = status[e.Target]; if (targetStatus == VertStatus.InStack) { feedbackSet.Insert(e); } else if (targetStatus == VertStatus.NotVisited) //have to go deeper { Push(enumStack, vertexStack, status, vertex, outEnum); vertex = e.Target; status[e.Target] = VertStatus.Visited; outEnum = graph.OutEdges(vertex).GetEnumerator(); } } } } return(feedbackSet as IEnumerable <IEdge>); } else { return(new Set <IEdge>()); } }
/// <summary> /// The function returns an array arr such that /// arr is a permutation of the graph vertices, /// and for any edge e in graph if e.Source=arr[i] /// e.Target=arr[j], then i is less than j /// </summary> /// <param name="graph"></param> /// <returns></returns> internal static int[] GetOrder <TEdge>(BasicGraphOnEdges <TEdge> graph) where TEdge : IEdge { var visited = new bool[graph.NodeCount]; //no recursion! So we have to organize a stack var sv = new Stack <int>(); var se = new Stack <IEnumerator <int> >(); var order = new List <int>(); IEnumerator <int> en; for (int u = 0; u < graph.NodeCount; u++) { if (visited[u]) { continue; } int cu = u; visited[cu] = true; en = graph.OutEdges(u).Select(e => e.Target).GetEnumerator(); do { while (en.MoveNext()) { int v = en.Current; if (!visited[v]) { visited[v] = true; sv.Push(cu); se.Push(en); cu = v; en = graph.OutEdges(cu).Select(e => e.Target).GetEnumerator(); } } order.Add(cu); if (sv.Count > 0) { en = se.Pop(); cu = sv.Pop(); } else { break; } } while (true); } order.Reverse(); return(order.ToArray()); }
static IEnumerable <int> Neighbors(BasicGraphOnEdges <TEdge> graph, int s) { foreach (TEdge e in graph.OutEdges(s)) { yield return(e.Target); } foreach (TEdge e in graph.InEdges(s)) { yield return(e.Source); } }