Beispiel #1
0
        public void TestMethod1()
        {
            // Arrange
            int[] idx    = { 0, 1, 2, 3, 4, 5 };
            var   sorter = new TopologicalSorter(idx.Length);

            sorter.AddVertex(0);
            sorter.AddVertex(1);
            sorter.AddVertex(2);
            sorter.AddVertex(3);
            sorter.AddVertex(4);
            sorter.AddVertex(5);
            sorter.AddEdge(5, 2);
            sorter.AddEdge(5, 0);
            sorter.AddEdge(4, 0);
            sorter.AddEdge(4, 1);
            sorter.AddEdge(2, 3);
            sorter.AddEdge(3, 1);

            // Act
            var result = sorter.Sort();

            // Assert
            result.Length.Should().Be(6);
            result.Should().ContainInOrder(new[] { 5, 4, 2, 3, 1, 0 });
        }
Beispiel #2
0
        public void TopologicalSorterOnDirectedAcyclicGraphWhereDirectionMeansOrder()
        {
            DirectedGraph <string, DirectedEdge <string> > graph = new DirectedGraph <string, DirectedEdge <string> >();

            graph.Add(new DirectedEdge <string>("A", "B"));             // A->B
            graph.Add(new DirectedEdge <string>("A", "C"));             // A->C
            graph.Add(new DirectedEdge <string>("B", "D"));             // B->D
            graph.Add(new DirectedEdge <string>("C", "D"));             // C->D
            graph.Add(new DirectedEdge <string>("D", "E"));             // D->E
            graph.Add(new DirectedEdge <string>("H", "G"));             // H->G
            graph.Add(new DirectedEdge <string>("G", "F"));             // G->F

            TopologicalSorter <string, DirectedEdge <string> > sorter = new TopologicalSorter <string, DirectedEdge <string> >(graph, true);

            sorter.Sort();
            List <string> expectedResults = new List <string>()
            {
                "H", "G", "F", "A", "C", "B", "D", "E"
            };

            for (int i = 0; i < sorter.SortResults.Count; i++)
            {
                Assert.AreEqual(expectedResults[i], sorter.SortResults[i]);
            }
        }
Beispiel #3
0
        private static IEnumerable <string> GetCalculationChain(IEnumerable <Cell> cells)
        {
            var topologicalSorter = new TopologicalSorter <string>();

            foreach (var cell in cells)
            {
                var cellReferences = cell.Formula.Tokens.OfType <RefToken>().Select(x => x.CellReference)
                                     .Concat(cell.Formula.Tokens.OfType <AreaToken>().SelectMany(token => token.CellReferences))
                                     .ToList();

                if (!cellReferences.Any())
                {
                    continue;
                }

                topologicalSorter.Add(cell.Reference, cellReferences);
            }

            var(sorted, cycled) = topologicalSorter.Sort();

            if (cycled.Any())
            {
                throw new Exception("Cyclic dependencies");
            }

            return(sorted);
        }
        private void TestSort <T>(T[] data, Predicate <T, T> connector, T[] expected, T[] loops)
        {
            List <Node <T, object> > actualLoopNodes;
            List <T> actual = TopologicalSorter.Sort(data, connector, out actualLoopNodes);

            T[] actualLoops = null;
            if (actualLoopNodes != null)
            {
                actualLoops = actualLoopNodes
                              .Where(n => n.OutgoingConnectionCount != 0)
                              .Select(n => n.Item)
                              .ToArray();
            }

            AssertEx.HasSameElements(expected, actual);
            AssertEx.HasSameElements(loops, actualLoops);

            List <NodeConnection <T, object> > removedEdges;
            List <T> sortWithRemove = TopologicalSorter.Sort(data, connector, out removedEdges);

            Assert.AreEqual(sortWithRemove.Count, data.Length);
            if (loops == null)
            {
                Assert.AreEqual(sortWithRemove.Count, actual.Count);
                for (int i = 0; i < actual.Count; i++)
                {
                    Assert.AreEqual(sortWithRemove[i], actual[i]);
                }
            }
            else
            {
                TestLog.Debug("Loops detected");
            }
        }
