PageRenderTime 4842ms CodeModel.GetById 35ms RepoModel.GetById 7ms app.codeStats 0ms

/3.0/sources/QuickGraph/Algorithms/ShortestPath/BellmanFordShortestPathAlgorithm.cs

https://github.com/rhishi/QuickGraph
C# | 248 lines | 146 code | 25 blank | 77 comment | 16 complexity | 3e1b7239aaba7bbc3e71412ba8cdb688 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using QuickGraph.Algorithms.Services;
  4. namespace QuickGraph.Algorithms.ShortestPath
  5. {
  6. /// <summary>
  7. /// Bellman Ford shortest path algorithm.
  8. /// </summary>
  9. /// <remarks>
  10. /// <para>
  11. /// The Bellman-Ford algorithm solves the single-source shortest paths
  12. /// problem for a graph with both positive and negative edge weights.
  13. /// </para>
  14. /// <para>
  15. /// If you only need to solve the shortest paths problem for positive
  16. /// edge weights, Dijkstra's algorithm provides a more efficient
  17. /// alternative.
  18. /// </para>
  19. /// <para>
  20. /// If all the edge weights are all equal to one then breadth-first search
  21. /// provides an even more efficient alternative.
  22. /// </para>
  23. /// </remarks>
  24. /// <reference-ref
  25. /// idref="shi03datastructures"
  26. /// />
  27. public sealed class BellmanFordShortestPathAlgorithm<TVertex, TEdge>
  28. : ShortestPathAlgorithmBase<TVertex,TEdge
  29. , IVertexAndEdgeListGraph<TVertex,TEdge>>
  30. , ITreeBuilderAlgorithm<TVertex, TEdge>
  31. where TEdge : IEdge<TVertex>
  32. {
  33. private readonly Dictionary<TVertex,TVertex> predecessors;
  34. private bool foundNegativeCycle;
  35. public BellmanFordShortestPathAlgorithm(
  36. IVertexAndEdgeListGraph<TVertex, TEdge> visitedGraph,
  37. Func<TEdge, double> weights
  38. )
  39. : this(visitedGraph, weights, DistanceRelaxers.ShortestDistance)
  40. { }
  41. public BellmanFordShortestPathAlgorithm(
  42. IVertexAndEdgeListGraph<TVertex, TEdge> visitedGraph,
  43. Func<TEdge, double> weights,
  44. IDistanceRelaxer distanceRelaxer
  45. )
  46. : this(null, visitedGraph, weights, distanceRelaxer)
  47. { }
  48. public BellmanFordShortestPathAlgorithm(
  49. IAlgorithmComponent host,
  50. IVertexAndEdgeListGraph<TVertex,TEdge> visitedGraph,
  51. Func<TEdge,double> weights,
  52. IDistanceRelaxer distanceRelaxer
  53. )
  54. :base(host, visitedGraph, weights, distanceRelaxer)
  55. {
  56. this.predecessors = new Dictionary<TVertex,TVertex>();
  57. }
  58. public bool FoundNegativeCycle
  59. {
  60. get { return this.foundNegativeCycle;}
  61. }
  62. /// <summary>
  63. /// Invoked on each vertex in the graph before the start of the
  64. /// algorithm.
  65. /// </summary>
  66. public event VertexAction<TVertex> InitializeVertex;
  67. /// <summary>
  68. /// Raises the <see cref="InitializeVertex"/> event.
  69. /// </summary>
  70. /// <param name="v">vertex that raised the event</param>
  71. private void OnInitializeVertex(TVertex v)
  72. {
  73. var eh = this.InitializeVertex;
  74. if (eh != null)
  75. eh(v);
  76. }
  77. /// <summary>
  78. /// Invoked on every edge in the graph |V| times.
  79. /// </summary>
  80. public event EdgeAction<TVertex,TEdge> ExamineEdge;
  81. /// <summary>
  82. /// Raises the <see cref="ExamineEdge"/> event.
  83. /// </summary>
  84. /// <param name="e">edge that raised the event</param>
  85. private void OnExamineEdge(TEdge e)
  86. {
  87. var eh = this.ExamineEdge;
  88. if (eh != null)
  89. eh(e);
  90. }
  91. /// <summary>
  92. /// Invoked if the distance label for the target vertex is not
  93. /// decreased.
  94. /// </summary>
  95. public event EdgeAction<TVertex,TEdge> EdgeNotRelaxed;
  96. /// <summary>
  97. /// Raises the <see cref="EdgeNotRelaxed"/> event.
  98. /// </summary>
  99. /// <param name="e">edge that raised the event</param>
  100. private void OnEdgeNotRelaxed(TEdge e)
  101. {
  102. var eh = this.EdgeNotRelaxed;
  103. if (eh != null)
  104. eh(e);
  105. }
  106. /// <summary>
  107. /// Invoked during the second stage of the algorithm,
  108. /// during the test of whether each edge was minimized.
  109. ///
  110. /// If the edge is minimized then this function is invoked.
  111. /// </summary>
  112. public event EdgeAction<TVertex,TEdge> EdgeMinimized;
  113. /// <summary>
  114. /// Raises the <see cref="EdgeMinimized"/> event.
  115. /// </summary>
  116. /// <param name="e">edge that raised the event</param>
  117. private void OnEdgeMinimized(TEdge e)
  118. {
  119. var eh = this.EdgeMinimized;
  120. if (eh != null)
  121. eh(e);
  122. }
  123. /// <summary>
  124. /// Invoked during the second stage of the algorithm,
  125. /// during the test of whether each edge was minimized.
  126. ///
  127. /// If the edge was not minimized, this function is invoked.
  128. /// This happens when there is a negative cycle in the graph.
  129. /// </summary>
  130. public event EdgeAction<TVertex,TEdge> EdgeNotMinimized;
  131. /// <summary>
  132. /// Raises the <see cref="EdgeNotMinimized"/> event.
  133. /// </summary>
  134. /// <param name="e">edge that raised the event</param>
  135. private void OnEdgeNotMinimized(TEdge e)
  136. {
  137. var eh = this.EdgeNotMinimized;
  138. if (eh != null)
  139. eh(e);
  140. }
  141. /// <summary>
  142. /// Constructed predecessor map
  143. /// </summary>
  144. public IDictionary<TVertex,TVertex> Predecessors
  145. {
  146. get
  147. {
  148. return predecessors;
  149. }
  150. }
  151. protected override void Initialize()
  152. {
  153. base.Initialize();
  154. this.foundNegativeCycle = false;
  155. // init color, distance
  156. this.VertexColors.Clear();
  157. foreach (var u in VisitedGraph.Vertices)
  158. {
  159. this.VertexColors[u] = GraphColor.White;
  160. this.Distances[u] = double.PositiveInfinity;
  161. this.OnInitializeVertex(u);
  162. }
  163. TVertex root;
  164. if (!this.TryGetRootVertex(out root))
  165. foreach (var v in this.VisitedGraph.Vertices)
  166. {
  167. root = v;
  168. break;
  169. }
  170. this.Distances[root] = 0;
  171. }
  172. /// <summary>
  173. /// Applies the Bellman Ford algorithm
  174. /// </summary>
  175. /// <remarks>
  176. /// Does not initialize the predecessor and distance map.
  177. /// </remarks>
  178. /// <returns>true if successful, false if there was a negative cycle.</returns>
  179. protected override void InternalCompute()
  180. {
  181. // getting the number of
  182. int N = this.VisitedGraph.VertexCount;
  183. for (int k = 0; k < N; ++k)
  184. {
  185. bool atLeastOneTreeEdge = false;
  186. foreach (var e in this.VisitedGraph.Edges)
  187. {
  188. this.OnExamineEdge(e);
  189. if (Relax(e))
  190. {
  191. atLeastOneTreeEdge = true;
  192. OnTreeEdge(e);
  193. }
  194. else
  195. this.OnEdgeNotRelaxed(e);
  196. }
  197. if (!atLeastOneTreeEdge)
  198. break;
  199. }
  200. var relaxer = this.DistanceRelaxer;
  201. foreach (var e in this.VisitedGraph.Edges)
  202. {
  203. var edgeWeight = Weights(e);
  204. if (edgeWeight < 0)
  205. throw new InvalidOperationException("non negative edge weight");
  206. if (relaxer.Compare(
  207. relaxer.Combine(
  208. this.Distances[e.Source], edgeWeight),
  209. this.Distances[e.Target]
  210. ) < 0
  211. )
  212. {
  213. this.OnEdgeMinimized(e);
  214. this.foundNegativeCycle = true;
  215. return;
  216. }
  217. else
  218. this.OnEdgeNotMinimized(e);
  219. }
  220. this.foundNegativeCycle = false;
  221. }
  222. }
  223. }