public static List <Tuple <Node, int, int> > SccOrdering(StrongComponent component) { if (component.nodes.Count <= 1) { return(component.nodes.Select(nd => new Tuple <Node, int, int>(nd, 0, 1)).ToList()); } var ordering = SccBfsOrdering(component); var s = ordering.First().Item2; var t = ordering .Aggregate(ordering.First().Item2, (res, cur) => res > cur.Item2 ? res : cur.Item2); var left = ordering.Skip(1).TakeWhile(a => a.Item2 < t).ToList(); var right = ordering.SkipWhile(a => a.Item2 < t).Skip(1).ToList(); var addition = 0; if (right.Count < 0 || right.Last().Item2 < 1) { addition = -right.Last().Item2 + 1; } var first = right .Select(a => new Tuple <Node, int, int>(a.Item1, a.Item2 + addition, 2)) .Concat(left.Select(a => new Tuple <Node, int, int>(a.Item1, a.Item2, right.Count > 0 ? 0 : 1))); var second = first.Append(ordering.Take(1).Select(a => new Tuple <Node, int, int>(a.Item1, a.Item2, 1)).First()); var third = second.Append(ordering.SkipWhile(a => a.Item2 < t).Take(1) .Select(a => new Tuple <Node, int, int>(a.Item1, a.Item2, 1)).First()); return(third.OrderBy(a => a.Item2).ToList()); }
private static List <System.Tuple <Node, int> > SccBfsOrdering(StrongComponent component) { //! only 1 outgoing, only 1 ingoing //! in general extremely bad approach causing many bugs => t doesnt have to be the only node on its layer found by bfs var s = component.incoming.Count == 0 ? component.nodes.First() : component.incoming.First(); //!assuming they are already sorted (p0 < p1 < p2 < ...), and well, assuming there is only 1 var t = component.outgoing.Count == 0 ? component.nodes.Last() : component.outgoing.Last(); var visited = component.nodes.ToDictionary(c => c, v => false); visited[s] = true; var order = new List <System.Tuple <Node, int> > { new System.Tuple <Node, int>(s, 0) }; var queue = new Queue <System.Tuple <Node, int> >(); queue.Enqueue(new System.Tuple <Node, int>(s, 0)); while (queue.Count > 0) { var(node, ord) = queue.Dequeue(); if (component.outgoing.Contains(node)) { continue; } foreach (var succ in node.succs .Where(nd => component.nodes.Contains(nd.Item1)) .Select(tup => tup.Item1).Where(nd => !visited[nd])) { order.Add(new System.Tuple <Node, int>(succ, ord + 1)); queue.Enqueue(order.Last()); visited[succ] = true; } } queue.Enqueue(order.Find(o => o.Item1.Equals(t))); while (queue.Count > 0) { var(node, ord) = queue.Dequeue(); foreach (var succ in node.succs .Where(nd => component.nodes.Contains(nd.Item1)) .Select(tup => tup.Item1).Where(nd => !visited[nd])) { order.Add(new System.Tuple <Node, int>(succ, ord - 1)); queue.Enqueue(order.Last()); visited[succ] = true; } } return(order); }
private static void TopoOnPetriGraph(Stack <StrongComponent> stack, StrongComponent component, int depth) { component.flag = true; component.depth = depth; if (component.outside != null) { foreach (var outside in component.outside .Where(outside => !outside.flag || outside.depth < depth + 1)) { TopoOnPetriGraph(stack, outside, depth + 1); } } stack.Push(component); }
private static void FindInAndOut(StrongComponent c, List <Node> nodes) { var res = new List <Node>(); var res2 = new List <Node>(); foreach (var cNode in c.nodes) { if (nodes.Exists(node => node.succs.Exists(nd => nd.Item1.Equals(cNode)))) { res.Add(cNode); } if (cNode.succs.Exists(nd => nodes.Exists(node => node.Equals(nd.Item1)))) { res2.Add(cNode); } } c.incoming = res.Count > 0 ? res : null; c.outgoing = res2.Count > 0 ? res2 : null; }