Beispiel #5
0
        private static void InternalPerformanceTest(int nodeCount, int averageEdgeCount, bool allowLoops)
        {
            TestLog.Info("Building graph: {0} nodes, {1} edges/node in average.", nodeCount, averageEdgeCount);
            var rnd   = new Random();
            var nodes = new List <Node <int> >();

            for (int i = 0; i < nodeCount; i++)
            {
                nodes.Add(new Node <int>(i));
            }
            int edgeCount = 0;

            foreach (var from in nodes)
            {
                int outgoingEdgeCount = rnd.Next(averageEdgeCount);
                for (int i = 0; i < outgoingEdgeCount; i++)
                {
                    var to = nodes[rnd.Next(allowLoops ? nodeCount : @from.Value)];
                    if (from == to)
                    {
                        continue;
                    }
                    var c = new Edge <int>(@from, to, edgeCount++);
                }
            }
            var graph = new Graph <Node <int>, Edge <int> >(nodes);

            GC.GetTotalMemory(true);
            using (new Measurement("Sorting", nodeCount + edgeCount)) {
                var result = TopologicalSorter.Sort(graph, e => true);
                Assert.IsFalse(result.HasLoops);
            }
            GC.GetTotalMemory(true);
        }
Beispiel #6
0
        /// <summary>
        /// Sort a collection of service types so that each service may be started after all
        /// their dependencies are started.
        /// </summary>
        /// <param name="serviceTypes">
        /// The service types.
        /// </param>
        /// <returns>
        /// The sorted service types.
        /// </returns>
        public IEnumerable <Type> Sort(IEnumerable <Type> serviceTypes)
        {
            var dependencies = serviceTypes.Select(x => new Dependency(x, FindDependencies(x)))
                               .ToArray();

            var sorter  = new TopologicalSorter(dependencies.Length);
            var indexes = new Dictionary <Type, int>();

            for (var i = 0; i < dependencies.Length; i++)
            {
                indexes[dependencies[i].Dependant] = sorter.AddVertex(i);
            }

            for (var i = 0; i < dependencies.Length; i++)
            {
                if (dependencies[i].Dependencies == null || !dependencies[i].Dependencies.Any())
                {
                    continue;
                }

                foreach (var t in dependencies[i].Dependencies)
                {
                    sorter.AddEdge(i, indexes[t]);
                }
            }

            var sortedServices = sorter.Sort()
                                 .Reverse()
                                 .Select(x => dependencies[x].Dependant)
                                 .ToList();

            return(sortedServices);
        }
        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);
        }
Beispiel #8
0
        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 void Sort_CanSortList()
        {
            var list = new List <SortableEntity>()
            {
                new SortableEntity(1, 2),
                new SortableEntity(2, 10),
                new SortableEntity(3, 10),
                new SortableEntity(4, 10),
                new SortableEntity(5, null),
                new SortableEntity(6, 5),
                new SortableEntity(7, 5),
                new SortableEntity(8, null),
                new SortableEntity(9, 8),
                new SortableEntity(10, 5),
            };

            var result = TopologicalSorter.Sort(
                list,
                (item, source) => source.Where(l => l.MyId == item.DependentOnId),
                true
                );

            var stringResult = string.Join(',', result.Select(r => r.MyId));

            Assert.Equal("5,10,2,1,3,4,6,7,8,9", stringResult);
        }
 public void Sort_NullDependencySelector_ThrowsException()
 {
     Assert.Throws <ArgumentNullException>(() =>
     {
         TopologicalSorter.Sort(Array.Empty <string>(), null, true);
     });
 }
    private static int[] getTopologicalSortOrder(List <Field> fields)
    {
        TopologicalSorter        g        = new TopologicalSorter();
        Dictionary <string, int> _indexes = new Dictionary <string, int>();

        //add vertices
        for (int i = 0; i < fields.Count; i++)
        {
            g.AddVertex((char)i);
            _indexes[fields[i].Name.ToLower()] = 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()]);
                }
            }
        }
        char[] array  = g.Sort();
        int[]  result = new int[fields.Count];
        for (int i = 0; i < fields.Count; i++)
        {
            result[i] = (int)array[i];
        }
        return(result);
    }
Beispiel #12
0
        public 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
            // [*] DAG (Directed Asyclic Graph):

            // 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);
            }

            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
            // [*] DAG (Directed Asyclic Graph):
            // 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);
            }
        }
        public void Sort_NullSource_ThrowsException()
        {
            string[] collection = null;

            Assert.Throws <ArgumentNullException>(() =>
            {
                TopologicalSorter.Sort(collection, (item, source) => Array.Empty <string>(), true);
            });
        }
