private static IEnumerable <Vertex <T> > SortTopologically <T> (IEnumerable <Vertex <T> > graph, bool throwIfOrderIsUndefined = false)
        {
            var graphAsList = graph.ToList();
            var result      = new List <Vertex <T> >(graphAsList.Count);

            while (graphAsList.Any())
            {
                var independents = graphAsList
                                   .Where(x => !result.Contains(x) && !graphAsList.Any(y => y.Dependencies.Contains(x)))
                                   .ToList();

                if (throwIfOrderIsUndefined && independents.Count > 1)
                {
                    throw new UndefinedOrderException(independents.Select(x => x.Value));
                }

                var independent = independents.FirstOrDefault();
                if (independent == null)
                {
                    var scc        = new StronglyConnectedComponentFinder <T>();
                    var enumerable = scc.DetectCycle(graphAsList).Select(x => x.Select(y => y.Value));
                    throw new CircularDependencyException(enumerable.Cast <IEnumerable>());
                }

                graphAsList.Remove(independent);
                result.Add(independent);
            }

            return(result);
        }
Example #2
0
        // B→D
        // D→C
        // A→B→C
        // A→B→D→C
        static void Main()
        {
            var feeder = new LineFeeder("data.txt");
            var factory = new VertexFactory<string>();
            foreach (var line in feeder)
            {
                var splittedLine = line.Split(',');
                factory.Add(splittedLine[0],splittedLine[1]);
            }
            //var path = @"C:\Users\Eduard\Source\Repos\CycleDetection\data.txt";
            var graph = new List<Vertex<string>>();
            graph.AddRange(factory.VertexDictionary.Select(vde=>vde.Value));

            var detector = new StronglyConnectedComponentFinder<string>();
            var components = detector.DetectCycle(graph);
            int index = 0;
            foreach (var component in components)
            {
                Console.Write($"component {index++} : ");
                foreach (var vertex in component)
                {
                    Console.Write(vertex.Value + " ");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
        }
Example #3
0
        public void TwoIsolated3Cycles()
        {
            var graph = new List <Vertex <int> >();
            var vA    = new Vertex <int>(1);
            var vB    = new Vertex <int>(2);
            var vC    = new Vertex <int>(3);

            vA.Dependencies.Add(vB);
            vB.Dependencies.Add(vC);
            vC.Dependencies.Add(vA);
            graph.Add(vA);
            graph.Add(vB);
            graph.Add(vC);

            var vD = new Vertex <int>(4);
            var vE = new Vertex <int>(5);
            var vF = new Vertex <int>(6);

            vD.Dependencies.Add(vE);
            vE.Dependencies.Add(vF);
            vF.Dependencies.Add(vD);
            graph.Add(vD);
            graph.Add(vE);
            graph.Add(vF);

            var detector   = new StronglyConnectedComponentFinder <int>();
            var components = detector.DetectCycle(graph);

            Assert.AreEqual(2, components.Count);
            Assert.AreEqual(0, components.IndependentComponents().Count());
            Assert.AreEqual(2, components.Cycles().Count());
            Assert.IsTrue(components.All(c => c.Count == 3));
        }
Example #4
0
        // B→D
        // D→C
        // A→B→C
        // A→B→D→C
        static void Main()
        {
            var feeder  = new LineFeeder("data.txt");
            var factory = new VertexFactory <string>();

            foreach (var line in feeder)
            {
                var splittedLine = line.Split(',');
                factory.Add(splittedLine[0], splittedLine[1]);
            }
            //var path = @"C:\Users\Eduard\Source\Repos\CycleDetection\data.txt";
            var graph = new List <Vertex <string> >();

            graph.AddRange(factory.VertexDictionary.Select(vde => vde.Value));

            var detector   = new StronglyConnectedComponentFinder <string>();
            var components = detector.DetectCycle(graph);
            int index      = 0;

            foreach (var component in components)
            {
                Console.Write($"component {index++} : ");
                foreach (var vertex in component)
                {
                    Console.Write(vertex.Value + " ");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
        }
Example #5
0
        public void Cycle3WithStub()
        {
            var graph = new List <Vertex <int> >();
            var vA    = new Vertex <int>(1);
            var vB    = new Vertex <int>(2);
            var vC    = new Vertex <int>(3);
            var vD    = new Vertex <int>(4);

            vA.Dependencies.Add(vB);
            vB.Dependencies.Add(vC);
            vC.Dependencies.Add(vA);
            vC.Dependencies.Add(vD);
            graph.Add(vA);
            graph.Add(vB);
            graph.Add(vC);
            graph.Add(vD);
            var detector   = new StronglyConnectedComponentFinder <int>();
            var components = detector.DetectCycle(graph);

            Assert.AreEqual(2, components.Count);
            Assert.AreEqual(1, components.IndependentComponents().Count());
            Assert.AreEqual(1, components.Cycles().Count());
            Assert.AreEqual(1, components.Count(c => c.Count == 3));
            Assert.AreEqual(1, components.Count(c => c.Count == 1));
            Assert.IsTrue(components.Single(c => c.Count == 1).Single() == vD);
        }
Example #6
0
        public void LinearTwoLines()
        {
            var graph = new List <Vertex <string> >();
            var vA    = new Vertex <string>("A");
            var vB    = new Vertex <string>("B");
            var vC    = new Vertex <string>("C");
            var vD    = new Vertex <string>("D");

            vB.Dependencies.Add(vD);
            vD.Dependencies.Add(vC);
            vA.Dependencies.Add(vB);
            vB.Dependencies.Add(vC);
            graph.Add(vA);
            graph.Add(vB);
            graph.Add(vC);

            var detector = new StronglyConnectedComponentFinder <string>();
            StronglyConnectedComponentList <string> components = detector.DetectCycle(graph);

            Assert.AreEqual(4, components.Count);
            Assert.AreEqual(4, components.IndependentComponents().Count());
            Assert.AreEqual(0, components.Cycles().Count());
            Assert.AreEqual("C", components.First().First().Value);
            Assert.AreEqual("D", components.Skip(1).First().First().Value);
            Assert.AreEqual("B", components.Skip(2).First().First().Value);
            Assert.AreEqual("A", components.Skip(3).First().First().Value);
        }
Example #7
0
        public void EmptyGraph()
        {
            var detector = new StronglyConnectedComponentFinder <int>();
            var cycles   = detector.DetectCycle(new List <Vertex <int> >());

            Assert.AreEqual(0, cycles.Count);
        }
        public void SingleVertex()
        {
            var graph = new List <Vertex <int> >();

            graph.Add(new Vertex <int>(1));
            var detector   = new StronglyConnectedComponentFinder <int>();
            var components = detector.DetectCycle(graph);

            Assert.AreEqual(1, components.Count);
            Assert.AreEqual(1, components.IndependentComponents().Count());
            Assert.AreEqual(0, components.Cycles().Count());
        }
 public void Cycle2()
 {
     var graph = new List<Vertex<int>>();
     var vA = new Vertex<int>(1);
     var vB = new Vertex<int>(2);
     vA.Dependencies.Add(vB);
     vB.Dependencies.Add(vA);
     graph.Add(vA);
     graph.Add(vB);
     var detector = new StronglyConnectedComponentFinder<int>();
     var components = detector.DetectCycle(graph);
     Assert.AreEqual(1, components.Count);
     Assert.AreEqual(0, components.IndependentComponents().Count());
     Assert.AreEqual(1, components.Cycles().Count());
     Assert.AreEqual(2, components.First().Count);
 }
        public void Linear2()
        {
            var graph = new List <Vertex <int> >();
            var vA    = new Vertex <int>(1);
            var vB    = new Vertex <int>(2);

            vA.Dependencies.Add(vB);
            graph.Add(vA);
            graph.Add(vB);
            var detector   = new StronglyConnectedComponentFinder <int>();
            var components = detector.DetectCycle(graph);

            Assert.AreEqual(2, components.Count);
            Assert.AreEqual(2, components.IndependentComponents().Count());
            Assert.AreEqual(0, components.Cycles().Count());
        }
        public void Cycle3()
        {
            var graph = new List <Vertex <int> >();
            var vA    = new Vertex <int>(1);
            var vB    = new Vertex <int>(2);
            var vC    = new Vertex <int>(3);

            vA.Dependencies.Add(vB);
            vB.Dependencies.Add(vC);
            vC.Dependencies.Add(vA);
            graph.Add(vA);
            graph.Add(vB);
            graph.Add(vC);
            var detector   = new StronglyConnectedComponentFinder <int>();
            var components = detector.DetectCycle(graph);

            Assert.Equal(1, components.Count);
            Assert.Equal(0, components.IndependentComponents().Count());
            Assert.Equal(1, components.Cycles().Count());
            Assert.Equal(3, components.Single().Count);
        }
 public void Cycle3WithStub()
 {
     var graph = new List<Vertex<int>>();
     var vA = new Vertex<int>(1);
     var vB = new Vertex<int>(2);
     var vC = new Vertex<int>(3);
     var vD = new Vertex<int>(4);
     vA.Dependencies.Add(vB);
     vB.Dependencies.Add(vC);
     vC.Dependencies.Add(vA);
     vC.Dependencies.Add(vD);
     graph.Add(vA);
     graph.Add(vB);
     graph.Add(vC);
     graph.Add(vD);
     var detector = new StronglyConnectedComponentFinder<int>();
     var components = detector.DetectCycle(graph);
     Assert.AreEqual(2, components.Count);
     Assert.AreEqual(1, components.IndependentComponents().Count());
     Assert.AreEqual(1, components.Cycles().Count());
     Assert.AreEqual(1, components.Count(c => c.Count == 3));
     Assert.AreEqual(1, components.Count(c => c.Count == 1));
     Assert.IsTrue(components.Single(c => c.Count == 1).Single() == vD);
 }
Example #13
0
        public void CycleWithDuplicates()
        {
            var testValues = new
            {
                A  = TestValue.Create("a ", "e"),
                B  = TestValue.Create(" B", " c "),
                A2 = TestValue.Create("A ", "C"),
                C  = TestValue.Create("C", "A", "D"),
                D  = TestValue.Create("d"),
                E  = TestValue.Create("E"),
            };

            var graph = new[]
            {
                testValues.A,
                testValues.B,
                testValues.C,
                testValues.D,
                testValues.E,
                testValues.A2,
            };

            var ignoreCase          = DerivedComparer.Create(StringComparer.OrdinalIgnoreCase, (string t) => t.Trim());
            var equalityComparer    = TestValue.CreateComparer(ignoreCase);
            var vertexValueComparer = new VertexValueComparer <TestValue <string> >(equalityComparer);

            var byValue = graph.ToLookup(t => t.Value, ignoreCase);

            var vertices = VertexBuilder.BuildVertices(graph, s => s.DependsOn.SelectMany(d => byValue[d]), equalityComparer).ToList();

            Assert.AreEqual(6, vertices.Count, "every source element should yield a vertex");
            Assert.AreEqual(5, vertices.Distinct().Count(), "'A' and 'a ' should yield the exact same vertex");

            var finder = new StronglyConnectedComponentFinder <TestValue <string> >();

            var simpleComponents = finder.DetectCycle(vertices, vertexValueComparer);

            var components = simpleComponents.ExtractCycles(equalityComparer);

            Assert.AreEqual(4, components.Count, "It should be only 4 components");
            Assert.AreEqual(3, components.IndependentComponents().Count(), "B, D & E are acylic");
            Assert.AreEqual(1, components.Cycles().Count(), "Only 1 cycle should be found");

            Assert.AreEqual
                (2,
                components.Take(2)
                .SelectMany(t => t)
                .Intersect(new[] { testValues.D, testValues.E })
                .Count(),
                "D & E should be the first components.");

            var component3 = components.Skip(2).First();
            var component4 = components.Skip(3).First();

            Assert.AreEqual(component3.Count, 2, "3rd component should be a cycle of 2");
            Assert.AreEqual
                (component3.Intersect(new[] { testValues.A, testValues.C }).Count(),
                2,
                "3rd component should be a cycle of A & C");

            Assert.AreEqual(testValues.B, component4.Single()); // 4th one has to be B (uses A)
        }
        public void TwoIsolated3Cycles()
        {
            var graph = new List<Vertex<int>>();
            var vA = new Vertex<int>(1);
            var vB = new Vertex<int>(2);
            var vC = new Vertex<int>(3);
            vA.Dependencies.Add(vB);
            vB.Dependencies.Add(vC);
            vC.Dependencies.Add(vA);
            graph.Add(vA);
            graph.Add(vB);
            graph.Add(vC);

            var vD = new Vertex<int>(4);
            var vE = new Vertex<int>(5);
            var vF = new Vertex<int>(6);
            vD.Dependencies.Add(vE);
            vE.Dependencies.Add(vF);
            vF.Dependencies.Add(vD);
            graph.Add(vD);
            graph.Add(vE);
            graph.Add(vF);

            var detector = new StronglyConnectedComponentFinder<int>();
            var components = detector.DetectCycle(graph);
            Assert.AreEqual(2, components.Count);
            Assert.AreEqual(0, components.IndependentComponents().Count());
            Assert.AreEqual(2, components.Cycles().Count());
            Assert.IsTrue(components.All(c => c.Count == 3));
        }
        public void CycleWithDuplicates()
        {
            var testValues = new
                       {
                         A = TestValue.Create("a ", "e"),
                         B = TestValue.Create(" B", " c "),
                         A2 = TestValue.Create("A ", "C"),
                         C = TestValue.Create("C", "A", "D"),
                         D = TestValue.Create("d"),
                         E = TestValue.Create("E"),
                       };

              var graph = new[]
                  {
                    testValues.A,
                    testValues.B,
                    testValues.C,
                    testValues.D,
                    testValues.E,
                    testValues.A2,
                  };

              var ignoreCase = DerivedComparer.Create(StringComparer.OrdinalIgnoreCase, (string t) => t.Trim());
              var equalityComparer = TestValue.CreateComparer(ignoreCase);
              var vertexValueComparer = new VertexValueComparer<TestValue<string>>(equalityComparer);

              var byValue = graph.ToLookup(t => t.Value, ignoreCase);

              var vertices = VertexBuilder.BuildVertices(graph, s => s.DependsOn.SelectMany(d => byValue[d]), equalityComparer).ToList();
              Assert.AreEqual(6, vertices.Count, "every source element should yield a vertex");
              Assert.AreEqual(5, vertices.Distinct().Count(), "'A' and 'a ' should yield the exact same vertex");

              var finder = new StronglyConnectedComponentFinder<TestValue<string>>();

              var simpleComponents = finder.DetectCycle(vertices, vertexValueComparer);

              var components = simpleComponents.ExtractCycles(equalityComparer);

              Assert.AreEqual(4, components.Count, "It should be only 4 components");
              Assert.AreEqual(3, components.IndependentComponents().Count(), "B, D & E are acylic");
              Assert.AreEqual(1, components.Cycles().Count(), "Only 1 cycle should be found");

              Assert.AreEqual
            (2,
             components.Take(2)
                   .SelectMany(t => t)
                   .Intersect(new[] { testValues.D, testValues.E })
                   .Count(),
             "D & E should be the first components.");

              var component3 = components.Skip(2).First();
              var component4 = components.Skip(3).First();
              Assert.AreEqual(component3.Count, 2, "3rd component should be a cycle of 2");
              Assert.AreEqual
            (component3.Intersect(new[] { testValues.A, testValues.C }).Count(),
             2,
             "3rd component should be a cycle of A & C");

              Assert.AreEqual(testValues.B, component4.Single()); // 4th one has to be B (uses A)
        }
 public void EmptyGraph()
 {
     var graph = new List<Vertex<int>>();
     var detector = new StronglyConnectedComponentFinder<int>();
     var cycles = detector.DetectCycle(graph);
     Assert.AreEqual(0, cycles.Count);
 }
 public void SingleVertex()
 {
     var graph = new List<Vertex<int>>();
     graph.Add(new Vertex<int>(1));
     var detector = new StronglyConnectedComponentFinder<int>();
     var components = detector.DetectCycle(graph);
     Assert.AreEqual(1, components.Count);
     Assert.AreEqual(1, components.IndependentComponents().Count());
     Assert.AreEqual(0, components.Cycles().Count());
 }