static void Main() { //var graph = new Dictionary<string, List<string>>() //{ // { "IDEs", new List<string>() { "variables", "loops" } }, // { "variables", new List<string>() { "conditionals", "loops", "bits" } }, // { "loops", new List<string>() { "bits" } }, // { "conditionals", new List<string>() { "loops" } }, //}; var graph = new Dictionary<string, List<string>>() { { "A", new List<string>() { "B", "C" } }, { "B", new List<string>() { "D", "E" } }, { "C", new List<string>() { "F" } }, { "D", new List<string>() { "C", "F" } }, { "E", new List<string>() { "D" } }, { "F", new List<string>() { } }, }; var topSorter = new TopologicalSorter(graph); var sortedNodes = topSorter.TopSort(); Console.WriteLine("Topological sorting: {0}", string.Join(", ", sortedNodes)); // Topological sorting: A, B, E, D, C, F }
public void Sort_MultipleElementsOneDependencyDeep_CanSortByDependency() { // Arrange var a = new SortItem("A"); var c = new SortItem("C"); var f = new SortItem("F"); var h = new SortItem("H"); var d = new SortItem("D"); var g = new SortItem("G"); var e = new SortItem("E"); var b = new SortItem("B"); d.SetDependencies(a); g.SetDependencies(f); e.SetDependencies(d); b.SetDependencies(c); var unsorted = new[] { a, b, c, d, e, f, g, h }; // Act TopologicalSorter topologicalSorter = new TopologicalSorter(); var sorted = topologicalSorter.Sort(unsorted, x => x.Dependencies, new SortItemEqualityComparer()); // Assert Assert.Equal(8, sorted.Count); Assert.Equal("A", sorted[0].Name); Assert.Equal("C", sorted[1].Name); Assert.Equal("B", sorted[2].Name); Assert.Equal("D", sorted[3].Name); Assert.Equal("E", sorted[4].Name); Assert.Equal("F", sorted[5].Name); Assert.Equal("G", sorted[6].Name); Assert.Equal("H", sorted[7].Name); }
public void TestTopSortAcyclicGraph2Vertices() { // Arrange var graph = new Dictionary<string, List<string>> { { "First", new List<string> { "Second" } }, { "Second", new List<string> { } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert this.AssertTopologicallySorted(graph, sortedNodes); }
public void TestTopSortAcyclicGraph5Vertices() { // Arrange var graph = new Dictionary<string, List<string>>() { { "IDEs", new List<string>() { "variables", "loops" } }, { "variables", new List<string>() { "conditionals", "loops", "bits" } }, { "loops", new List<string>() { "bits" } }, { "conditionals", new List<string>() { "loops" } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert AssertTopologicallySorted(graph, sortedNodes); }
static void Main() { //var graph = new Dictionary<string, List<string>>() //{ // { "IDEs", new List<string>() { "variables", "loops" } }, // { "variables", new List<string>() { "conditionals", "loops", "bits" } }, // { "loops", new List<string>() { "bits" } }, // { "conditionals", new List<string>() { "loops" } }, //}; var graph = new Dictionary <string, List <string> >() { { "A", new List <string>() { "B", "C" } }, { "B", new List <string>() { "D", "E" } }, { "C", new List <string>() { "F" } }, { "D", new List <string>() { "C", "F" } }, { "E", new List <string>() { "D" } }, { "F", new List <string>() { } }, }; var topSorter = new TopologicalSorter(graph); var sortedNodes = topSorter.TopSort(); Console.WriteLine("Topological sorting: {0}", string.Join(", ", sortedNodes)); // Topological sorting: A, B, E, D, C, F }
public static List <T> TopologicalSort <T>(this IReadOnlyCollection <T> collection, Func <T, IEnumerable <T> > getDependentsFunc) where T : IEquatable <T> { var edges = new List <Tuple <T, T> >(); foreach (var item in collection) { var dependents = getDependentsFunc(item); foreach (var dependent in dependents) { edges.Add(new Tuple <T, T>(item, dependent)); } } var sorted = TopologicalSorter <T> .Sort(collection, edges); return(sorted); }
public void TestTopSortAcyclicGraph2Vertices() { // Arrange var graph = new Dictionary <string, List <string> >() { { "First", new List <string>() { "Second" } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List <string>(topSorter.TopSort()); // Assert AssertTopologicallySorted(graph, sortedNodes); }
public void InsertEdgeOrdered(char a, char b) { var an = adj[a]; var bn = adj[b]; if (!an.children.ContainsKey(b)) { var list = TopologicalSorter.Sort(an); foreach (var c in list) { if (c == b) { return; } } an.children.Add(b, bn); } }
/// <summary> /// Write the entire structure to the given writer. /// </summary> internal void WriteTo(BinaryWriter writer) { new ModelSorter().Collect(dex); //new ModelShuffler().Collect(Dex); map.Clear(); stringLookup = CollectStrings(); typeLookup = CollectTypeReferences(); methodLookup = CollectMethodReferences(); fieldLookup = CollectFieldReferences(); prototypeLookup = CollectPrototypes(); flatClasses = ClassDefinition.Flattenize(dex.Classes); // Standard sort then topological sort var tsorter = new TopologicalSorter(); var classDefinitionComparer = new ClassDefinitionComparer(); flatClasses.Sort(classDefinitionComparer); flatClasses = new List <ClassDefinition>(tsorter.TopologicalSort(flatClasses, classDefinitionComparer)); WriteHeader(writer); WriteStringId(writer); WriteTypeId(writer); WritePrototypeId(writer); WriteFieldId(writer); WriteMethodId(writer); WriteClassDef(writer); WriteAnnotationSetRefList(writer); WriteAnnotationSet(writer); WriteCodeItems(writer); WriteAnnotationsDirectoryItems(writer); WriteTypeLists(writer); WriteStringData(writer); WriteDebugInfo(writer); WriteAnnotations(writer); WriteEncodedArray(writer); WriteClassData(writer); WriteMapList(writer); ComputeSHA1Signature(writer); ComputeAdlerCheckSum(writer); }
public void TestTopSortAcyclicGraph8Vertices() { // Arrange var graph = new Dictionary <string, List <string> >() { { "H", new List <string>() { "G" } }, { "G", new List <string>() { } }, { "B", new List <string>() { "A" } }, { "A", new List <string>() { } }, { "F", new List <string>() { "B", "C", "E" } }, { "C", new List <string>() { "A" } }, { "E", new List <string>() { "C", "A" } }, { "D", new List <string>() { "A", "B" } }, }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List <string>(topSorter.TopSort()); // Assert AssertTopologicallySorted(graph, sortedNodes); }
public void TestTopSortGraph7VerticesWithCycle() { // Arrange var graph = new Dictionary <string, List <string> >() { { "A", new List <string>() { "B" } }, { "B", new List <string>() { "C" } }, { "C", new List <string>() { "D", "E" } }, { "D", new List <string>() { "E" } }, { "E", new List <string>() { "F", "C" } }, { "F", new List <string>() { } }, { "Z", new List <string>() { "A" } } }; // Act Assert.Throws <InvalidOperationException>(() => { var topSorter = new TopologicalSorter(graph); var sortedNodes = new List <string>(topSorter.TopSort()); }); }
public void Sort_FirstOrderCircularDependency_ThrowsSortException() { // Arrange var a = new SortItem("A"); var c = new SortItem("C"); a.SetDependencies(c); c.SetDependencies(a); var unsorted = new[] { a, c }; // Act and Assert TopologicalSorter topologicalSorter = new TopologicalSorter(); CircularDependencyException<SortItem> exception = Assert.Throws<CircularDependencyException<SortItem>>( () => topologicalSorter.Sort(unsorted, x => x.Dependencies, new SortItemEqualityComparer())); Assert.Equal(1, exception.AffectedItems.Count); Assert.Equal("A", exception.AffectedItems[0].Name); }
/// <summary> /// Collects all dependency nodes recursively, and sorts them in a topological order such that the final collection /// of nodes can be executed sequentially. /// </summary> /// <param name="node">The node to find all dependencies for.</param> /// <param name="flags">Flags that influence the behaviour of the algorithm.</param> /// <typeparam name="T">The type of contents that each node contains.</typeparam> /// <returns>The topological ordering of all dependencies of the node.</returns> /// <exception cref="CyclicDependencyException">Occurs when there is a cyclic dependency in the graph.</exception> public static IEnumerable <DataFlowNode <T> > GetOrderedDependencies <T>(this DataFlowNode <T> node, DependencyCollectionFlags flags) { try { var topologicalSorting = new TopologicalSorter <DataFlowNode <T> >(GetSortedOutgoingEdges); return(topologicalSorting.GetTopologicalSorting(node)); } catch (CycleDetectedException ex) { throw new CyclicDependencyException("Cyclic dependency was detected.", ex); } IReadOnlyList <DataFlowNode <T> > GetSortedOutgoingEdges(DataFlowNode <T> n) { var result = new List <DataFlowNode <T> >(); // Prioritize stack dependencies over variable dependencies. if ((flags & DependencyCollectionFlags.IncludeStackDependencies) != 0) { foreach (var dependency in n.StackDependencies) { if (dependency.HasKnownDataSources) { result.Add(dependency.First().Node); } } } if ((flags & DependencyCollectionFlags.IncludeVariableDependencies) != 0) { foreach (var entry in n.VariableDependencies) { if (entry.Value.HasKnownDataSources) { result.Add(entry.Value.First().Node); } } } return(result); } }
private IEnumerable <TrackedItem> GetOrderedItems() { var items = (from tab in this.GetTables() from ti in ((ITrackedTable)tab).TrackedItems where ti.State != SubmitAction.None select ti).ToList(); // build edge map to represent all references between entities var edges = this.GetEdges(items).Distinct().ToList(); var stLookup = edges.ToLookup(e => e.Source, e => e.Target); var tsLookup = edges.ToLookup(e => e.Target, e => e.Source); return(TopologicalSorter.Sort(items, item => { switch (item.State) { case SubmitAction.Insert: case SubmitAction.InsertOrUpdate: // all things this instance depends on must come first var beforeMe = stLookup[item]; // if another object exists with same key that is being deleted, then the delete must come before the insert object cached = item.Table.GetFromCacheById(this.provider.Mapping.GetPrimaryKey(item.Entity, item.Instance)); if (cached != null && cached != item.Instance) { var ti = item.Table.GetTrackedItem(cached); if (ti != null && ti.State == SubmitAction.Delete) { beforeMe = beforeMe.Concat(new[] { ti }); } } return beforeMe; case SubmitAction.Delete: // all things that depend on this instance must come first return tsLookup[item]; default: return TrackedItem.EmptyList; } })); }
/// <summary> /// Processes a list of application versions and their dependencies ready for sorting. /// </summary> /// <param name="requiredAppVersions">The list of required app versions.</param> /// <param name="sorter">The topological sorter.</param> /// <param name="ids">The full indexed list of ids.</param> /// <param name="currentId">The current id that owns the required app versions.</param> private void AddRequiredAppVersionEdgesToSorter( IEnumerable <ManagedAppVersion> requiredAppVersions, TopologicalSorter sorter, IList <Guid> ids, Guid currentId) { foreach (var req in requiredAppVersions) { if (req.VersionId == null || req.VersionId.Value == Guid.Empty) { continue; } // required app version --> dependent app/app version sorter.AddEdge(ids.IndexOf(req.VersionId.Value), ids.IndexOf(currentId)); AddRequiredAppEdgesToSorter(req.RequiredApps, sorter, ids, req.VersionId.Value); AddRequiredAppVersionEdgesToSorter(req.RequiredAppVersions, sorter, ids, req.VersionId.Value); } }
private IEnumerable <JsClass> GetStaticInitializationOrder(IEnumerable <JsClass> types, int pass) { if (pass > 3) { return(types); // If we can't find a non-circular order after 3 passes, just use some random order. } // We run the algorithm in 3 passes, each considering less types of references than the previous one. var dict = types.ToDictionary(t => t.CSharpTypeDefinition, t => new { deps = GetStaticInitializationDependencies(t, pass), backref = t }); var edges = from s in dict from t in s.Value.deps where dict.ContainsKey(t) select Edge.Create(s.Key, t); var result = new List <JsClass>(); foreach (var group in TopologicalSorter.FindAndTopologicallySortStronglyConnectedComponents(dict.Keys.ToList(), edges)) { var backrefed = group.Select(t => dict[t].backref); result.AddRange(group.Count > 1 ? GetStaticInitializationOrder(backrefed.ToList(), pass + 1) : backrefed); } return(result); }
public void Sort_WithCyclicDependency_ThrowsException() { var list = new List <SortableEntity>() { new SortableEntity(1, 2), new SortableEntity(2, 3), new SortableEntity(3, 4), new SortableEntity(4, 5), new SortableEntity(5, 1), }; Assert.Throws <CyclicDependencyException>(() => { var result = TopologicalSorter.Sort( list, (item, source) => source.Where(l => l.MyId == item.DependentOnId), true ); }); }
public void Can_sort() { var list = new List <string> { "A", "B", "C" }; var edges = new List <Tuple <string, string> > { new Tuple <string, string>("C", "A"), // A depends on C new Tuple <string, string>("B", "C") // C depends on B }; var sorted = TopologicalSorter <string> .Sort(list, edges); Assert.NotNull(sorted); foreach (var entry in sorted) { _output.WriteLine(entry); } }
public void Sort_WithCyclicDependencyAndNoThrowOption_DoesNotThrowsException() { var list = new List <SortableEntity>() { new SortableEntity(1, 5), new SortableEntity(2, 4), new SortableEntity(3, 3), new SortableEntity(4, 2), new SortableEntity(5, 1), }; var result = TopologicalSorter.Sort( list, (item, source) => source.Where(l => l.MyId == item.DependentOnId), false ); var stringResult = string.Join(',', result.Select(r => r.MyId)); Assert.Equal("5,1,4,2,3", stringResult); }
/// <summary> /// Sorts <paramref name="values"/> in topological order according to <paramref name="edgeTester"/>. /// </summary> /// <typeparam name="TValue">Type of a value to sort.</typeparam> /// <param name="values">Values to sort.</param> /// <param name="edgeTester">A predicate for testing edge presence.</param> /// <returns>Topologically sorted <paramref name="values"/> if no cycles exist, otherwise null.</returns> public static List <TValue> SortTopologically <TValue>(this IEnumerable <TValue> values, Func <TValue, TValue, bool> edgeTester) { ArgumentValidator.EnsureArgumentNotNull(values, "values"); ArgumentValidator.EnsureArgumentNotNull(edgeTester, "edgeTester"); var graph = new Graph <Node <TValue>, Edge>(); graph.Nodes.AddRange(values.Select(p => new Node <TValue>(p))); foreach (var left in graph.Nodes) { foreach (var right in graph.Nodes) { if (edgeTester.Invoke(left.Value, right.Value)) { new Edge(left, right); } } } var result = TopologicalSorter.Sort(graph); return(result.HasLoops ? null : result.SortedNodes.Select(node => node.Value).ToList()); }
public void RemoveWholeNodeTest() { var node1 = new Node <int, string>(1); var node2 = new Node <int, string>(2); var connection12_1 = new NodeConnection <int, string>(node1, node2, "ConnectionItem 1->2 1"); connection12_1.BindToNodes(); var connection12_2 = new NodeConnection <int, string>(node1, node2, "ConnectionItem 1->2 2"); connection12_2.BindToNodes(); var connection21_1 = new NodeConnection <int, string>(node2, node1, "ConnectionItem 2->1 1"); connection21_1.BindToNodes(); // Remove edge by edge. List <NodeConnection <int, string> > removedEdges; List <int> result = TopologicalSorter.Sort(new[] { node2, node1 }, out removedEdges); Assert.AreEqual(2, result.Count); Assert.AreEqual(node1.Item, result[0]); Assert.AreEqual(node2.Item, result[1]); Assert.AreEqual(1, removedEdges.Count); Assert.AreEqual(connection21_1, removedEdges[0]); // Remove whole node connection12_1.BindToNodes(); connection12_2.BindToNodes(); connection21_1.BindToNodes(); result = TopologicalSorter.Sort(new[] { node2, node1 }, out removedEdges, true); Assert.AreEqual(2, result.Count); Assert.AreEqual(node1.Item, result[1]); Assert.AreEqual(node2.Item, result[0]); Assert.AreEqual(2, removedEdges.Count); Assert.AreEqual(0, removedEdges.Except(new[] { connection12_1, connection12_2 }).Count()); }
/// <summary> /// Orders a collection of UpdatePackage instances into the correct execution /// order, making sure dependencies are taken into consideration. /// </summary> /// <param name="packages">update packages to sort.</param> /// <returns>Enumerable collection of update packages, sorted into the correct order.</returns> public ICollection <UpdatePackage> Order(ICollection <UpdatePackage> packages) { // Build a collection of dependency instances to use in sorting var dependentModuleLookup = packages .Where(p => !EnumerableHelper.IsNullOrEmpty(p.DependentModules)) .SelectMany(p => p.DependentModules) .Distinct() .ToDictionary(k => k, v => packages.Where(p => p.ModuleIdentifier == v)); // Make sure Cofoundry packages are installed first, even if someone has forgotten // to mark it as a dependency. Use secondary sorting to ensure deterministic ordering. var orderedPackages = packages .OrderByDescending(p => p.ModuleIdentifier == CofoundryModuleInfo.ModuleIdentifier) .ThenBy(p => p.ModuleIdentifier) .ThenBy(p => p.GetType().FullName) .ToList(); // Sort based on dependencies var topologicallySortedPackages = TopologicalSorter.Sort(orderedPackages, (p, l) => FindDependencies(p, dependentModuleLookup), true); return(topologicallySortedPackages); }
/// <summary> /// Constructs the tree of scopes and basic blocks based on the provided control flow graph. /// </summary> /// <param name="cfg">The control flow graph.</param> /// <returns>The root scope.</returns> public ScopeBlock <TInstruction> ConstructBlocks(ControlFlowGraph <TInstruction> cfg) { // Sort the nodes in topological order, where we ignore cyclic dependencies. var sorter = new TopologicalSorter <ControlFlowNode <TInstruction> >(ChildrenLister) { IgnoreCycles = true }; var sorting = sorter .GetTopologicalSorting(cfg.Entrypoint) .Reverse() #if DEBUG .ToArray() #endif ; // We maintain a stack of scope information. Every time we enter a new region, we enter a new scope, // and similarly, we leave a scope when we leave a region. var rootScope = new ScopeBlock <TInstruction>(); var scopeStack = new IndexableStack <ScopeInfo>(); scopeStack.Push(new ScopeInfo(cfg, rootScope)); // Add the nodes in the order of the sorting. foreach (var node in sorting) { var currentScope = scopeStack.Peek(); if (node.ParentRegion != currentScope.Region) { UpdateScopeStack(node, scopeStack); currentScope = scopeStack.Peek(); } currentScope.AddBlock(node.Contents); } return(rootScope); }
private static void InternalPerformanceTest(int nodeCount, int averageConnectionCount, bool allowLoops) { TestLog.Info("Building graph: {0} nodes, {1} connections/node in average.", nodeCount, averageConnectionCount); var rnd = new Random(); var nodes = new List <Node <int, int> >(); for (int i = 0; i < nodeCount; i++) { nodes.Add(new Node <int, int>(i)); } int connectionCount = 0; foreach (var from in nodes) { int outgoingConnectionCount = rnd.Next(averageConnectionCount); for (int i = 0; i < outgoingConnectionCount; i++) { var to = nodes[rnd.Next(allowLoops ? nodeCount : @from.Item)]; if (from == to) { continue; } var c = new NodeConnection <int, int>(@from, to, connectionCount++); c.BindToNodes(); } } GC.GetTotalMemory(true); using (new Measurement("Sorting", nodeCount + connectionCount)) { List <Node <int, int> > removedEdges; var result = TopologicalSorter.Sort(nodes, out removedEdges); if (!allowLoops) { Assert.AreEqual(nodeCount, result.Count); } } GC.GetTotalMemory(true); }
public void TestTopSortGraph7VerticesWithCycle() { // Arrange var graph = new Dictionary <string, List <string> >() { { "A", new List <string>() { "B" } }, { "B", new List <string>() { "C" } }, { "C", new List <string>() { "D", "E" } }, { "D", new List <string>() { "E" } }, { "E", new List <string>() { "F", "C" } }, { "F", new List <string>() { } }, { "Z", new List <string>() { "A" } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List <string>(topSorter.TopSort()); }
public void TestGlobalSort <T>(Func <Dex, List <T> > provider, IComparer <T> comparer) { foreach (var file in Directory.GetFiles(FilesDirectory)) { TestContext.WriteLine("Testing {0}", file); var dex = Dex.Read(file); var items = new List <T>(provider(dex)); items.Shuffle(); items.Sort(comparer); if (comparer is IPartialComparer <T> ) { var tsorter = new TopologicalSorter(); items = new List <T>(tsorter.TopologicalSort(items, comparer as IPartialComparer <T>)); } for (var i = 0; i < items.Count; i++) { Assert.AreEqual(items[i], provider(dex)[i]); } } }
private void TestSort <T>(T[] nodeValues, Predicate <T, T> connector, T[] expected, T[] loops) { // WIth edge breaker, that breaks only self-referencing edges var nodes = nodeValues.Select(v => new Node <T>(v)).ToList(); var graph = new Graph <Node <T>, Edge>(nodes); graph.AddEdges((s, t) => connector(s.Value, t.Value) ? new Edge(s, t) : null); int selfReferencingEdgeCount = graph.Edges.Count(e => e.Source == e.Target); var result = TopologicalSorter.Sort(graph, e => e.Source == e.Target); var actual = result.SortedNodes.Select(n => n.Value).ToArray(); var actualLoops = result.LoopNodes.Select(n => n.Value).ToArray(); AssertEx.HasSameElements(expected, actual); AssertEx.HasSameElements(loops, actualLoops); Assert.AreEqual(selfReferencingEdgeCount, result.BrokenEdges.Count); // With edge breaker (any edge can be broken) nodes = nodeValues.Select(v => new Node <T>(v)).ToList(); graph = new Graph <Node <T>, Edge>(nodes); graph.AddEdges((s, t) => connector(s.Value, t.Value) ? new Edge(s, t) : null); result = TopologicalSorter.Sort(graph, e => true); actual = result.SortedNodes.Select(n => n.Value).ToArray(); actualLoops = result.LoopNodes.Select(n => n.Value).ToArray(); Assert.AreEqual(nodeValues.Length, actual.Length); Assert.AreEqual(0, actualLoops.Length); if (loops.Length == 0) { Assert.AreEqual(selfReferencingEdgeCount, result.BrokenEdges.Count); } else { Assert.AreNotEqual(selfReferencingEdgeCount, result.BrokenEdges.Count); } }
public void TestPerformanceGraph1000Vertices() { // Arrange const int NodesCount = 1000; var graph = new Dictionary<string, List<string>>(); for (int i = 0; i < NodesCount; i++) { graph["node" + i] = new List<string>(); } for (int i = 0; i < NodesCount - 50; i++) { for (int c = 25; c < i % 50; c++) { graph["node" + i].Add("node" + (i + c)); } } // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert this.AssertTopologicallySorted(graph, sortedNodes); }
public void Instance04Test() // aus Sedgewick: Algorithmen, Abb. 32.8, S. 543 { var iGraph = new Graph(); iGraph.Nodes = new Node[] { new Node // A { Id = 1, SuccessorIds = new int[] { 6, 2, 3, 7 } }, new Node // B { Id = 2, SuccessorIds = new int[] {} }, new Node // C { Id = 3, SuccessorIds = new int[] {} }, new Node // D { Id = 4, SuccessorIds = new int[] {} }, new Node // E { Id = 5, SuccessorIds = new int[] { 4 } }, new Node // F { Id = 6, SuccessorIds = new int[] { 4, 5 } }, new Node // G { Id = 7, SuccessorIds = new int[] { 3, 5, 8 } }, new Node // H { Id = 8, SuccessorIds = new int[] { 9 } }, new Node // I { Id = 9, SuccessorIds = new int[] {} }, new Node // J { Id = 10, SuccessorIds = new int[] { 7, 11, 12, 13 } }, new Node // K { Id = 11, SuccessorIds = new int[] {} }, new Node // L { Id = 12, SuccessorIds = new int[] { 7, 13 } }, new Node // M { Id = 13, SuccessorIds = new int[] {} } }; iGraph.PrepareSuccessors(); var HasCycle = false; var Result = TopologicalSorter.Sort(iGraph.Nodes, iNode => iNode.Successors, out HasCycle); // generated result // 10 (J), 12 (L), 13 (M), 11 (K), 1 (A), // 7 (G), 8 (H), 9 (I), 3 (C), 2 (B), // 6 (F), 5 (E), 4 (D) // dfs visiting sequence // 1 (A), 6 (F), 4 (D), 5 (E), 2 (B), // 3 (C), 7 (G), 8 (H), 9 (I), 10 (J), // 11 (K), 12 (L), 13 (M) Assert.IsTrue(IsTopologicalSort(Result, iNode => iNode.Successors)); }
public void Instance03Test() { var iGraph = new Graph(); iGraph.Nodes = new Node[] { new Node { Id = 1, SuccessorIds = new int[] { 23, 34 } }, new Node { Id = 2, SuccessorIds = new int[] { 43, 26 } }, new Node { Id = 3, SuccessorIds = new int[] { 9, 16 } }, new Node { Id = 4, SuccessorIds = new int[] { 19, 49 } }, new Node { Id = 5, SuccessorIds = new int[] { 21, 52 } }, new Node { Id = 6, SuccessorIds = new int[] { 5, 14 } }, new Node { Id = 7, SuccessorIds = new int[] { 12, 31 } }, new Node { Id = 8, SuccessorIds = new int[] { 47, 54 } }, new Node { Id = 9, SuccessorIds = new int[] { 24, 37 } }, new Node { Id = 10, SuccessorIds = new int[] { 2, 46 } }, new Node { Id = 11, SuccessorIds = new int[] { 3, 25 } }, new Node { Id = 12, SuccessorIds = new int[] { 8, 20 } }, new Node { Id = 13, SuccessorIds = new int[] {} // lose }, new Node { Id = 14, SuccessorIds = new int[] { 21, 52 } }, new Node { Id = 15, SuccessorIds = new int[] {} // lose }, new Node { Id = 16, SuccessorIds = new int[] { 6, 44 } }, new Node { Id = 17, SuccessorIds = new int[] { 35, 40 } }, new Node { Id = 18, SuccessorIds = new int[] { 42, 55 } }, new Node { Id = 19, SuccessorIds = new int[] { 10, 33 } }, new Node { Id = 20, SuccessorIds = new int[] { 13, 54 } }, new Node { Id = 21, SuccessorIds = new int[] { 30, 53 } }, new Node { Id = 22, SuccessorIds = new int[] { 9, 56 } }, new Node { Id = 23, SuccessorIds = new int[] { 4, 41 } }, new Node { Id = 24, SuccessorIds = new int[] { 27, 32 } }, new Node { Id = 25, SuccessorIds = new int[] { 16, 56 } }, new Node { Id = 26, SuccessorIds = new int[] {} // lose }, new Node { Id = 27, SuccessorIds = new int[] { 21, 52 } }, new Node { Id = 28, SuccessorIds = new int[] { 2, 56 } }, new Node { Id = 29, SuccessorIds = new int[] { 11, 51 } }, new Node { Id = 30, SuccessorIds = new int[] { 50 } }, new Node { Id = 31, SuccessorIds = new int[] { 8, 20 } }, new Node { Id = 32, SuccessorIds = new int[] { 21, 52 } }, new Node { Id = 33, SuccessorIds = new int[] { 46, 56 } }, new Node { Id = 34, SuccessorIds = new int[] { 18, 29 } }, new Node { Id = 35, SuccessorIds = new int[] { 8, 20 } }, new Node { Id = 36, SuccessorIds = new int[] { 10, 28 } }, new Node { Id = 37, SuccessorIds = new int[] { 27, 32 } }, new Node { Id = 38, SuccessorIds = new int[] { 12, 31 } }, new Node { Id = 39, SuccessorIds = new int[] {} // win }, new Node { Id = 40, SuccessorIds = new int[] { 8, 20 } }, new Node { Id = 41, SuccessorIds = new int[] { 15, 36 } }, new Node { Id = 42, SuccessorIds = new int[] { 22, 56 } }, new Node { Id = 43, SuccessorIds = new int[] { 35, 40 } }, new Node { Id = 44, SuccessorIds = new int[] {} // lose }, new Node { Id = 45, SuccessorIds = new int[] {} // lose }, new Node { Id = 46, SuccessorIds = new int[] { 7, 38 } }, new Node { Id = 47, SuccessorIds = new int[] { 39, 50 } }, new Node { Id = 48, SuccessorIds = new int[] { 5, 14 } }, new Node { Id = 49, SuccessorIds = new int[] { 33, 56 } }, new Node { Id = 50, SuccessorIds = new int[] {} // win }, new Node { Id = 51, SuccessorIds = new int[] {} // lose }, new Node { Id = 52, SuccessorIds = new int[] {} // lose }, new Node { Id = 53, SuccessorIds = new int[] {} // lose }, new Node { Id = 54, SuccessorIds = new int[] { 39, 45 } }, new Node { Id = 55, SuccessorIds = new int[] { 22, 3 } }, new Node { Id = 56, SuccessorIds = new int[] { 17, 48 } } }; iGraph.PrepareSuccessors(); var HasCycle = false; var Result = TopologicalSorter.Sort(iGraph.Nodes, iNode => iNode.Successors, out HasCycle); // generated result // 1, 34, 29, 51, 11, 25, 18, 55, 3, 16, // 44, 6, 42, 22, 9, 37, 24, 32, 27, 23, // 41, 36, 28, 15, 4, 49, 19, 33, 56, 48, // 14, 5, 52, 21, 53, 30, 17, 10, 46, 38, // 7, 31, 12, 2, 26, 43, 40, 35, 20, 13, // 8, 54, 45, 47, 50, 39 Assert.IsTrue(IsTopologicalSort(Result, iNode => iNode.Successors)); }
private List <string> RunTest(int numNodes, params string[] edges) { var result = TopologicalSorter.FindAndTopologicallySortStronglyConnectedComponents(Enumerable.Range('a', numNodes).Select(c => ((char)c)), edges.Select(e => Tuple.Create(e[0], e[1]))); return(result.Select(x => new string(x.ToArray())).ToList()); }
public void TestTopSortAcyclicGraph8Vertices() { // Arrange var graph = new Dictionary<string, List<string>>() { { "H", new List<string>() { "G" } }, { "G", new List<string>() { } }, { "B", new List<string>() { "A" } }, { "A", new List<string>() { } }, { "F", new List<string>() { "B", "C", "E" } }, { "C", new List<string>() { "A" } }, { "E", new List<string>() { "C", "A" } }, { "D", new List<string>() { "A", "B" } }, }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert this.AssertTopologicallySorted(graph, sortedNodes); }
public void TestTopSortGraph7VerticesWithCycle() { // Arrange var graph = new Dictionary<string, List<string>>() { { "A", new List<string>() { "B" } }, { "B", new List<string>() { "C" } }, { "C", new List<string>() { "D", "E" } }, { "D", new List<string>() { "E" } }, { "E", new List<string>() { "F", "C" } }, { "Z", new List<string>() { "A" } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); }
public void TestTopSortGraph1Vertex() { // Arrange var graph = new Dictionary<string, List<string>>() { { "A", new List<string>() { } } }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert this.AssertTopologicallySorted(graph, sortedNodes); }
public void TestTopologicalSorter() { List<Node> nodes = new List<Node>(); Node seven = new Node(7); nodes.Add(seven); Node five = new Node(5); nodes.Add(five); Node three = new Node(3); nodes.Add(three); Node eleven = new Node(11); nodes.Add(eleven); Node eight = new Node(8); nodes.Add(eight); Node two = new Node(2); nodes.Add(two); Node nine = new Node(9); nodes.Add(nine); Node ten = new Node(10); nodes.Add(ten); three.Parent = two; eleven.Parent = seven; seven.Parent = eight; five.Parent = nine; ten.Parent = eleven; nine.Parent = eleven; TopologicalSorter<Node> sorter = new TopologicalSorter<Node>(); IList<Node> sorted = sorter.Sort(nodes); StringBuilder sb = new StringBuilder(); foreach (Node node in sorted) { sb.Append(node.ID + " "); } Assert.IsTrue(sorted.IndexOf(two) < sorted.IndexOf(three), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eight) < sorted.IndexOf(seven), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(seven) < sorted.IndexOf(eleven), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eleven) < sorted.IndexOf(nine), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eleven) < sorted.IndexOf(ten), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(nine) < sorted.IndexOf(five), "The order: " + sb.ToString()); Random rand = new Random((int)DateTime.Now.Ticks); for (int i = 0; i < 10000; i++) { List<Node> newList = this.RandomizeList(sorted, rand); sorted = sorter.Sort(newList); sb = new StringBuilder(); foreach (Node node in sorted) { sb.Append(node.ID + " "); } Assert.IsTrue(sorted.IndexOf(two) < sorted.IndexOf(three), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eight) < sorted.IndexOf(seven), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(seven) < sorted.IndexOf(eleven), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eleven) < sorted.IndexOf(nine), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(eleven) < sorted.IndexOf(ten), "The order: " + sb.ToString()); Assert.IsTrue(sorted.IndexOf(nine) < sorted.IndexOf(five), "The order: " + sb.ToString()); } }
public void TestTopologicalSorterWithCircularGraph() { List<Node> nodes = new List<Node>(); Node seven = new Node(7); nodes.Add(seven); Node five = new Node(5); nodes.Add(five); five.Parent = seven; seven.Parent = five; TopologicalSorter<Node> sorter = new TopologicalSorter<Node>(); IList<Node> sorted = sorter.Sort(nodes); }
private static int[] GetTopologicalSortOrder(IList<DependencyField> fields) { var g = new TopologicalSorter(fields.Count()); var _indexes = new Dictionary<string, int>(); //add vertices for (int i = 0; i < fields.Count(); i++) { _indexes[fields[i].Alias.ToLower()] = g.AddVertex(i); } //add edges for (int i = 0; i < fields.Count; i++) { if (fields[i].DependsOn != null) { for (int j = 0; j < fields[i].DependsOn.Length; j++) { g.AddEdge(i, _indexes[fields[i].DependsOn[j].ToLower()]); } } } int[] result = g.Sort(); return result; }
public static IList <T> TopologicalSort <T>(IList <T> sourceObjects, IComparer <T> comparer) { TopologicalSorter <T> sorter = new TopologicalSorter <T>(); return(sorter.Sort(sourceObjects, comparer)); }
public void SetUp() { sorter = new TopologicalSorter(); }
public void Sort_BasicExample_ProducesCorrectResults() { var sorter = new TopologicalSorter(); var output = sorter.Sort(new[] { (before: 1, after: 2), (before: 1, after: 3), (before: 2, after: 4), (before: 3, after: 4) })
public static void DoTest() { var V01 = new string[] { "A", "B", "C", "D", "E", "X" }; var DAG01 = new DirectedSparseGraph <string>(); // Insert new values of V DAG01.AddVertices(V01); // Insert new value for edges DAG01.AddEdge("A", "B"); DAG01.AddEdge("A", "X"); DAG01.AddEdge("B", "C"); DAG01.AddEdge("C", "D"); DAG01.AddEdge("D", "E"); DAG01.AddEdge("E", "X"); // PRINT THE GRAPH Console.WriteLine("[*] DAG (Directed Asyclic Graph):"); Console.WriteLine(DAG01.ToReadable() + "\r\n"); // CALCULATE THE TOPOLOGICAL SORT var topologicalSort01 = TopologicalSorter.Sort <string>(DAG01); var output01 = string.Empty; foreach (var node in topologicalSort01) { output01 = String.Format("{0}({1}) ", output01, node); } // PRINT THE TOPOLOGICAL SORT Console.WriteLine("Was the previous graph cyclic? " + output01); Console.WriteLine("\r\n*********************************************\r\n"); /**************************************************************************/ var V02 = new int[] { 7, 5, 3, 11, 8, 2, 9, 10 }; var DAG02 = new DirectedSparseGraph <int>(); // Insert new values of V DAG02.AddVertices(V02); // Insert new value for edges DAG02.AddEdge(7, 11); DAG02.AddEdge(7, 8); DAG02.AddEdge(5, 11); DAG02.AddEdge(3, 8); DAG02.AddEdge(3, 10); DAG02.AddEdge(11, 2); DAG02.AddEdge(11, 9); DAG02.AddEdge(11, 10); DAG02.AddEdge(8, 9); // PRINT THE GRAPH Console.WriteLine("[*] DAG (Directed Asyclic Graph):"); Console.WriteLine(DAG02.ToReadable() + "\r\n"); // CALCULATE THE TOPOLOGICAL SORT var topologicalSort02 = TopologicalSorter.Sort <int>(DAG02); var output02 = string.Empty; foreach (var node in topologicalSort02) { output02 = String.Format("{0}({1}) ", output02, node); } // PRINT THE TOPOLOGICAL SORT Console.WriteLine("Was the previous graph cyclic? " + output02); Console.WriteLine("\r\n*********************************************\r\n"); Console.ReadLine(); }
static void Main(string[] args) { List <Task> tasks = new List <Task> { new Task { Message = "A - depends on B and C" }, //0 new Task { Message = "B - depends on none" }, //1 new Task { Message = "C - depends on D and E" }, //2 new Task { Message = "D - depends on none" }, //3 new Task { Message = "E - depends on F, G and H" }, //4 new Task { Message = "F - depends on I" }, //5 new Task { Message = "G - depends on none" }, //6 new Task { Message = "H - depends on none" }, //7 new Task { Message = "I - depends on none" }, //8 }; TopologicalSorter <Task> resolver = new TopologicalSorter <Task>(); // now setting relations between them as described above resolver.Add(tasks[0], new[] { tasks[1], tasks[2] }); //resolver.Add(tasks[1]); // no need for this since the task was already mentioned as a dependency resolver.Add(tasks[2], new[] { tasks[3], tasks[4] }); //resolver.Add(tasks[3]); // no need for this since the task was already mentioned as a dependency resolver.Add(tasks[4], tasks[5], tasks[6], tasks[7]); resolver.Add(tasks[5], tasks[8]); //resolver.Add(tasks[6]); // no need for this since the task was already mentioned as a dependency //resolver.Add(tasks[7]); // no need for this since the task was already mentioned as a dependency //resolver.Add(tasks[3], tasks[0]); // uncomment this line to test cycled dependency var result = resolver.Sort(); var sorted = result.Item1; var cycled = result.Item2; if (!cycled.Any()) { foreach (var d in sorted) { Console.WriteLine(d.Message); } } else { Console.Write("Cycled dependencies detected: "); foreach (var d in cycled) { Console.Write($"{d.Message[0]} "); } Console.WriteLine(); } Console.WriteLine("exiting..."); }
public void Sort_TwoElementsOneDependencyDeep_CanSortByDependency() { // Arrange SortItem a = new SortItem("A"); SortItem c = new SortItem("C"); c.SetDependencies(a); SortItem[] unsorted = new[] { c, a }; // Act TopologicalSorter topologicalSorter = new TopologicalSorter(); IList<SortItem> sorted = topologicalSorter.Sort(unsorted, x => x.Dependencies, new SortItemEqualityComparer()); // Assert Assert.Equal(2, sorted.Count); Assert.Equal("A", sorted[0].Name); Assert.Equal("C", sorted[1].Name); }
public void TestTopSortEmptyGraph() { // Arrange var graph = new Dictionary<string, List<string>>() { }; // Act var topSorter = new TopologicalSorter(graph); var sortedNodes = new List<string>(topSorter.TopSort()); // Assert AssertTopologicallySorted(graph, sortedNodes); }