Skip to content

Commit 0794b2d

Browse files
committed
added the bellman ford shortest path thinking to add more of the graphs problems as its likee too emty in the folder
1 parent ec0dc12 commit 0794b2d

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

graphs/BellmanFordShortestPaths.cs

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Collections.Generic;
4+
using Algorithms.Common;
5+
using DataStructures.Graphs;
6+
7+
namespace Algorithms.Graphs
8+
{
9+
public class BellmanFordShortestPaths<TGraph, TVertex>
10+
where TGraph : IGraph<TVertex>, IWeightedGraph<TVertex>
11+
where TVertex : IComparable<TVertex>
12+
{
13+
/// INSTANCE VARIABLES
14+
private int _edgesCount;
15+
private int _verticesCount;
16+
private long[] _distances;
17+
private int[] _predecessors;
18+
private WeightedEdge<TVertex>[] _edgeTo;
19+
20+
// A dictionary that maps node-values to integer indeces
21+
private Dictionary<TVertex, int> _nodesToIndices;
22+
23+
// A dictionary that maps integer index to node-value
24+
private Dictionary<int, TVertex> _indicesToNodes;
25+
26+
// A const that represent an infinite distance
27+
private const Int64 Infinity = Int64.MaxValue;
28+
private const int NilPredecessor = -1;
29+
30+
31+
/// CONSTRUCTOR
32+
public BellmanFordShortestPaths(TGraph Graph, TVertex Source)
33+
{
34+
if (Graph == null) {
35+
throw new ArgumentNullException ();
36+
} else {
37+
if (!Graph.HasVertex (Source))
38+
throw new ArgumentException ("The source vertex doesn't belong to graph.");
39+
40+
// Init
41+
_initializeDataMembers (Graph);
42+
43+
// Traverse the graph
44+
var status = _bellmanFord (Graph, Source);
45+
46+
if (status == false)
47+
throw new Exception ("Negative-weight cycle detected.");
48+
49+
Debug.Assert (_checkOptimalityConditions (Graph, Source));
50+
}
51+
}
52+
53+
54+
/************************************************************************************************************/
55+
56+
57+
/// The Bellman-Ford Algorithm.
58+
/// <>True if shortest-path computation is finished with no negative-weight cycles detected; otehrwise, false.</>
59+
private bool _bellmanFord(TGraph graph, TVertex source)
60+
{
61+
int srcIndex = _nodesToIndices[source];
62+
_distances[srcIndex] = 0;
63+
64+
var edges = graph.Edges as IEnumerable<WeightedEdge<TVertex>>;
65+
66+
// First pass
67+
// Calculate shortest paths and relax all edges.
68+
for (int i = 1; i < graph.VerticesCount - 1; ++i)
69+
{
70+
foreach (var edge in edges)
71+
{
72+
int fromIndex = _nodesToIndices[edge.Source];
73+
int toIndex = _nodesToIndices[edge.Destination];
74+
75+
// calculate a new possible weighted path if the edge weight is less than infinity
76+
var delta = Infinity;
77+
if (edge.Weight < Infinity && (Infinity - edge.Weight) > _distances[fromIndex]) // Handles overflow
78+
delta = _distances[fromIndex] + edge.Weight;
79+
80+
// Relax the edge
81+
// if check is true, a shorter path is found from current to adjacent
82+
if (delta < _distances[toIndex])
83+
{
84+
_edgeTo[toIndex] = edge;
85+
_distances[toIndex] = delta;
86+
_predecessors[toIndex] = fromIndex;
87+
}
88+
}
89+
}
90+
91+
// Second pass
92+
// Check for negative-weight cycles.
93+
foreach (var edge in edges)
94+
{
95+
int fromIndex = _nodesToIndices[edge.Source];
96+
int toIndex = _nodesToIndices[edge.Destination];
97+
98+
// calculate a new possible weighted path if the edge weight is less than infinity
99+
var delta = Infinity;
100+
if (edge.Weight < Infinity && (Infinity - edge.Weight) > _distances[fromIndex]) // Handles overflow
101+
delta = _distances[fromIndex] + edge.Weight;
102+
103+
// if check is true a negative-weight cycle is detected
104+
// return false;
105+
if (delta < _distances[toIndex])
106+
return false;
107+
}
108+
109+
// Completed shortest paths computation.
110+
// No negative edges were detected.
111+
return true;
112+
}
113+
114+
/// Constructors helper function. Initializes some of the data memebers.
115+
private void _initializeDataMembers(TGraph Graph)
116+
{
117+
_edgesCount = Graph.EdgesCount;
118+
_verticesCount = Graph.VerticesCount;
119+
120+
_distances = new Int64[_verticesCount];
121+
_predecessors = new int[_verticesCount];
122+
_edgeTo = new WeightedEdge<TVertex>[_edgesCount];
123+
124+
_nodesToIndices = new Dictionary<TVertex, int>();
125+
_indicesToNodes = new Dictionary<int, TVertex>();
126+
127+
// Reset the information arrays
128+
int i = 0;
129+
foreach (var node in Graph.Vertices)
130+
{
131+
if (i >= _verticesCount)
132+
break;
133+
134+
_edgeTo[i] = null;
135+
_distances[i] = Infinity;
136+
_predecessors[i] = NilPredecessor;
137+
138+
_nodesToIndices.Add(node, i);
139+
_indicesToNodes.Add(i, node);
140+
141+
++i;
142+
}
143+
}
144+
145+
/// Constructors helper function. Checks Optimality Conditions:
146+
/// (i) for all edges e: distTo[e.to()] <= distTo[e.from()] + e.weight()
147+
/// (ii) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight()
148+
private bool _checkOptimalityConditions(TGraph graph, TVertex source)
149+
{
150+
// Get the source index (to be used with the information arrays).
151+
int s = _nodesToIndices[source];
152+
153+
// check that distTo[v] and edgeTo[v] are consistent
154+
if (_distances[s] != 0 || _predecessors[s] != NilPredecessor)
155+
{
156+
Console.WriteLine("distanceTo[s] and edgeTo[s] are inconsistent");
157+
return false;
158+
}
159+
160+
for (int v = 0; v < graph.VerticesCount; v++)
161+
{
162+
if (v == s) continue;
163+
164+
if (_predecessors[v] == NilPredecessor && _distances[v] != Infinity)
165+
{
166+
Console.WriteLine("distanceTo[] and edgeTo[] are inconsistent for at least one vertex.");
167+
return false;
168+
}
169+
}
170+
171+
// check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
172+
foreach (var vertex in graph.Vertices)
173+
{
174+
int v = _nodesToIndices[vertex];
175+
176+
foreach (var edge in graph.NeighboursMap(vertex))
177+
{
178+
int w = _nodesToIndices[edge.Key];
179+
180+
if (_distances[v] + edge.Value < _distances[w])
181+
{
182+
Console.WriteLine("edge " + vertex + "-" + edge.Key + " is not relaxed");
183+
return false;
184+
}
185+
}
186+
}
187+
188+
// check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
189+
foreach (var vertex in graph.Vertices)
190+
{
191+
int w = _nodesToIndices[vertex];
192+
193+
if (_edgeTo[w] == null)
194+
continue;
195+
196+
var edge = _edgeTo[w];
197+
int v = _nodesToIndices[edge.Source];
198+
199+
if (!vertex.IsEqualTo(edge.Destination))
200+
return false;
201+
202+
if ((_distances[v] + edge.Weight) != _distances[w])
203+
{
204+
Console.WriteLine("edge " + edge.Source + "-" + edge.Destination + " on shortest path not tight");
205+
return false;
206+
}
207+
}
208+
209+
return true;
210+
}
211+
212+
213+
/************************************************************************************************************/
214+
215+
216+
/// Determines whether there is a path from the source vertex to this specified vertex.
217+
public bool HasPathTo(TVertex destination)
218+
{
219+
if (!_nodesToIndices.ContainsKey(destination))
220+
throw new Exception("Graph doesn't have the specified vertex.");
221+
222+
int index = _nodesToIndices[destination];
223+
return _distances[index] != Infinity;
224+
}
225+
226+
/// Returns the distance between the source vertex and the specified vertex.
227+
public long DistanceTo(TVertex destination)
228+
{
229+
if (!_nodesToIndices.ContainsKey(destination))
230+
throw new Exception("Graph doesn't have the specified vertex.");
231+
232+
int index = _nodesToIndices[destination];
233+
return _distances[index];
234+
}
235+
236+
/// Returns an enumerable collection of nodes that specify the shortest path from the source vertex to the destination vertex.
237+
public IEnumerable<TVertex> ShortestPathTo(TVertex destination)
238+
{
239+
if (!_nodesToIndices.ContainsKey(destination))
240+
throw new Exception("Graph doesn't have the specified vertex.");
241+
if (!HasPathTo(destination))
242+
return null;
243+
244+
int dstIndex = _nodesToIndices[destination];
245+
var stack = new DataStructures.Lists.Stack<TVertex>();
246+
247+
int index;
248+
for (index = dstIndex; _distances[index] != 0; index = _predecessors[index])
249+
stack.Push(_indicesToNodes[index]);
250+
251+
// Push the source vertex
252+
stack.Push(_indicesToNodes[index]);
253+
254+
return stack;
255+
}
256+
257+
}
258+
259+
}

0 commit comments

Comments
 (0)