Beispiel #14
0
        /// <summary>
        /// Examines the applications and application versions in a product and produces a sorted list for a sequence of
        /// actions (usually installation) that takes dependencies into account.
        /// </summary>
        /// <param name="product">The product to examine.</param>
        /// <returns>The sorted list of ids.</returns>
        private IEnumerable <Guid> GetSortedApplicationIds(IMarketplaceProduct product)
        {
            var set = new List <Guid?>();

            set.AddRange(product.IncludesApps.Select(a => a.ApplicationId));
            set.AddRange(product.IncludesAppVersions.Select(a => a.VersionId));
            set.AddRange(product.IncludesApps.SelectMany(i => i.RequiredApps).Select(a => a.ApplicationId));
            set.AddRange(product.IncludesApps.SelectMany(i => i.RequiredAppVersions).Select(a => a.VersionId));
            set.AddRange(product.IncludesAppVersions.SelectMany(i => i.RequiredApps).Select(a => a.ApplicationId));
            set.AddRange(product.IncludesAppVersions.SelectMany(i => i.RequiredAppVersions).Select(a => a.VersionId));

            var ids = set.Where(s => s != null && s.Value != Guid.Empty).Select(s => s.Value).Distinct().ToList();

            var sorter  = new TopologicalSorter(ids.Count);
            var indices = new Dictionary <Guid, int>();

            // add vertices
            for (var i = 0; i < ids.Count; i++)
            {
                indices[ids[i]] = sorter.AddVertex(i);
            }

            // add edges
            foreach (var app in product.IncludesApps)
            {
                if (app.ApplicationId == null || app.ApplicationId.Value == Guid.Empty)
                {
                    continue;
                }

                AddRequiredAppEdgesToSorter(app.RequiredApps, sorter, ids, app.ApplicationId.Value);
                AddRequiredAppVersionEdgesToSorter(app.RequiredAppVersions, sorter, ids, app.ApplicationId.Value);
            }

            foreach (var appVersion in product.IncludesAppVersions)
            {
                if (appVersion.VersionId == null || appVersion.VersionId.Value == Guid.Empty)
                {
                    continue;
                }

                AddRequiredAppEdgesToSorter(appVersion.RequiredApps, sorter, ids, appVersion.VersionId.Value);
                AddRequiredAppVersionEdgesToSorter(appVersion.RequiredAppVersions, sorter, ids, appVersion.VersionId.Value);
            }

            var sorted = sorter.Sort();
            var result = sorted.Select(t => ids[t]).ToList();

            return(result);
        }
Beispiel #15
0
        public void RemoveEdgeTest1()
        {
            var node1          = new Node <int>(1);
            var node2          = new Node <int>(2);
            var connection12_1 = new Edge <int>(node1, node2, 1);
            var connection12_2 = new Edge <int>(node1, node2, 2);
            var connection21_1 = new Edge <int>(node2, node1, 3);
            var graph          = new Graph <Node <int>, Edge <int> >(new[] { node2, node1 });

            var result = TopologicalSorter.Sort(graph, e => e.Value == 3);

            Assert.AreEqual(2, result.SortedNodes.Count);
            Assert.AreEqual(1, result.BrokenEdges.Count);
        }
        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();

            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:
                    {
                        var beforeMe = stLookup[item];
                        var 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:
                    {
                        return tsLookup[item];
                    }

                default:
                    {
                        return TrackedItem.EmptyList;
                    }
                }
            }));
        }
        public void SelfReferenceTest()
        {
            var node       = new Node <int, string>(1);
            var connection = new NodeConnection <int, string>(node, node, "ConnectionItem");

            connection.BindToNodes();

            List <NodeConnection <int, string> > removedEdges;
            List <int> result = TopologicalSorter.Sort(EnumerableUtils.One(node), out removedEdges);

            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(node.Item, result[0]);
            Assert.AreEqual(1, removedEdges.Count);
            Assert.AreEqual(connection, removedEdges[0]);
        }
Beispiel #18
0
        public void SelfReferenceTest()
        {
            var node  = new Node <int>(1);
            var edge  = new Edge <int>(node, node, 1);
            var graph = new Graph <Node <int>, Edge <int> >(EnumerableUtils.One(node));

            List <Edge <int> > removedEdges;
            var result = TopologicalSorter.Sort(graph, e => e.Source == e.Target);

            Assert.AreEqual(1, result.SortedNodes.Count);
            Assert.AreSame(node, result.SortedNodes[0]);
            Assert.AreEqual(1, result.BrokenEdges.Count);
            Assert.AreSame(edge, result.BrokenEdges[0]);
            Assert.AreEqual(0, node.Edges.Count());
        }
Beispiel #19
0
        private IEnumerable <TypeDef> GetTypeBuildSequence()
        {
            List <Node <Node <TypeDef>, object> > loops;
            var result = TopologicalSorter.Sort(context.DependencyGraph.Nodes, TypeConnector, out loops);

            if (result == null)
            {
                throw new DomainBuilderException(string.Format(
                                                     Strings.ExAtLeastOneLoopHaveBeenFoundInPersistentTypeDependenciesGraphSuspiciousTypesX,
                                                     loops.Select(node => node.Item.Value.Name).ToCommaDelimitedString()));
            }
            var dependentTypes   = result.Select(n => n.Value);
            var independentTypes = context.ModelDef.Types.Except(dependentTypes);

            return(independentTypes.Concat(dependentTypes));
        }
