graph_algorithms/
bellman_ford.rs

1use crate::{GraphAlgorithm, GraphError};
2
3/// Edge in the graph.
4#[derive(Debug, Clone)]
5pub struct Edge {
6    /// Source node.
7    pub source: usize,
8
9    /// Destination node.
10    pub destination: usize,
11
12    /// Weight of the edge.
13    pub weight: i32,
14}
15
16/// Bellman-Ford Algorithm.
17/// Compute shortest paths from a single source vertex to all of the other vertices in a weighted digraph.
18#[derive(Debug, Clone)]
19pub struct BellmanFordAlgorithm {
20    /// Total number of vertices in the graph.
21    pub total_vertices: usize,
22
23    /// Edges in the graph.
24    pub edges: Vec<Edge>,
25}
26
27impl Default for BellmanFordAlgorithm {
28    /// Create a new default instance of Bellman-Ford Algorithm.
29    ///
30    /// # Returns
31    ///
32    /// New default instance of Bellman-Ford Algorithm.
33    fn default() -> Self {
34        Self::new()
35    }
36}
37
38impl BellmanFordAlgorithm {
39    /// Create a new instance of Bellman-Ford Algorithm.
40    ///
41    /// # Returns
42    ///
43    /// New instance of Bellman-Ford Algorithm.
44    pub fn new() -> Self {
45        BellmanFordAlgorithm {
46            total_vertices: 0,
47            edges: Vec::new(),
48        }
49    }
50
51    /// Set a node's edges to the graph.
52    ///
53    /// # Arguments
54    ///
55    /// - `source`: Source node.
56    /// - `edges`: Edges of the source node.
57    pub fn set_edge(&mut self, source: usize, edges: Vec<(usize, i32)>) {
58        if edges.is_empty() {
59            self.total_vertices = self.total_vertices.max(source + 1);
60            return;
61        }
62
63        for (destination, weight) in edges {
64            self.edges.push(Edge {
65                source,
66                weight,
67                destination,
68            });
69
70            self.total_vertices = self.total_vertices.max(source + 1).max(destination + 1);
71        }
72    }
73
74    /// Set multiple nodes' edges to the graph.
75    ///
76    /// # Arguments
77    ///
78    /// - `nodes`: Vector of tuples where each tuple contains a node and its associated edges.
79    pub fn set_edges(&mut self, nodes: Vec<(usize, Vec<(usize, i32)>)>) {
80        for (source, edges) in nodes {
81            self.set_edge(source, edges);
82        }
83    }
84}
85
86impl GraphAlgorithm for BellmanFordAlgorithm {
87    /// Type of node.
88    type Node = isize;
89
90    /// Type of weight.
91    type Weight = Vec<i32>;
92
93    /// Run Bellman-Ford Algorithm.
94    ///
95    /// # Arguments
96    ///
97    /// - `start`: Starting node.
98    ///
99    /// # Returns
100    ///
101    /// Result containing a vector of shortest paths, or an error if applicable.
102    fn run(&self, start: Option<Self::Node>) -> Result<Self::Weight, GraphError> {
103        let start = start.ok_or(GraphError::MissingStartNode)?;
104
105        let mut distances = vec![i32::MAX; self.total_vertices];
106        distances[start as usize] = 0;
107
108        for _ in 0..self.total_vertices - 1 {
109            let mut is_distance_updated = false;
110
111            for edge in &self.edges {
112                if distances[edge.source] != i32::MAX {
113                    let new_distance = distances[edge.source] + edge.weight;
114
115                    if new_distance < distances[edge.destination] {
116                        distances[edge.destination] = new_distance;
117                        is_distance_updated = true;
118                    }
119                }
120            }
121
122            if !is_distance_updated {
123                break;
124            }
125        }
126
127        for edge in &self.edges {
128            if distances[edge.source] != i32::MAX {
129                let new_distance = distances[edge.source] + edge.weight;
130
131                if new_distance < distances[edge.destination] {
132                    return Err(GraphError::NegativeWeightCycle);
133                }
134            }
135        }
136
137        Ok(distances)
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_new() {
147        let algorithm = BellmanFordAlgorithm::new();
148        let algorithm_default = BellmanFordAlgorithm::default();
149
150        assert_eq!(algorithm.edges.len(), 0);
151        assert_eq!(algorithm_default.edges.len(), 0);
152    }
153
154    #[test]
155    fn test_missing_start_node() {
156        let algorithm = BellmanFordAlgorithm::new();
157
158        assert_eq!(algorithm.run(None), Err(GraphError::MissingStartNode));
159    }
160
161    #[test]
162    fn test_run() {
163        let mut algorithm = BellmanFordAlgorithm {
164            total_vertices: 50,
165            edges: Vec::new(),
166        };
167
168        let edges = vec![
169            (0, 1, 4),
170            (0, 2, 1),
171            (1, 2, 2),
172            (1, 3, 5),
173            (2, 3, 8),
174            (2, 4, 2),
175            (3, 5, 3),
176            (4, 5, 4),
177            (5, 6, 1),
178            (6, 7, 3),
179            (7, 8, 2),
180            (8, 9, 6),
181            (9, 10, 2),
182            (10, 11, 1),
183            (11, 12, 3),
184            (12, 13, 4),
185            (13, 14, 2),
186            (14, 15, 1),
187            (15, 16, 5),
188            (16, 17, 1),
189            (17, 18, 2),
190            (18, 19, 3),
191            (19, 20, 6),
192            (20, 21, 2),
193            (21, 22, 1),
194            (22, 23, 3),
195            (23, 24, 4),
196            (24, 25, 2),
197            (25, 26, 1),
198            (26, 27, 5),
199            (27, 28, 1),
200            (28, 29, 2),
201            (29, 30, 3),
202            (30, 31, 6),
203            (31, 32, 2),
204            (32, 33, 1),
205            (33, 34, 3),
206            (34, 35, 4),
207            (35, 36, 2),
208            (36, 37, 1),
209            (37, 38, 5),
210            (38, 39, 1),
211            (39, 40, 2),
212            (40, 41, 3),
213            (41, 42, 6),
214            (42, 43, 2),
215            (43, 44, 1),
216            (44, 45, 4),
217            (45, 46, 1),
218            (46, 47, 2),
219            (47, 48, 3),
220            (48, 49, 1),
221        ];
222
223        for (source, destination, weight) in edges {
224            algorithm.set_edge(source, vec![(destination, weight)]);
225        }
226
227        let result = algorithm.run(Some(0)).unwrap();
228
229        assert_eq!(result[0], 0);
230
231        for &distance in &result {
232            assert!(distance >= 0 || distance == i32::MAX);
233        }
234
235        for item in result.iter().take(10).skip(1) {
236            assert!(item < &i32::MAX);
237        }
238    }
239
240    #[test]
241    fn test_run_single_node_graph() {
242        let mut algorithm = BellmanFordAlgorithm::new();
243        algorithm.set_edge(0, vec![]);
244
245        assert_eq!(algorithm.run(Some(0)).unwrap(), vec![0]);
246    }
247
248    #[test]
249    fn test_run_simple_graph_no_negative_edges() {
250        let mut algorithm = BellmanFordAlgorithm::new();
251        algorithm.set_edge(0, vec![(1, 4), (2, 3)]);
252        algorithm.set_edge(1, vec![(2, 1), (3, 2)]);
253        algorithm.set_edge(2, vec![(3, 5)]);
254
255        assert_eq!(algorithm.run(Some(0)).unwrap(), vec![0, 4, 3, 6]);
256    }
257
258    #[test]
259    fn test_run_graph_with_negative_edge() {
260        let mut algorithm = BellmanFordAlgorithm::new();
261        algorithm.set_edge(0, vec![(1, 4), (2, 3)]);
262        algorithm.set_edge(1, vec![(2, -2), (3, 2)]);
263        algorithm.set_edge(2, vec![(3, 3)]);
264
265        assert_eq!(algorithm.run(Some(0)).unwrap(), vec![0, 4, 2, 5]);
266    }
267
268    #[test]
269    fn test_run_graph_with_no_edges() {
270        let mut algorithm = BellmanFordAlgorithm::new();
271        algorithm.set_edge(0, vec![]);
272        algorithm.set_edge(1, vec![]);
273        algorithm.set_edge(2, vec![]);
274        algorithm.set_edge(3, vec![]);
275
276        assert_eq!(
277            algorithm.run(Some(0)).unwrap(),
278            vec![0, i32::MAX, i32::MAX, i32::MAX]
279        );
280    }
281
282    #[test]
283    fn test_run_run_from_different_start_node() {
284        let mut algorithm = BellmanFordAlgorithm::new();
285        algorithm.set_edge(0, vec![(1, 4), (2, 3)]);
286        algorithm.set_edge(1, vec![(2, 1), (3, 2)]);
287        algorithm.set_edge(2, vec![(3, 5)]);
288
289        assert_eq!(algorithm.run(Some(1)).unwrap(), vec![i32::MAX, 0, 1, 2]);
290    }
291
292    #[test]
293    fn test_run_disconnected_graph() {
294        let mut algorithm = BellmanFordAlgorithm::new();
295        algorithm.set_edge(0, vec![(1, 4)]);
296        algorithm.set_edge(2, vec![(3, 5)]);
297
298        assert_eq!(
299            algorithm.run(Some(0)).unwrap(),
300            vec![0, 4, i32::MAX, i32::MAX]
301        );
302    }
303
304    #[test]
305    fn test_run_graph_with_negative_weight_cycle() {
306        let mut algorithm = BellmanFordAlgorithm::new();
307        algorithm.set_edges(vec![
308            (0, vec![(1, 1)]),
309            (1, vec![(2, -1)]),
310            (2, vec![(0, -1)]),
311        ]);
312
313        assert_eq!(algorithm.run(Some(0)), Err(GraphError::NegativeWeightCycle));
314    }
315
316    #[test]
317    fn test_run_early_exit_no_updates() {
318        let mut algorithm = BellmanFordAlgorithm::new();
319        algorithm.set_edge(0, vec![(1, 2)]);
320        algorithm.set_edge(1, vec![(2, 3)]);
321        algorithm.set_edge(2, vec![(3, 4)]);
322        algorithm.set_edge(3, vec![(4, 1)]);
323
324        let result = algorithm.run(Some(0)).unwrap();
325
326        assert_eq!(result[0], 0);
327        assert_eq!(result[1], 2);
328        assert_eq!(result[2], 5);
329        assert_eq!(result[3], 9);
330        assert_eq!(result[4], 10);
331    }
332
333    #[test]
334    fn test_run_early_exit_with_no_negative_cycle() {
335        let mut algorithm = BellmanFordAlgorithm::new();
336        algorithm.set_edge(0, vec![(1, 2)]);
337        algorithm.set_edge(1, vec![(2, 3)]);
338        algorithm.set_edge(2, vec![(3, -5)]);
339        algorithm.set_edge(3, vec![(4, 1)]);
340
341        let result = algorithm.run(Some(0)).unwrap();
342
343        assert_eq!(result[0], 0);
344        assert_eq!(result[1], 2);
345        assert_eq!(result[2], 5);
346        assert_eq!(result[3], 0);
347        assert_eq!(result[4], 1);
348    }
349
350    #[test]
351    fn test_run_early_exit_with_negative_cycle() {
352        let mut algorithm = BellmanFordAlgorithm::new();
353        algorithm.set_edge(0, vec![(1, 1)]);
354        algorithm.set_edge(1, vec![(2, -2)]);
355        algorithm.set_edge(2, vec![(0, -1)]); // Negative cycle here
356
357        assert_eq!(algorithm.run(Some(0)), Err(GraphError::NegativeWeightCycle));
358    }
359}