/// <summary> /// Search strict dangling vertices, for example /// |\ /// | \ /// |__\Y_________Z /// In the above draft, Z is a dangling vertex, but Y is not. /// </summary> /// <returns></returns> public IEnumerable <CurveVertex> SearchDanglingVertices() { // Search none loop vertices. var noneLoopVertices = SearchNoneLoopVertices(); // Depth first search the graph, and find all the path end vertices. var result = new HashSet <CurveVertex>(); var observer = new VertexPredecessorPathRecorderObserver <CurveVertex, SEdge <CurveVertex> >(); var dfs = new DepthFirstSearchAlgorithm <CurveVertex, SEdge <CurveVertex> >((IVertexListGraph <CurveVertex, SEdge <CurveVertex> >)_graph); using (observer.Attach(dfs)) { dfs.Compute(); } // Dangling vertex must be an end path vertex. foreach (var curveVertex in observer.EndPathVertices) { if (!noneLoopVertices.Contains(curveVertex)) { continue; } result.Add(curveVertex); // Check whether this path's root point is a dangling vertex. var root = GetRootVertex(observer.VertexPredecessors, curveVertex); if (root != null && noneLoopVertices.Contains(root.Value)) { result.Add(root.Value); } } return(result); }
public IEnumerable <IEnumerable <SEdge <CurveVertex> > > SearchDanglingPaths() { // Search all none loop vertices var noneLoopVertices = SearchNoneLoopVertices(); var danglingEdges = new List <SEdge <CurveVertex> >(); foreach (var vertex in noneLoopVertices) { IEnumerable <SEdge <CurveVertex> > edges = null; if (_graph.TryGetOutEdges(vertex, out edges)) { danglingEdges.AddRange(edges); } } // Create a small graph. var tempGraph = danglingEdges.ToAdjacencyGraph <CurveVertex, SEdge <CurveVertex> >(); // Deep first search the graph and get all its paths. var observer = new VertexPredecessorPathRecorderObserver <CurveVertex, SEdge <CurveVertex> >(); var dfs = new DepthFirstSearchAlgorithm <CurveVertex, SEdge <CurveVertex> >((IVertexListGraph <CurveVertex, SEdge <CurveVertex> >)tempGraph); using (observer.Attach(dfs)) { dfs.Compute(); } return(observer.AllPaths()); }
public static IList <IEnumerable <TaggedEdge <string, string> > > GetPaths(AdjacencyGraph <string, TaggedEdge <string, string> > g) { var dfs = new DepthFirstSearchAlgorithm <string, TaggedEdge <string, string> >(g); var recorder = new VertexPredecessorPathRecorderObserver <string, TaggedEdge <string, string> >(); List <IEnumerable <TaggedEdge <string, string> > > results = new List <IEnumerable <TaggedEdge <string, string> > >(); using (recorder.Attach(dfs)) { dfs.Compute(); var paths = recorder.AllPaths(); foreach (var p in paths) { results.Add(p); } } return(results); }
public void Attach() { // DFS is used for tests but result may change if using another search algorithm // or another starting point { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); var graph = new AdjacencyGraph <int, Edge <int> >(); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.IsEmpty(recorder.VerticesPredecessors); CollectionAssert.IsEmpty(recorder.EndPathVertices); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVertexRange(new[] { 1, 2 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.IsEmpty(recorder.VerticesPredecessors); CollectionAssert.AreEquivalent(new[] { 1, 2 }, recorder.EndPathVertices); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); // Graph without cycle var edge12 = new Edge <int>(1, 2); var edge13 = new Edge <int>(1, 3); var edge14 = new Edge <int>(1, 4); var edge24 = new Edge <int>(2, 4); var edge31 = new Edge <int>(3, 1); var edge33 = new Edge <int>(3, 3); var edge34 = new Edge <int>(3, 4); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVerticesAndEdgeRange(new[] { edge12, edge13, edge14, edge24, edge31, edge33, edge34 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.AreEqual( new Dictionary <int, Edge <int> > { [2] = edge12, [3] = edge13, [4] = edge24 }, recorder.VerticesPredecessors); CollectionAssert.AreEquivalent(new[] { 3, 4 }, recorder.EndPathVertices); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); // Graph with cycle var edge12 = new Edge <int>(1, 2); var edge13 = new Edge <int>(1, 3); var edge14 = new Edge <int>(1, 4); var edge24 = new Edge <int>(2, 4); var edge31 = new Edge <int>(3, 1); var edge33 = new Edge <int>(3, 3); var edge34 = new Edge <int>(3, 4); var edge41 = new Edge <int>(4, 1); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVerticesAndEdgeRange(new[] { edge12, edge13, edge14, edge24, edge31, edge33, edge34, edge41 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.AreEqual( new Dictionary <int, Edge <int> > { [2] = edge12, [3] = edge13, [4] = edge24 }, recorder.VerticesPredecessors); CollectionAssert.AreEquivalent(new[] { 3, 4 }, recorder.EndPathVertices); } } }
public void AllPaths() { { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); var graph = new AdjacencyGraph <int, Edge <int> >(); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.IsEmpty(recorder.AllPaths()); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVertexRange(new[] { 1, 2 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.IsEmpty(recorder.AllPaths()); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); // Graph without cycle var edge12 = new Edge <int>(1, 2); var edge13 = new Edge <int>(1, 3); var edge14 = new Edge <int>(1, 4); var edge24 = new Edge <int>(2, 4); var edge31 = new Edge <int>(3, 1); var edge33 = new Edge <int>(3, 3); var edge34 = new Edge <int>(3, 4); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVerticesAndEdgeRange(new[] { edge12, edge13, edge14, edge24, edge31, edge33, edge34 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.AreEquivalent( new IEnumerable <Edge <int> >[] { new[] { edge13 }, new[] { edge12, edge24 } }, recorder.AllPaths()); } } { var recorder = new VertexPredecessorPathRecorderObserver <int, Edge <int> >(); // Graph with cycle var edge12 = new Edge <int>(1, 2); var edge13 = new Edge <int>(1, 3); var edge14 = new Edge <int>(1, 4); var edge24 = new Edge <int>(2, 4); var edge31 = new Edge <int>(3, 1); var edge33 = new Edge <int>(3, 3); var edge34 = new Edge <int>(3, 4); var edge41 = new Edge <int>(4, 1); var graph = new AdjacencyGraph <int, Edge <int> >(); graph.AddVerticesAndEdgeRange(new[] { edge12, edge13, edge14, edge24, edge31, edge33, edge34, edge41 }); var dfs = new DepthFirstSearchAlgorithm <int, Edge <int> >(graph); using (recorder.Attach(dfs)) { dfs.Compute(); CollectionAssert.AreEquivalent( new IEnumerable <Edge <int> >[] { new[] { edge13 }, new[] { edge12, edge24 } }, recorder.AllPaths()); } } }