Example #1
0
    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);
    }
Example #5
0
        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);
        }
Example #7
0
    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);
                }
            }
Example #9
0
        /// <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);
        }
Example #10
0
    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);
    }
Example #11
0
    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);
        }
Example #13
0
        /// <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);
            }
        }
Example #14
0
        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;
                }
            }));
        }
Example #15
0
        /// <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);
            }
        }
Example #16
0
        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);
        }
Example #17
0
        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);
            }
        }
Example #19
0
        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);
        }
Example #23
0
        /// <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);
        }
Example #25
0
    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());
    }
Example #26
0
        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]);
                }
            }
        }
Example #27
0
        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);
        }
Example #29
0
        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));
        }
Example #30
0
        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);
        }
Example #35
0
        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());
            }
        }
Example #36
0
        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;

        }
Example #38
0
        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);
    }