private void put_arcs() { foreach (object node in nodes_in_graph) { StronglyConnectedComponent scc = (StronglyConnectedComponent)node2scc[node]; Debug.Assert(scc != null); // add the arcs from scc to successor SCCs foreach (object next_node in navigator.NextNodes(node)) { if (nodes_in_graph.Contains(next_node)) { StronglyConnectedComponent next = (StronglyConnectedComponent)node2scc[next_node]; Debug.Assert(next != null); scc.next_SCCs.Add(next); } } // add the arcs from scc to predecessor SCCs foreach (object prev_node in navigator.PreviousNodes(node)) { if (nodes_in_graph.Contains(prev_node)) { StronglyConnectedComponent prev = (StronglyConnectedComponent)node2scc[prev_node]; Debug.Assert(prev != null); scc.prev_SCCs.Add(prev); } } } foreach (StronglyConnectedComponent scc in all_SCCs) { scc.contains_cycle = scc.next_SCCs.Contains(scc); scc.next_SCCs.Remove(scc); scc.prev_SCCs.Remove(scc); } }
/// <summary> /// Initializes a new instance of the <see cref="Condensation"/> class. /// </summary> /// <param name="root">The root of the condensation DAG.</param> /// <param name="transitionFilter"> /// A function specifying whether the transition should be treated as an edge /// of the automaton graph while building the condensation. /// </param> /// <param name="useApproximateClosure"> /// Specifies whether <see cref="Weight.ApproximateClosure"/> should be used /// instead of <see cref="Weight.Closure"/> in semiring computations. /// </param> internal Condensation(State root, Func <Transition, bool> transitionFilter, bool useApproximateClosure) { Debug.Assert(root != null, "A valid root node must be provided."); Debug.Assert(transitionFilter != null, "A valid transition filter must be provided."); this.Root = root; this.transitionFilter = transitionFilter; this.useApproximateClosure = useApproximateClosure; this.components = new List <StronglyConnectedComponent>(); var stateIdStack = new Stack <State>(); var stateIdToTarjanInfo = new Dictionary <int, TarjanStateInfo>(); int traversalIndex = 0; this.FindStronglyConnectedComponents(this.Root, ref traversalIndex, stateIdToTarjanInfo, stateIdStack); this.stateIdToInfo = new Dictionary <int, CondensationStateInfo>(stateIdToTarjanInfo.Count); for (int i = 0; i < this.components.Count; ++i) { StronglyConnectedComponent component = this.components[i]; for (int j = 0; j < component.Size; ++j) { this.stateIdToInfo.Add(component.GetStateByIndex(j).Index, CondensationStateInfo.Default); } } }
private void StrongConnect(Vertex <T> v) { v.Index = index; v.LowLink = index; index++; stack.Push(v); foreach (Vertex <T> w in v.Dependencies) { if (w.Index < 0) { StrongConnect(w); v.LowLink = System.Math.Min(v.LowLink, w.LowLink); } else if (stack.Contains(w)) { v.LowLink = System.Math.Min(v.LowLink, w.Index); } } if (v.LowLink == v.Index) { var scc = new StronglyConnectedComponent <T>(); Vertex <T> w; do { w = stack.Pop(); scc.Add(w); } while (v != w); stronglyConnectedComponents.Add(scc); } }
private void StrongConnect(Vertex <T> v) { v.Index = _index; v.LowLink = _index; _index++; _stack.Push(v); foreach (var w1 in v.Dependencies) { if (w1.Index < 0) { StrongConnect(w1); v.LowLink = Math.Min(v.LowLink, w1.LowLink); } else if (_stack.Contains(w1)) { v.LowLink = Math.Min(v.LowLink, w1.Index); } } if (v.LowLink != v.Index) { return; } var scc = new StronglyConnectedComponent <T>(); Vertex <T> w2; do { w2 = _stack.Pop(); scc.Add(w2); } while (w2 != v); _stronglyConnectedComponents.Add(scc); }
List <string> sccOutput(List <string> files) { List <CsNode <string, string> > nodes = PerformDependencyAnalysis.dependencyAnalysis(GenerateTypeTable.TypeTableGenerator(files), files); StronglyConnectedComponent scc_obj = new StronglyConnectedComponent(); return(Display.showSCC(scc_obj.Tarjan(nodes))); }
/// <summary> /// Initializes a new instance of the <see cref="Condensation"/> class. /// </summary> /// <param name="automaton">The automaton.</param> /// <param name="root">The root of the condensation DAG.</param> /// <param name="transitionFilter"> /// A function specifying whether the transition should be treated as an edge /// of the automaton graph while building the condensation. /// </param> /// <param name="useApproximateClosure"> /// Specifies whether <see cref="Weight.ApproximateClosure"/> should be used /// instead of <see cref="Weight.Closure"/> in semiring computations. /// </param> internal Condensation( Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> automaton, State root, Func <Transition, bool> transitionFilter, bool useApproximateClosure) { Debug.Assert(transitionFilter != null, "A valid transition filter must be provided."); this.automaton = automaton; this.Root = root; this.transitionFilter = transitionFilter; this.useApproximateClosure = useApproximateClosure; this.components = this.FindStronglyConnectedComponents(); this.stateInfo = PreallocatedAutomataObjects.LeaseComputeCondensationState(); for (int i = 0; i < this.components.Count; ++i) { StronglyConnectedComponent component = this.components[i]; for (int j = 0; j < component.Size; ++j) { this.stateInfo.Add(component.GetStateByIndex(j).Index, CondensationStateInfo.Default); } } }
public void InitializeTest() { Assert.DoesNotThrow(() => _ = new StronglyConnectedComponent(0)); Assert.DoesNotThrow(() => _ = new StronglyConnectedComponent(10)); Assert.Throws <ArgumentOutOfRangeException>(() => _ = new StronglyConnectedComponent(-1)); Assert.That(new StronglyConnectedComponent(0).Length, Is.Zero); Assert.That(new StronglyConnectedComponent(10).Length, Is.EqualTo(10)); }
/// <summary> /// For each state of the component, computes the total weight of all paths starting at the root /// and ending at that state. Ending weights are not taken into account. /// </summary> /// <remarks>The weights are computed using dynamic programming, going down from the root to leafs.</remarks> private void ComputeWeightsFromRoot() { CondensationStateInfo rootInfo = this.stateIdToInfo[this.Root.Index]; rootInfo.UpwardWeightFromRoot = Weight.One; this.stateIdToInfo[this.Root.Index] = rootInfo; // Iterate in the topological order for (int currentComponentIndex = this.components.Count - 1; currentComponentIndex >= 0; --currentComponentIndex) { StronglyConnectedComponent currentComponent = this.components[currentComponentIndex]; // Propagate weights inside the component for (int srcStateIndex = 0; srcStateIndex < currentComponent.Size; ++srcStateIndex) { State srcState = currentComponent.GetStateByIndex(srcStateIndex); CondensationStateInfo srcStateInfo = this.stateIdToInfo[srcState.Index]; if (srcStateInfo.UpwardWeightFromRoot.IsZero) { continue; } for (int destStateIndex = 0; destStateIndex < currentComponent.Size; ++destStateIndex) { State destState = currentComponent.GetStateByIndex(destStateIndex); CondensationStateInfo destStateInfo = this.stateIdToInfo[destState.Index]; destStateInfo.WeightFromRoot += srcStateInfo.UpwardWeightFromRoot * currentComponent.GetWeight(srcStateIndex, destStateIndex); this.stateIdToInfo[destState.Index] = destStateInfo; } } // Compute weight contributions to downward components for (int srcStateIndex = 0; srcStateIndex < currentComponent.Size; ++srcStateIndex) { State srcState = currentComponent.GetStateByIndex(srcStateIndex); CondensationStateInfo srcStateInfo = this.stateIdToInfo[srcState.Index]; if (srcStateInfo.WeightFromRoot.IsZero) { continue; } // Aggregate weights of all the outgoing transitions from this state foreach (var transition in srcState.Transitions) { State destState = this.automaton.States[transition.DestinationStateIndex]; if (this.transitionFilter(transition) && !currentComponent.HasState(destState)) { CondensationStateInfo destStateInfo = this.stateIdToInfo[destState.Index]; destStateInfo.UpwardWeightFromRoot += srcStateInfo.WeightFromRoot * transition.Weight; this.stateIdToInfo[transition.DestinationStateIndex] = destStateInfo; } } } } this.weightsFromRootComputed = true; }
public StronglyConnectedComponents(ControlFlowGraph cfg) { this.cfg = cfg; this.sccMap = null; IEnumerable /*<StronglyConnectedComponent<CfgBlock>>*/ all_sccs = StronglyConnectedComponent.ConstructSCCs(this.cfg.Blocks(), new BackwardGraphNavigator(this.cfg)); this.sccs = GraphUtil.TopologicallySortComponentGraph(DataStructUtil.DefaultSetFactory, all_sccs); }
public void SimpleGraphTest() { var scc = new StronglyConnectedComponent(2); scc.AddEdge(0, 1); scc.AddEdge(1, 0); var graph = scc.GetGraph(); Assert.That(graph.Count, Is.EqualTo(1)); }
public void EmptyTest() { var scc0 = new StronglyConnectedComponent(0); Assert.That(scc0.GetGraph().Count, Is.Zero); var scc1 = new StronglyConnectedComponent(0); Assert.That(scc1.GetGraph().Count, Is.Zero); }
private void btnFindStronglyConnectedComponent_Click(object sender, RoutedEventArgs e) { if (draw.CurrentGraph.Nodes.Count > 0) { draw.ClearAll(); StronglyConnectedComponent.Find(draw.CurrentGraph); draw.NodeRadius = (int)sliderNodeRadius.Value; draw.Radius = (int)sliderRadius.Value; draw.DrawMainCircle(); draw.Draw(); } }
/// <summary> /// Initializes a new instance of the <see cref="EpsilonClosure"/> class. /// </summary> /// <param name="automaton">The automaton from to which <paramref name="state"/> belongs.</param> /// <param name="state">The state, which epsilon closure this instance will represent.</param> internal EpsilonClosure( Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> automaton, State state) { this.weightedStates = new List <(State, Weight)>(DefaultStateListCapacity); // Optimize for a very common case: a single-node closure bool singleNodeClosure = true; Weight selfLoopWeight = Weight.Zero; foreach (var transition in state.Transitions) { if (transition.IsEpsilon) { if (transition.DestinationStateIndex != state.Index) { singleNodeClosure = false; break; } selfLoopWeight += transition.Weight; } } if (singleNodeClosure) { Weight stateWeight = Weight.ApproximateClosure(selfLoopWeight); this.weightedStates.Add((state, stateWeight)); this.EndWeight = stateWeight * state.EndWeight; } else { Condensation condensation = automaton.ComputeCondensation(state, tr => tr.IsEpsilon, true); for (int i = 0; i < condensation.ComponentCount; ++i) { StronglyConnectedComponent component = condensation.GetComponent(i); for (int j = 0; j < component.Size; ++j) { State componentState = component.GetStateByIndex(j); this.weightedStates.Add((componentState, condensation.GetWeightFromRoot(componentState))); } } this.EndWeight = condensation.GetWeightToEnd(state.Index); } }
/// <summary> /// Initializes a new instance of the <see cref="EpsilonClosure"/> class. /// </summary> /// <param name="state">The state, which epsilon closure this instance will represent.</param> internal EpsilonClosure(State state) { Argument.CheckIfValid(!state.IsNull, nameof(state)); // Optimize for a very common case: a single-node closure bool singleNodeClosure = true; Weight selfLoopWeight = Weight.Zero; for (int i = 0; i < state.TransitionCount; ++i) { Transition transition = state.GetTransition(i); if (transition.IsEpsilon) { if (transition.DestinationStateIndex != state.Index) { singleNodeClosure = false; break; } selfLoopWeight = Weight.Sum(selfLoopWeight, transition.Weight); } } if (singleNodeClosure) { Weight stateWeight = Weight.ApproximateClosure(selfLoopWeight); this.weightedStates.Add(Pair.Create(state, stateWeight)); this.EndWeight = Weight.Product(stateWeight, state.EndWeight); } else { Condensation condensation = state.Owner.ComputeCondensation(state, tr => tr.IsEpsilon, true); for (int i = 0; i < condensation.ComponentCount; ++i) { StronglyConnectedComponent component = condensation.GetComponent(i); for (int j = 0; j < component.Size; ++j) { State componentState = component.GetStateByIndex(j); this.weightedStates.Add(Pair.Create(componentState, condensation.GetWeightFromRoot(componentState))); } } this.EndWeight = condensation.GetWeightToEnd(state); } }
/// <summary> /// For each state of the component, computes the total weight of all paths starting at that state. /// Ending weights are taken into account. /// </summary> /// <remarks>The weights are computed using dynamic programming, going up from leafs to the root.</remarks> private void ComputeWeightsToEnd() { // Iterate in the reverse topological order for (int currentComponentIndex = 0; currentComponentIndex < this.components.Count; ++currentComponentIndex) { StronglyConnectedComponent currentComponent = this.components[currentComponentIndex]; // Update end weights in this component based on outgoing transitions to downward components for (int stateIndex = 0; stateIndex < currentComponent.Size; ++stateIndex) { State state = currentComponent.GetStateByIndex(stateIndex); // Aggregate weights of all the outgoing transitions from this state Weight weightToAdd = state.EndWeight; for (int transitionIndex = 0; transitionIndex < state.TransitionCount; ++transitionIndex) { Transition transition = state.GetTransition(transitionIndex); State destState = state.Owner.states[transition.DestinationStateIndex]; if (this.transitionFilter(transition) && !currentComponent.HasState(destState)) { weightToAdd = Weight.Sum( weightToAdd, Weight.Product(transition.Weight, this.stateIdToInfo[transition.DestinationStateIndex].WeightToEnd)); } } // We can go from any state of the component to the current state if (!weightToAdd.IsZero) { for (int updatedStateIndex = 0; updatedStateIndex < currentComponent.Size; ++updatedStateIndex) { State updatedState = currentComponent.GetStateByIndex(updatedStateIndex); CondensationStateInfo updatedStateInfo = this.stateIdToInfo[updatedState.Index]; updatedStateInfo.WeightToEnd = Weight.Sum( updatedStateInfo.WeightToEnd, Weight.Product(currentComponent.GetWeight(updatedStateIndex, stateIndex), weightToAdd)); this.stateIdToInfo[updatedState.Index] = updatedStateInfo; } } } } this.weightsToEndComputed = true; }
static void Main(string[] args) { Console.Write("\nDemonstrating Project 3: Type Based Package Dependency Analysis"); Console.Write("\n=================================================================\n"); ShowCommandLine(args); List <List <Elem> > tableList = new List <List <Elem> >(); List <string> files = ProcessCommandline(args); tableList = GenerateTypeTable.TypeTableGenerator(files); DisplayRequirement1(tableList); List <CsNode <string, string> > nodes = PerformDependencyAnalysis.dependencyAnalysis(tableList, files); DisplayRequirement2(nodes); StronglyConnectedComponent scc_obj = new StronglyConnectedComponent(); List <string> scc = scc_obj.Tarjan(nodes); DisplayRequirement3(scc); Console.Read(); }
private static void StrongConnect(IVertex vertex, IGraph graph, Stack <IVertex> vertexStack, List <StronglyConnectedComponent> strongConnectedComponents, ref uint index) { var algorithmData = (TarjanStrongConnectedComponentAlgorithmData)vertex.AlgorithmData; algorithmData.Index = index; algorithmData.LowLink = index; index++; vertexStack.Push(vertex); algorithmData.IsOnStack = true; foreach (var adjacentVertex in GetAdjacentVertices(graph, vertex)) { var adjacentAlgorithmData = (TarjanStrongConnectedComponentAlgorithmData)adjacentVertex.AlgorithmData; if (!adjacentAlgorithmData.Index.HasValue) { StrongConnect(adjacentVertex, graph, vertexStack, strongConnectedComponents, ref index); algorithmData.LowLink = Math.Min(algorithmData.LowLink.Value, adjacentAlgorithmData.LowLink.Value); } else if (adjacentAlgorithmData.IsOnStack) { algorithmData.LowLink = Math.Min(algorithmData.LowLink.Value, adjacentAlgorithmData.Index.Value); } } if (algorithmData.LowLink == algorithmData.Index) { IVertex stackVertex; var strongConnectedComponent = new StronglyConnectedComponent(); do { stackVertex = vertexStack.Pop(); var stackVertexAlgorithmData = (TarjanStrongConnectedComponentAlgorithmData)stackVertex.AlgorithmData; stackVertexAlgorithmData.IsOnStack = false; strongConnectedComponent.Add(stackVertex); } while (!stackVertex.Equals(vertex)); strongConnectedComponents.Add(strongConnectedComponent); } }
/// <summary> /// Initializes a new instance of the <see cref="Condensation"/> class. /// </summary> /// <param name="root">The root of the condensation DAG.</param> /// <param name="transitionFilter"> /// A function specifying whether the transition should be treated as an edge /// of the automaton graph while building the condensation. /// </param> /// <param name="useApproximateClosure"> /// Specifies whether <see cref="Weight.ApproximateClosure"/> should be used /// instead of <see cref="Weight.Closure"/> in semiring computations. /// </param> internal Condensation(State root, Func <Transition, bool> transitionFilter, bool useApproximateClosure) { Debug.Assert(transitionFilter != null, "A valid transition filter must be provided."); this.Root = root; this.transitionFilter = transitionFilter; this.useApproximateClosure = useApproximateClosure; this.components = this.FindStronglyConnectedComponents(); this.stateIdToInfo = new Dictionary <int, CondensationStateInfo>(); for (int i = 0; i < this.components.Count; ++i) { StronglyConnectedComponent component = this.components[i]; for (int j = 0; j < component.Size; ++j) { this.stateIdToInfo.Add(component.GetStateByIndex(j).Index, CondensationStateInfo.Default); } } }
/// <summary> /// For each state of the component, computes the total weight of all paths starting at that state. /// Ending weights are taken into account. /// </summary> /// <remarks>The weights are computed using dynamic programming, going up from leafs to the root.</remarks> private void ComputeWeightsToEnd() { // Iterate in the reverse topological order for (int currentComponentIndex = 0; currentComponentIndex < this.components.Count; ++currentComponentIndex) { StronglyConnectedComponent currentComponent = this.components[currentComponentIndex]; // Update end weights in this component based on outgoing transitions to downward components for (int stateIndex = 0; stateIndex < currentComponent.Size; ++stateIndex) { State state = currentComponent.GetStateByIndex(stateIndex); // Aggregate weights of all the outgoing transitions from this state Weight weightToAdd = state.EndWeight; foreach (var transition in state.Transitions) { State destState = this.automaton.States[transition.DestinationStateIndex]; if (this.transitionFilter(transition) && !currentComponent.HasState(destState)) { weightToAdd += transition.Weight * this.stateInfo[transition.DestinationStateIndex].WeightToEnd; } } // We can go from any state of the component to the current state if (!weightToAdd.IsZero) { for (int updatedStateIndex = 0; updatedStateIndex < currentComponent.Size; ++updatedStateIndex) { State updatedState = currentComponent.GetStateByIndex(updatedStateIndex); CondensationStateInfo updatedStateInfo = this.stateInfo[updatedState.Index]; updatedStateInfo.WeightToEnd += currentComponent.GetWeight(updatedStateIndex, stateIndex) * weightToAdd; this.stateInfo.Update(updatedState.Index, updatedStateInfo); } } } } this.weightsToEndComputed = true; }
public static void Solve() { var NM = Console.ReadLine().Split(" ").Select(int.Parse).ToArray(); var(N, M) = (NM[0], NM[1]); var G = new StronglyConnectedComponent(N); for (var i = 0; i < M; i++) { var UV = Console.ReadLine().Split(" ").Select(int.Parse).ToArray(); var(u, v) = (UV[0], UV[1]); G.AddEdge(u, v); } var scc = G.GetGraph(); Console.WriteLine(scc.Count()); foreach (var v in scc) { Console.WriteLine($"{v.Count()} {string.Join(" ", v)}"); } }
public static void Solve() { var(N, M) = Scanner.Scan <int, int>(); var scc = new StronglyConnectedComponent(N); for (var i = 0; i < M; i++) { var(a, b) = Scanner.Scan <int, int>(); a--; b--; scc.AddEdge(a, b); } var answer = 0L; foreach (var group in scc.GetGraph()) { var c = (long)group.Count(); answer += c * (c - 1) / 2; } Console.WriteLine(answer); }
//function initiates dependency analysis public static List <CsNode <string, string> > dependencyAnalysis(List <List <Elem> > tableList, List <string> files) { var graph = new List <Tuple <string, string> >(); List <FindDependency> dataOfTypeUsing = new List <FindDependency>(); List <FindDependency> dataOfTypeNameSpace = new List <FindDependency>(); foreach (List <Elem> table in tableList) { foreach (Elem e in table) { if (e.type.Equals("namespace")) { FindDependency findDependency_obj = new FindDependency(); findDependency_obj.FileName = e.FileName; findDependency_obj.NameOfType = e.name; dataOfTypeNameSpace.Add(findDependency_obj); } if (e.type.Equals("using") || e.type.Equals("alias")) { FindDependency findDependency_obj = new FindDependency(); findDependency_obj.FileName = e.FileName; findDependency_obj.NameOfType = e.name; if (e.type.Equals("alias") && !e.aliasName.StartsWith("System")) { findDependency_obj.AliasName = e.aliasName; } dataOfTypeUsing.Add(findDependency_obj); } } } FirstParse(dataOfTypeUsing, dataOfTypeNameSpace, tableList, files, graph); Console.WriteLine("\n"); StronglyConnectedComponent obj = new StronglyConnectedComponent(); List <CsNode <string, string> > nodes = obj.graphAccept(graph, files); return(nodes); }
private void create_new_SCC (object node) { current_scc = new StronglyConnectedComponent(scc_id++); all_SCCs.Add(current_scc); }
public void Add(StronglyConnectedComponent <T> scc) => collection.AddLast(scc);
public void InvalidAddEdgeTest(int u, int v) { var scc = new StronglyConnectedComponent(2); Assert.Throws <ArgumentOutOfRangeException>(() => scc.AddEdge(u, v)); }
private void create_new_SCC(object node) { current_scc = new StronglyConnectedComponent(scc_id++); all_SCCs.Add(current_scc); }