public StrongComponentChecker(IDirectedGraph <NodeType, EdgeType> graph) { this.graph = graph; dfs = new DepthFirstSearch <NodeType, EdgeType>(graph); CanCreateNodeData <NodeType> data = (CanCreateNodeData <NodeType>)graph; DiscoverTime = data.CreateNodeData <int>(0); RootDiscoverTime = data.CreateNodeData <int>(0); dfs.DiscoverNode += delegate(NodeType node) { DiscoverTime[node] = time; RootDiscoverTime[node] = time; time++; }; dfs.BackEdge += ProcessEdge2; dfs.CrossEdge += ProcessEdge2; dfs.FinishTreeEdge += ProcessEdge; dfs.FinishNode += delegate(NodeType node) { int thisRootDiscoverTime = RootDiscoverTime[node]; if (thisRootDiscoverTime < DiscoverTime[node]) { // not a root } else { // root of a component if (thisRootDiscoverTime != 0) { IsStrong = false; } } }; }
public StrongComponents2(Converter <NodeType, IEnumerable <NodeType> > successors, CanCreateNodeData <NodeType> data) { dfs = new DepthFirstSearch <NodeType>(successors, data); finished = new Stack <NodeType>(); DiscoverTime = data.CreateNodeData <int>(0); RootDiscoverTime = data.CreateNodeData <int>(0); dfs.DiscoverNode += delegate(NodeType node) { DiscoverTime[node] = time; RootDiscoverTime[node] = time; time++; }; dfs.BackEdge += delegate(Edge <NodeType> edge) { if (RootDiscoverTime[edge.Target] < RootDiscoverTime[edge.Source]) { RootDiscoverTime[edge.Source] = RootDiscoverTime[edge.Target]; } }; dfs.CrossEdge += delegate(Edge <NodeType> edge) { if (RootDiscoverTime[edge.Target] < RootDiscoverTime[edge.Source]) { RootDiscoverTime[edge.Source] = RootDiscoverTime[edge.Target]; } }; dfs.FinishTreeEdge += delegate(Edge <NodeType> edge) { if (RootDiscoverTime[edge.Target] < RootDiscoverTime[edge.Source]) { RootDiscoverTime[edge.Source] = RootDiscoverTime[edge.Target]; } }; dfs.FinishNode += delegate(NodeType node) { int thisRootDiscoverTime = RootDiscoverTime[node]; if (thisRootDiscoverTime < DiscoverTime[node]) { // not a root finished.Push(node); } else { // root of a component OnBeginComponent(); OnAddNode(node); while (finished.Count > 0 && RootDiscoverTime[finished.Peek()] >= thisRootDiscoverTime) { NodeType child = finished.Pop(); OnAddNode(child); RootDiscoverTime[child] = Int32.MaxValue; // prevent child from affecting any other components } RootDiscoverTime[node] = Int32.MaxValue; // prevent node from affecting any other components OnEndComponent(); } }; }
public StrongComponents(Converter <NodeType, IEnumerable <NodeType> > successors, Converter <NodeType, IEnumerable <NodeType> > predecessors, CanCreateNodeData <NodeType> data) { dfsForward = new DepthFirstSearch <NodeType>(successors, data); finished = new Stack <NodeType>(); dfsForward.FinishNode += node => finished.Push(node); dfsBackward = new DepthFirstSearch <NodeType>(node => predecessors(node).Where(source => (dfsForward.IsVisited[source] != VisitState.Unvisited)), data); dfsBackward.DiscoverNode += OnAddNode; }
public List <NodeIndex> GetScheduleWithGroups(Converter <NodeIndex, IEnumerable <NodeIndex> > predecessors) { // toposort the forward edges to get a schedule // algorithm: create a schedule for each group and then stitch them together List <NodeIndex> schedule = new List <NodeIndex>(); if (dfsScheduleWithGroups == null) { // used by SearchFrom dfsScheduleWithGroups = new DepthFirstSearch <NodeIndex>(predecessors, this); dfsScheduleWithGroups.BackEdge += delegate(Edge <NodeIndex> edge) { List <NodeIndex> cycle = new List <NodeIndex>(); cycle.Add(edge.Target); bool found = false; dfsScheduleWithGroups.ForEachStackNode(delegate(NodeIndex node) { if (node == edge.Target) { found = true; } if (!found) { cycle.Add(node); } }); //cycle.Reverse(); NodeIndex source = cycle[cycle.Count - 1]; Debug.Write("cycle: "); Debug.Write(IsGroup(source) ? $"[{source}] " : $"{source}"); foreach (var target in cycle) { foreach (EdgeIndex edge2 in GetAllEdges(source, target)) { if (IsGroup(source)) { Debug.Write($"{g.SourceOf(edge2)}"); } Debug.Write($"->{g.TargetOf(edge2)} "); } if (IsGroup(target)) { Debug.Write($"[{target}] "); } source = target; } Debug.WriteLine(""); throw new InferCompilerException("Cycle of forward edges"); }; dfsScheduleWithGroups.FinishNode += node => groupSchedule.Add(node); } else { dfsScheduleWithGroups.Clear(); } // the top-level schedule. will only contain nodes/groups that are not in groups. List <NodeIndex> topSchedule = new List <NodeIndex>(); Dictionary <NodeIndex, List <NodeIndex> > scheduleOfGroup = new Dictionary <EdgeIndex, List <NodeIndex> >(); scheduleOfGroup[-1] = topSchedule; schedule.Clear(); // build a schedule by visiting each node and placing all predecessors on the schedule. // predecessors are added by DFS FinishNode. foreach (NodeIndex node in g.Nodes) { if (!IsGroup(node)) { SearchFrom(node, scheduleOfGroup); } } // The top-level schedule may contain references to groups, whose schedule is contained in scheduleOfGroup. // Insert the group schedules into the top-level schedule to get one combined schedule. ForEachLeafNode(topSchedule, scheduleOfGroup, schedule.Add); return(schedule); }