public TravelPath ShortestPath(int sourcePlace, int targetPlace) { var algo = new UndirectedBreadthFirstSearchAlgorithm <int, TravelEdge>(this); algo.SetRootVertex(sourcePlace); var predecessors = new UndirectedVertexPredecessorRecorderObserver <int, TravelEdge>(); predecessors.Attach(algo); algo.Compute(); List <TravelEdge> path = new List <TravelEdge>(); var place = targetPlace; //there is no way to get to the target if (!predecessors.VertexPredecessors.ContainsKey(place)) { return(null); } while (place != sourcePlace) { var edge = predecessors.VertexPredecessors[place]; path.Insert(0, edge); place = edge.getAnotherPlace(place); } return(ConvertToPath(path, sourcePlace)); }
public static UndirectedBreadthFirstSearchAlgorithm <T, Edge <T> > CreateAlgorithmAndMaybeDoComputation <T>( [NotNull] ContractScenario <T> scenario) { var graph = new UndirectedGraph <T, Edge <T> >(); graph.AddVerticesAndEdgeRange(scenario.EdgesInGraph.Select(e => new Edge <T>(e.Source, e.Target))); graph.AddVertexRange(scenario.SingleVerticesInGraph); var algorithm = new UndirectedBreadthFirstSearchAlgorithm <T, Edge <T> >(graph); if (scenario.DoComputation) { algorithm.Compute(scenario.Root); } return(algorithm); }
public void GetVertexColor() { var graph = new UndirectedGraph <int, Edge <int> >(); graph.AddVerticesAndEdge(new Edge <int>(1, 2)); var algorithm = new UndirectedBreadthFirstSearchAlgorithm <int, Edge <int> >(graph); // Algorithm not run // ReSharper disable once ReturnValueOfPureMethodIsNotUsed Assert.Throws <VertexNotFoundException>(() => algorithm.GetVertexColor(1)); algorithm.Compute(1); Assert.AreEqual(GraphColor.Black, algorithm.GetVertexColor(1)); Assert.AreEqual(GraphColor.Black, algorithm.GetVertexColor(2)); }
private void BFS() { watch.Restart(); var found = new List <int>(); var bfs = new UndirectedBreadthFirstSearchAlgorithm <int, Edge>(graph); bfs.DiscoverVertex += v => found.Add(v); bfs.Compute(0); watch.Stop(); span = watch.Elapsed; elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", span.Hours, span.Minutes, span.Seconds, span.Milliseconds / 10); Console.WriteLine("BFS time: " + elapsedTime); Console.WriteLine("BFS elements: " + found.Count); foreach (int index in indexes) { Console.WriteLine(index + ": " + found[index]); } }
private static void RunBFSAndCheck <TVertex, TEdge>( [NotNull] IUndirectedGraph <TVertex, TEdge> graph, [NotNull] TVertex sourceVertex) where TEdge : IEdge <TVertex> { var parents = new Dictionary <TVertex, TVertex>(); var distances = new Dictionary <TVertex, int>(); TVertex currentVertex = default; int currentDistance = 0; var algorithm = new UndirectedBreadthFirstSearchAlgorithm <TVertex, TEdge>(graph); algorithm.InitializeVertex += vertex => { Assert.AreEqual(GraphColor.White, algorithm.VerticesColors[vertex]); }; algorithm.StartVertex += vertex => { Assert.AreEqual(GraphColor.White, algorithm.VerticesColors[vertex]); }; algorithm.DiscoverVertex += vertex => { Assert.AreEqual(GraphColor.Gray, algorithm.VerticesColors[vertex]); if (vertex.Equals(sourceVertex)) { currentVertex = sourceVertex; } else { Assert.IsNotNull(currentVertex); Assert.AreEqual(parents[vertex], currentVertex); // ReSharper disable once AccessToModifiedClosure Assert.AreEqual(distances[vertex], currentDistance + 1); Assert.AreEqual(distances[vertex], distances[parents[vertex]] + 1); } }; algorithm.ExamineEdge += edge => { Assert.IsTrue(edge.Source.Equals(currentVertex) || edge.Target.Equals(currentVertex)); }; algorithm.ExamineVertex += vertex => { TVertex u = vertex; currentVertex = u; // Ensure that the distances monotonically increase. // ReSharper disable AccessToModifiedClosure Assert.IsTrue(distances[u] == currentDistance || distances[u] == currentDistance + 1); if (distances[u] == currentDistance + 1) // New level { ++currentDistance; } // ReSharper restore AccessToModifiedClosure }; algorithm.TreeEdge += (sender, args) => { TVertex u = args.Edge.Source; TVertex v = args.Edge.Target; if (algorithm.VerticesColors[v] == GraphColor.Gray) { TVertex temp = u; u = v; v = temp; } Assert.AreEqual(GraphColor.White, algorithm.VerticesColors[v]); Assert.AreEqual(distances[u], currentDistance); parents[v] = u; distances[v] = distances[u] + 1; }; algorithm.NonTreeEdge += (sender, args) => { TVertex u = args.Edge.Source; TVertex v = args.Edge.Target; if (algorithm.VerticesColors[v] != GraphColor.White) { TVertex temp = u; u = v; v = temp; } Assert.IsFalse(algorithm.VerticesColors[v] == GraphColor.White); if (algorithm.VisitedGraph.IsDirected) { // Cross or back edge Assert.IsTrue(distances[v] <= distances[u] + 1); } else { // Cross edge (or going backwards on a tree edge) Assert.IsTrue( distances[v] == distances[u] || distances[v] == distances[u] + 1 || distances[v] == distances[u] - 1); } }; algorithm.GrayTarget += (sender, args) => { Assert.AreEqual(GraphColor.Gray, algorithm.VerticesColors[args.Target]); }; algorithm.BlackTarget += (sender, args) => { Assert.AreEqual(GraphColor.Black, algorithm.VerticesColors[args.Target]); foreach (TEdge edge in algorithm.VisitedGraph.AdjacentEdges(args.Target)) { Assert.IsFalse(algorithm.VerticesColors[edge.Target] == GraphColor.White); } }; algorithm.FinishVertex += vertex => { Assert.AreEqual(GraphColor.Black, algorithm.VerticesColors[vertex]); }; parents.Clear(); distances.Clear(); currentDistance = 0; foreach (TVertex vertex in graph.Vertices) { distances[vertex] = int.MaxValue; parents[vertex] = vertex; } distances[sourceVertex] = 0; var recorder = new UndirectedVertexPredecessorRecorderObserver <TVertex, TEdge>(); using (recorder.Attach(algorithm)) { algorithm.Compute(sourceVertex); } // All white vertices should be unreachable from the source. foreach (TVertex vertex in graph.Vertices) { if (algorithm.VerticesColors[vertex] == GraphColor.White) { // Check !IsReachable(sourceVertex, vertex, graph); if (recorder.TryGetPath(vertex, out IEnumerable <TEdge> path)) { foreach (TEdge edge in path) { Assert.AreNotEqual(sourceVertex, edge.Source); Assert.AreNotEqual(sourceVertex, edge.Target); } } } } // The shortest path to a child should be one longer than // shortest path to the parent. foreach (TVertex vertex in graph.Vertices) { if (!parents[vertex].Equals(vertex)) // Not the root of the BFS tree { Assert.AreEqual(distances[vertex], distances[parents[vertex]] + 1); } } }
private void Search(IUndirectedGraph<string,Edge<string>> graph, string rootVertex) { Console.WriteLine(rootVertex); algo = new UndirectedBreadthFirstSearchAlgorithm<string,Edge<string>>(graph); try { algo.InitializeVertex += new VertexEventHandler<string>(this.InitializeVertex); algo.DiscoverVertex += new VertexEventHandler<string>(this.DiscoverVertex); algo.ExamineVertex += new VertexEventHandler<string>(this.ExamineVertex); algo.TreeEdge += new EdgeEventHandler<string,Edge<string>>(this.TreeEdge); algo.NonTreeEdge += new EdgeEventHandler<string,Edge<string>>(this.NonTreeEdge); algo.GrayTarget += new EdgeEventHandler<string,Edge<string>>(this.GrayTarget); algo.BlackTarget += new EdgeEventHandler<string,Edge<string>>(this.BlackTarget); algo.FinishVertex += new VertexEventHandler<string>(this.FinishVertex); parents.Clear(); distances.Clear(); currentDistance = 0; sourceVertex = rootVertex; foreach (string v in this.algo.VisitedGraph.Vertices) { distances[v] = int.MaxValue; parents[v] = v; } distances[sourceVertex] = 0; algo.Compute(sourceVertex); CheckBfs(); } finally { algo.InitializeVertex -= new VertexEventHandler<string>(this.InitializeVertex); algo.DiscoverVertex -= new VertexEventHandler<string>(this.DiscoverVertex); algo.ExamineVertex -= new VertexEventHandler<string>(this.ExamineVertex); algo.TreeEdge -= new EdgeEventHandler<string,Edge<string>>(this.TreeEdge); algo.NonTreeEdge -= new EdgeEventHandler<string,Edge<string>>(this.NonTreeEdge); algo.GrayTarget -= new EdgeEventHandler<string,Edge<string>>(this.GrayTarget); algo.BlackTarget -= new EdgeEventHandler<string,Edge<string>>(this.BlackTarget); algo.FinishVertex -= new VertexEventHandler<string>(this.FinishVertex); } }