public void CheckPredecessorLineGraph() { AdjacencyGraph <int, Edge <int> > g = new AdjacencyGraph <int, Edge <int> >(true); g.AddVertex(1); g.AddVertex(2); g.AddVertex(3); Edge <int> e12 = new Edge <int>(1, 2); g.AddEdge(e12); Edge <int> e23 = new Edge <int>(2, 3); g.AddEdge(e23); Dictionary <Edge <int>, double> weights = DijkstraShortestPathAlgorithm <int, Edge <int> > .UnaryWeightsFromEdgeList(g); DijkstraShortestPathAlgorithm <int, Edge <int> > dij = new DijkstraShortestPathAlgorithm <int, Edge <int> >(g, weights); VertexPredecessorRecorderObserver <int, Edge <int> > vis = new VertexPredecessorRecorderObserver <int, Edge <int> >(); vis.Attach(dij); dij.Compute(1); IList <Edge <int> > col = vis.Path(2); Assert.AreEqual(1, col.Count); Assert.AreEqual(e12, col[0]); col = vis.Path(3); Assert.AreEqual(2, col.Count); Assert.AreEqual(e12, col[0]); Assert.AreEqual(e23, col[1]); }
public void CheckPredecessorLineGraph() { AdjacencyGraph<int, Edge<int>> g = new AdjacencyGraph<int, Edge<int>>(true); g.AddVertex(1); g.AddVertex(2); g.AddVertex(3); Edge<int> e12 = new Edge<int>(1, 2); g.AddEdge(e12); Edge<int> e23 = new Edge<int>(2, 3); g.AddEdge(e23); Dictionary<Edge<int>, double> weights = DijkstraShortestPathAlgorithm<int, Edge<int>>.UnaryWeightsFromEdgeList(g); DijkstraShortestPathAlgorithm<int, Edge<int>> dij = new DijkstraShortestPathAlgorithm<int, Edge<int>>(g, weights); VertexPredecessorRecorderObserver<int, Edge<int>> vis = new VertexPredecessorRecorderObserver<int, Edge<int>>(); vis.Attach(dij); dij.Compute(1); IList<Edge<int>> col = vis.Path(2); Assert.AreEqual(1, col.Count); Assert.AreEqual(e12, col[0]); col = vis.Path(3); Assert.AreEqual(2, col.Count); Assert.AreEqual(e12, col[0]); Assert.AreEqual(e23, col[1]); }
/// <summary> /// Computes a set of eulerian trail, starting at <paramref name="s"/> /// that spans the entire graph. /// </summary> /// <remarks> /// <para> /// This method computes a set of eulerian trail starting at <paramref name="s"/> /// that spans the entire graph.The algorithm outline is as follows: /// </para> /// <para> /// The algorithms iterates throught the Eulerian circuit of the augmented /// graph (the augmented graph is the graph with additional edges to make /// the number of odd vertices even). /// </para> /// <para> /// If the current edge is not temporary, it is added to the current trail. /// </para> /// <para> /// If the current edge is temporary, the current trail is finished and /// added to the trail collection. The shortest path between the /// start vertex <paramref name="s"/> and the target vertex of the /// temporary edge is then used to start the new trail. This shortest /// path is computed using the <see cref="BreadthFirstSearchAlgorithm"/>. /// </para> /// </remarks> /// <param name="s">start vertex</param> /// <returns>eulerian trail set, all starting at s</returns> /// <exception cref="ArgumentNullException">s is a null reference.</exception> /// <exception cref="Exception">Eulerian trail not computed yet.</exception> public ICollection <ICollection <TEdge> > Trails(TVertex s) { if (s == null) { throw new ArgumentNullException("s"); } if (this.Circuit.Count == 0) { throw new Exception("Circuit is empty"); } // find the first edge in the circuit. int i = 0; for (i = 0; i < this.Circuit.Count; ++i) { TEdge e = this.Circuit[i]; if (this.temporaryEdges.Contains(e)) { continue; } if (e.Source.Equals(s)) { break; } } if (i == this.Circuit.Count) { throw new Exception("Did not find vertex in eulerian trail?"); } // create collections List <ICollection <TEdge> > trails = new List <ICollection <TEdge> >(); List <TEdge> trail = new List <TEdge>(); BreadthFirstSearchAlgorithm <TVertex, TEdge> bfs = new BreadthFirstSearchAlgorithm <TVertex, TEdge>(VisitedGraph); VertexPredecessorRecorderObserver <TVertex, TEdge> vis = new VertexPredecessorRecorderObserver <TVertex, TEdge>(); vis.Attach(bfs); bfs.Compute(s); // go throught the edges and build the predecessor table. int start = i; for (; i < this.Circuit.Count; ++i) { TEdge e = this.Circuit[i]; if (this.temporaryEdges.Contains(e)) { // store previous trail and start new one. if (trail.Count != 0) { trails.Add(trail); } // start new trail // take the shortest path from the start vertex to // the target vertex trail = vis.Path(e.Target); } else { trail.Add(e); } } // starting again on the circuit for (i = 0; i < start; ++i) { TEdge e = this.Circuit[i]; if (this.temporaryEdges.Contains(e)) { // store previous trail and start new one. if (trail.Count != 0) { trails.Add(trail); } // start new trail // take the shortest path from the start vertex to // the target vertex trail = vis.Path(e.Target); } else { trail.Add(e); } } // adding the last element if (trail.Count != 0) { trails.Add(trail); } return(trails); }
/// <summary> /// Carries out the shortest path between the two nodes /// ids passed as variables and returns an <see cref="ILineString" /> /// giveing the shortest path. /// </summary> /// <param name="source">The source node</param> /// <param name="destination">The destination node</param> /// <returns>A line string geometric shape of the path</returns> public ILineString Perform(ICoordinate source, ICoordinate destination) { if (!graph.ContainsVertex(source)) throw new ArgumentException("key not found in the graph", "source"); if (!graph.ContainsVertex(destination)) throw new ArgumentException("key not found in the graph", "destination"); // Build algorithm DijkstraShortestPathAlgorithm<ICoordinate, IEdge<ICoordinate>> dijkstra = new DijkstraShortestPathAlgorithm<ICoordinate, IEdge<ICoordinate>>(graph, consts); // Attach a Distance observer to give us the distances between edges VertexDistanceRecorderObserver<ICoordinate, IEdge<ICoordinate>> distanceObserver = new VertexDistanceRecorderObserver<ICoordinate, IEdge<ICoordinate>>(); distanceObserver.Attach(dijkstra); // Attach a Vertex Predecessor Recorder Observer to give us the paths VertexPredecessorRecorderObserver<ICoordinate, IEdge<ICoordinate>> predecessorObserver = new VertexPredecessorRecorderObserver<ICoordinate, IEdge<ICoordinate>>(); predecessorObserver.Attach(dijkstra); // Run the algorithm with A set to be the source dijkstra.Compute(source); // Get the path computed to the destination. IList<IEdge<ICoordinate>> path = predecessorObserver.Path(destination); // Then we need to turn that into a geomery. if (path.Count > 1) return buildString(path); // if the count is greater than one then a // path could not be found, so we return null return null; }