public void Cycle3()
        {
            // A→B
              // ↑ ↓
              // └─C

              var graph = new[]
                  {
                    new
                    {
                      Value = "A",
                      DependsOn = "B"
                    },
                    new
                    {
                      Value = "B",
                      DependsOn = "C"
                    },
                    new
                    {
                      Value = "C",
                      DependsOn = "A"
                    },
                  };

              var byValue = graph.ToLookup(k => k.Value);
              var components = graph.DetectCycles(s => byValue[s.DependsOn]);

              Assert.AreEqual(1, components.Count);
              Assert.AreEqual(0, components.IndependentComponents().Count());
              Assert.AreEqual(1, components.Cycles().Count());
              Assert.AreEqual(3, components.Single().Count);
        }
        public void Cycle2()
        {
            var graph = new[]
                  {
                    TestValue.Create(1, 2),
                    TestValue.Create(2, 1),
                  };
              var byValue = graph.ToLookup(t => t.Value);
              var components = graph.DetectCycles(s => s.DependsOn.SelectMany(d => byValue[d]));

              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 Cycle3WithStub()
        {
            TestValue<string> vD;
              var graph = new[]
                  {
                    TestValue.Create("A", "B"),
                    TestValue.Create("B", "C"),
                    TestValue.Create("C", "A", "D"),
                    vD = TestValue.Create("D"),
                  };
              var byValue = graph.ToLookup(t => t.Value);
              var components = graph.DetectCycles(s => s.DependsOn.SelectMany(d => byValue[d]));

              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);
        }
        public void TwoIsolated3Cycles()
        {
            var graph = new[]
                  {
                    TestValue.Create(1, 2),
                    TestValue.Create(2, 3),
                    TestValue.Create(3, 1),
                    TestValue.Create(4, 5),
                    TestValue.Create(5, 6),
                    TestValue.Create(6, 4),
                  };
              var byValue = graph.ToLookup(t => t.Value);
              var components = graph.DetectCycles(s => s.DependsOn.SelectMany(d => byValue[d]));

              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 SingleVertex()
 {
     var graph = new[]
           {
             1
           };
       var components = graph.DetectCycles(t => null);
       Assert.AreEqual(1, components.Count);
       Assert.AreEqual(1, components.IndependentComponents().Count());
       Assert.AreEqual(0, components.Cycles().Count());
 }
        public void Cycle4WithStubIgnoreCaseAndTrim()
        {
            var testValues = new
                       {
                         A = TestValue.Create("a ", "B"),
                         B = TestValue.Create(" B", " c "),
                         C = TestValue.Create("C", "A", "D"),
                         D = TestValue.Create("d"),
                         E = TestValue.Create("e", "b"),
                         A2 = TestValue.Create("A ", "B"),
                       };

              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 byValue = graph.ToLookup(t => t.Value, ignoreCase);
              var components = graph.DetectCycles(s => s.DependsOn.SelectMany(d => byValue[d]), TestValue.CreateComparer(ignoreCase));

              Assert.AreEqual(3, components.Count);
              Assert.AreEqual(2, components.IndependentComponents().Count()); // D & E are acyclic
              Assert.AreEqual(1, components.Cycles().Count());
              Assert.AreEqual(1, components.Count(c => c.Count == 3));
              Assert.AreEqual(2, components.Count(c => c.Count == 1));

              var component1 = components.First();

              Assert.IsTrue(component1.Single() == testValues.D); // first component has to be D (used by C which is in a cycle)

              var component2 = components.Skip(1).First().ToList();

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

              Assert.IsTrue(component3.Single() == testValues.E); // 3rd component has to be E (requires B which is in a cycle)

              Assert.IsTrue(component2[0] == testValues.C); // first one has to be C (used by A & B)
              Assert.IsTrue(component2[1] == testValues.B); // first one has to be B (used by A)
              Assert.IsTrue(component2[2] == testValues.A); // first one has to be A (used by C, but was in the list )
        }