private void StrongConnect( ref int index, Stack <TarjanNode <TTrigger> > S, Dictionary <UpdateNode <TTrigger>, TarjanNode <TTrigger> > tarjanInfo, List <IEnumerable <UpdateNode <TTrigger> > > SCC, TarjanNode <TTrigger> v) { v.Index = index; v.LowLink = index; index++; S.Push(v); v.OnStack = true; foreach (var node in GetTriggeredNodes(v.Node.OutgoingTriggers)) { if (!tarjanInfo.TryGetValue(node, out var w)) { w = new TarjanNode <TTrigger>(node); tarjanInfo.Add(node, w); StrongConnect(ref index, S, tarjanInfo, SCC, w); v.LowLink = Math.Min(w.LowLink, v.LowLink); } else if (w.OnStack) { v.LowLink = Math.Min(v.LowLink, w.Index); } } if (v.LowLink == v.Index) { var cycle = new List <UpdateNode <TTrigger> >(); while (S.Peek() != v) { var w = S.Pop(); w.OnStack = false; cycle.Add(w.Node); } cycle.Add(S.Pop().Node); if (cycle.Count > 1) { SCC.Add(cycle); } } }
private IEnumerable <IEnumerable <UpdateNode <TTrigger> > > FindStronglyConnectedComponents(IEnumerable <TTrigger> triggers) { var startNodes = GetTriggeredNodes(triggers); var SCC = new List <IEnumerable <UpdateNode <TTrigger> > >(); var S = new Stack <TarjanNode <TTrigger> >(); var tarjanInfo = new Dictionary <UpdateNode <TTrigger>, TarjanNode <TTrigger> >(); var index = 0; foreach (var node in startNodes) { if (!tarjanInfo.TryGetValue(node, out var v)) { v = new TarjanNode <TTrigger>(node); tarjanInfo.Add(node, v); StrongConnect(ref index, S, tarjanInfo, SCC, v); } } return(SCC); }