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); }
// 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(); }
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)); }
// 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(); }
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); }
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); }
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); }
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 EmptyGraph() { var graph = new List<Vertex<int>>(); var detector = new StronglyConnectedComponentFinder<int>(); var cycles = detector.DetectCycle(graph); Assert.AreEqual(0, cycles.Count); }
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 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()); }