Beispiel #20
0
        public void TopologicalSorterOnDirectedGraphWithCycle()
        {
            DirectedGraph <string, DirectedEdge <string> > graph = new DirectedGraph <string, DirectedEdge <string> >();

            graph.Add(new DirectedEdge <string>("A", "B"));             // A->B
            graph.Add(new DirectedEdge <string>("A", "C"));             // A->C
            graph.Add(new DirectedEdge <string>("B", "D"));             // B->D
            graph.Add(new DirectedEdge <string>("C", "D"));             // C->D
            graph.Add(new DirectedEdge <string>("D", "E"));             // D->E
            graph.Add(new DirectedEdge <string>("E", "A"));             // E->A, creates cycle A, B/C, D, E, A
            graph.Add(new DirectedEdge <string>("H", "G"));             // H->G
            graph.Add(new DirectedEdge <string>("G", "F"));             // G->F

            TopologicalSorter <string, DirectedEdge <string> > sorter = new TopologicalSorter <string, DirectedEdge <string> >(graph);

            sorter.Sort();
        }
Beispiel #21
0
        private static IEnumerable <IStartupConfigurationTask> SortTasksByDependency(IEnumerable <IStartupConfigurationTask> startupTasks)
        {
            // Set up a lookup of task
            var startupTaskLookup = startupTasks.ToDictionary(k => k.GetType(), v => new StartupTaskLookupItem(v));

            foreach (var startupTask in startupTasks
                     .Where(t => t is IRunAfterStartupConfigurationTask)
                     .Cast <IRunAfterStartupConfigurationTask>())
            {
                var startupTaskLookupItem = startupTaskLookup[startupTask.GetType()];

                foreach (var runAfterTaskType in startupTask.RunAfter)
                {
                    var dependentTask = startupTaskLookup[runAfterTaskType].StartupTask;
                    startupTaskLookupItem.Dependencies.Add(dependentTask);
                }
            }

            foreach (var startupTask in startupTasks
                     .Where(t => t is IRunBeforeStartupConfigurationTask)
                     .Cast <IRunBeforeStartupConfigurationTask>())
            {
                foreach (var runBeforeTaskType in startupTask.RunBefore)
                {
                    startupTaskLookup[runBeforeTaskType].Dependencies.Add(startupTask);
                }
            }

            // Pre-sort by numerical task ordering
            // The fullname secondry ordering is used to get predicatable task ordering
            IEnumerable <IStartupConfigurationTask> orderedTasks = startupTasks
                                                                   .OrderBy(t => t.Ordering)
                                                                   .ThenBy(t => t.GetType().FullName);

            try
            {
                // Then do a Topological Sort based on task dependencies
                orderedTasks = TopologicalSorter.Sort(orderedTasks, t => startupTaskLookup[t.GetType()].Dependencies, true);
            }
            catch (CyclicDependencyException ex)
            {
                throw new CyclicDependencyException("A cyclic dependency has been detected between multiple IStartupConfigurationTask classes. Check your startup tasks to ensure they do not depend on each other. For more details see the inner exception message.", ex);
            }

            return(orderedTasks);
        }
Beispiel #22
0
        public void TopologicalSorterOnDirectedGraphWithCycle()
        {
            DirectedGraph <string, DirectedEdge <string> > graph = new DirectedGraph <string, DirectedEdge <string> >();

            graph.Add(new DirectedEdge <string>("A", "B"));             // A->B
            graph.Add(new DirectedEdge <string>("A", "C"));             // A->C
            graph.Add(new DirectedEdge <string>("B", "D"));             // B->D
            graph.Add(new DirectedEdge <string>("C", "D"));             // C->D
            graph.Add(new DirectedEdge <string>("D", "E"));             // D->E
            graph.Add(new DirectedEdge <string>("E", "A"));             // E->A, creates cycle A, B/C, D, E, A
            graph.Add(new DirectedEdge <string>("H", "G"));             // H->G
            graph.Add(new DirectedEdge <string>("G", "F"));             // G->F

            TopologicalSorter <string, DirectedEdge <string> > sorter = new TopologicalSorter <string, DirectedEdge <string> >(graph);

            Assert.That(() => sorter.Sort(), Throws.TypeOf <InvalidOperationException>());
        }
            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);
                }
            }
        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 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);
        }
Beispiel #26
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;
                }
            }));
        }
        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 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);
        }
        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);
            }
        }
        /// <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>
        /// 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());
        }
Beispiel #33
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());
            }
        }
        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;

        }
Beispiel #35
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);
        }
        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);
        }