simple_graph_algorithms/lib.rs
1//! # Overview
2//!
3//! All algorithms in this crate are run using the [Graph](struct.Graph.html) struct.
4//! It is used to organize nodes that are connected to each other using weighted edges
5//! and to provide a simple to use interface.
6//!
7//! Click [here](algorithms/index.html#algorithms-implemented) to see a list of implemented algorithms.
8//!
9//! # Minimal working example
10//! ```
11//! use simple_graph_algorithms::{Graph, algorithms::{dijkstra, RunAlgorithmError}};
12//!
13//! fn main() -> Result<(), RunAlgorithmError> {
14//! // Create empty graph
15//! let mut graph = Graph::new();
16//!
17//! // Add new nodes to the graph
18//! graph.add_node("a");
19//! graph.add_node("b");
20//! graph.add_node("c");
21//! graph.add_node("d");
22//! graph.add_node("e");
23//!
24//! // Add edges to the graph
25//! graph.add_edge(1, &"a", &"b"); // Adds an edge that leads from a to b with weight 1
26//! graph.add_edge(2, &"a", &"c");
27//! graph.add_edge(5, &"b", &"d");
28//! graph.add_edge(3, &"c", &"a");
29//! graph.add_edge(4, &"d", &"a");
30//! graph.add_edge(2, &"d", &"c");
31//! graph.add_edge(3, &"c", &"e");
32//!
33//! // Calculate the shortest path tree starting at node "a" using Dijkstra's algorithm
34//! let spt = dijkstra(&mut graph, &"a")?;
35//!
36//! // Get the shortest distance from "a" to other nodes
37//! assert_eq!(spt.shortest_distance(&"d"), Some(6));
38//! assert_eq!(spt.shortest_distance(&"c"), Some(2));
39//! assert_eq!(spt.shortest_distance(&"e"), Some(5));
40//!
41//! Ok(())
42//! }
43//! ```
44//! # Features
45//!
46//! | Feature | Description |
47//! | - | - |
48//! | from_instruction | Enables functionality that allows graphs to be parsed from a list of instructions. |
49//! | serde | Serde serialization and deserialization support for some objects. |
50
51use std::{fmt::{Display, Debug}, rc::Rc, cell::RefCell, collections::HashMap, hash::Hash};
52
53#[cfg(feature = "serde")]
54use serde::{Serialize, Deserialize};
55
56/// Contains implementations for the graph to work.
57mod graph;
58/// Contains all algorithms that are implemented in this crate.
59pub mod algorithms;
60/// Graph parsing from a list of instructions.
61#[cfg(feature = "from_instruction")]
62pub mod instruction;
63
64/// A node inside the graph
65#[derive(Clone, Eq, Debug)]
66struct Node<T: Display + Eq> {
67 /// Identifier of this node
68 id: T,
69 /// Edges of this node
70 edges: Vec<Edge<T>>,
71 /// The calculated minimum distance to this node from the start node
72 distance: i32,
73 /// The way to go to get to this node
74 shortest_path: Vec<Rc<RefCell<Node<T>>>>,
75}
76
77// An edge between two nodes inside a graph
78#[derive(Clone, Eq, Ord, PartialOrd, Debug)]
79struct Edge<T: Display + Eq> {
80 /// The "cost" of moving along this edge
81 weight: i32,
82 /// The parent of this edge
83 parent: Rc<RefCell<Node<T>>>,
84 /// Where this edge lands
85 target: Rc<RefCell<Node<T>>>,
86}
87
88/// Graph data structure to organize nodes that are connected to each other with edges.
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub struct Graph<T: Display + Eq + Hash> {
91 /// All nodes contained in this graph
92 //nodes: Vec<Rc<RefCell<Node<T>>>>,
93
94 /// Stores all nodes contained in this graph mapped to the node's id.
95 nodes: HashMap<T, Rc<RefCell<Node<T>>>>,
96}
97
98impl<T: Display + Eq + Hash + Clone> PartialOrd for Graph<T> {
99 /// Compares the size of this graph with the size of another graph.
100 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
101 self.size().partial_cmp(&other.size())
102 }
103}
104
105impl<T: Display + Eq + Hash + Clone> Ord for Graph<T> {
106 /// Compares the size of this graph with the size of another graph.
107 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
108 self.size().cmp(&other.size())
109 }
110}
111
112impl<T: Display + Eq + Hash> Graph<T> {
113
114 /// Resets the distance of each node in the graph back to `i32::MAX` and resets the shortest path string.
115 ///
116 /// Is called each time before a pathfinding algorithm is run.
117 fn reset_nodes(&mut self) {
118 for (_, node) in self.nodes.iter_mut() {
119 node.borrow_mut().distance = i32::MAX;
120 node.borrow_mut().shortest_path = Vec::new();
121 }
122 }
123}
124
125/// Structure to store the shortest path and distance from one node
126/// to other nodes after a pathfinding algorithm has been run on a graph.
127#[derive(Eq, PartialEq, Debug)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129pub struct ShortestPathTree<T: Display + Clone + Hash + Eq> {
130 source: T,
131 results: HashMap<T, Option<(i32, ShortestPath<T>)>>,
132}
133
134impl<T: Display + Clone + Eq + Hash> ShortestPathTree<T> {
135
136 /// Create a new shortest path tree originating at `source`.
137 fn new(source: T) -> Self {
138 Self {
139 source,
140 results: HashMap::new(),
141 }
142 }
143
144 /// Adds a new result to the shortest path tree
145 ///
146 /// The `node_id` is the id of the node for which a result should be added.
147 /// The `distance` is the minimal distance to this node and `shortest_path` is the path taken to get to this node.
148 ///
149 /// If either `distance` or `shortest_path` is None, no path will be added.
150 #[allow(clippy::unnecessary_unwrap)]
151 fn add_result(&mut self, node_id: T, distance: Option<i32>, shortest_path: Option<ShortestPath<T>>) {
152 if shortest_path.is_none() | distance.is_none() {
153 self.results.insert(node_id, None);
154 } else {
155 self.results.insert(node_id, Some((distance.unwrap(), shortest_path.unwrap())));
156 }
157 }
158
159 /// Returns the shortest path to the node with id `target_id`.
160 ///
161 /// If the `target_id` is not contained within the shortest path tree,
162 /// `None` is returned instead of the shortest path.
163 ///
164 /// For further information and for what can be done with the shortest
165 /// path see [ShortestPath](struct.ShortestPath.html).
166 pub fn shortest_path(&self, target_id: &T) -> Option<&ShortestPath<T>> {
167 match self.results.get(target_id)? {
168 Some(res) => Some(&res.1),
169 None => None
170 }
171 }
172
173 /// Returns the shortest distance to the node with id `target_id`.
174 ///
175 /// If the `target_id` is not contained within the shortest path tree,
176 /// `None` is returned instead of the distance.
177 ///
178 /// # Example
179 /// ```
180 /// use simple_graph_algorithms::{Graph, algorithms::dijkstra};
181 /// # use simple_graph_algorithms::algorithms::RunAlgorithmError;
182 /// # fn main() -> Result<(), RunAlgorithmError> {
183 ///
184 /// let mut graph = Graph::new();
185 /// graph.add_node('a');
186 /// graph.add_node('b');
187 /// graph.add_node('c');
188 /// graph.add_edge(1, &'a', &'b');
189 /// graph.add_edge(2, &'b', &'c');
190 ///
191 /// let spt = dijkstra(&mut graph, &'a')?;
192 ///
193 /// assert_eq!(spt.shortest_distance(&'b'), Some(1));
194 /// assert_eq!(spt.shortest_distance(&'c'), Some(3));
195 /// assert_eq!(spt.shortest_distance(&'d'), None);
196 /// # Ok(())
197 /// # }
198 /// ```
199 pub fn shortest_distance(&self, target_id: &T) -> Option<i32> {
200 self.results.get(target_id)?.as_ref().map(|res| res.0)
201 }
202
203 /// Creates a shortest path tree from a graph and the id of a source node. A pathfinding algorithm
204 /// should have run on the graph before the shortest path tree is constructed, to make sure that the
205 /// resulting shortest path tree is not empty.
206 fn from_graph(graph: &Graph<T>, source_id: &T) -> Self {
207 let mut spt = ShortestPathTree::new(source_id.clone());
208 for (id, node) in &graph.nodes {
209 if let Ok(path) = ShortestPath::try_from(node) {
210 spt.add_result(id.clone(), Some(node.borrow().distance), Some(path));
211 } else {
212 spt.add_result(id.clone(), None, None);
213 }
214 }
215 spt
216 }
217
218}
219
220/// The shortest path from one node to another.
221#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
223pub struct ShortestPath<T: Display + Clone> {// Add documentation
224 /// Contains a list of node ids, first entry is the start node, last entry is the target node.
225 path: Vec<T>, //TODO maybe add later that the distance between each node is stored as well
226}
227
228impl<T: Display + Clone> ShortestPath<T> {
229
230 /// Creates a new shortest path from a source node to a target node
231 fn new(path: Vec<T>) -> Self {
232 Self {
233 path,
234 }
235 }
236
237 /// Id of source node where this shortest path starts.
238 ///
239 /// # Example
240 /// ```
241 /// use simple_graph_algorithms::{Graph, algorithms::dijkstra};
242 /// # use simple_graph_algorithms::algorithms::RunAlgorithmError;
243 /// # fn main() -> Result<(), RunAlgorithmError> {
244 ///
245 /// let mut graph = Graph::new();
246 /// graph.add_node('a');
247 /// graph.add_node('b');
248 /// graph.add_edge(4, &'a', &'b');
249 /// let spt = dijkstra(&mut graph, &'a')?;
250 ///
251 /// // Calculate shortest path from a to b using dijkstra's algorithm.
252 /// // It is ok to use .unwrap() here, because we know that the graph contains node b.
253 /// let shortest_path = spt.shortest_path(&'b').unwrap();
254 ///
255 /// assert_eq!(shortest_path.source(), Some(&'a'));
256 /// # Ok(())}
257 /// ```
258 pub fn source(&self) -> Option<&T> {
259 self.path.first()
260 }
261
262 /// Id of target node where this shortest path ends.
263 ///
264 /// # Example
265 /// ```
266 /// use simple_graph_algorithms::{Graph, algorithms::dijkstra};
267 /// # use simple_graph_algorithms::algorithms::RunAlgorithmError;
268 /// # fn main() -> Result<(), RunAlgorithmError> {
269 ///
270 /// let mut graph = Graph::new();
271 /// graph.add_node('a');
272 /// graph.add_node('b');
273 /// graph.add_edge(4, &'a', &'b');
274 /// let spt = dijkstra(&mut graph, &'a')?;
275 ///
276 /// // Calculate shortest path from a to b using dijkstra's algorithm.
277 /// // It is ok to use .unwrap() here, because we know that the graph contains node b.
278 /// let shortest_path = spt.shortest_path(&'b').unwrap();
279 ///
280 /// assert_eq!(shortest_path.target(), Some(&'b'));
281 /// # Ok(())}
282 /// ```
283 pub fn target(&self) -> Option<&T> {
284 self.path.last()
285 }
286
287 /// Id's of nodes that form the shortest path.
288 ///
289 /// First element is the id of the start node.
290 /// Last element is the id of the target node.
291 ///
292 /// # Example
293 /// ```
294 /// use simple_graph_algorithms::{Graph, algorithms::dijkstra};
295 /// # use simple_graph_algorithms::algorithms::RunAlgorithmError;
296 /// # fn main() -> Result<(), RunAlgorithmError> {
297 ///
298 /// let mut graph = Graph::new();
299 /// graph.add_node('a');
300 /// graph.add_node('b');
301 /// graph.add_node('c');
302 /// graph.add_edge(4, &'a', &'b');
303 /// graph.add_edge(2, &'b', &'c');
304 /// let spt = dijkstra(&mut graph, &'a')?;
305 ///
306 /// // Calculate shortest path from a to c using dijkstra's algorithm.
307 /// // It is ok to use .unwrap() here, because we know that the graph contains node c.
308 /// let shortest_path = spt.shortest_path(&'c').unwrap();
309 ///
310 /// assert_eq!(shortest_path.path(), &vec!['a', 'b', 'c']);
311 /// # Ok(())}
312 /// ```
313 pub fn path(&self) -> &Vec<T> {
314 &self.path
315 }
316
317}
318
319impl<T: Display + Clone + Debug> Display for ShortestPath<T> {
320
321 /// Formats the shortest path in a way that can be printed easily.
322 ///
323 /// # Example
324 /// ```
325 /// use simple_graph_algorithms::{Graph, algorithms::dijkstra};
326 /// # use simple_graph_algorithms::algorithms::RunAlgorithmError;
327 /// # fn main() -> Result<(), RunAlgorithmError> {
328 ///
329 /// let mut graph = Graph::new();
330 /// graph.add_node('a');
331 /// graph.add_node('b');
332 /// graph.add_node('c');
333 /// graph.add_edge(4, &'a', &'b');
334 /// graph.add_edge(2, &'b', &'c');
335 /// let spt = dijkstra(&mut graph, &'a')?;
336 ///
337 /// // Calculate shortest path from a to c using dijkstra's algorithm.
338 /// // It is ok to use .unwrap() here, because we know that the graph contains node c.
339 /// let shortest_path = spt.shortest_path(&'c').unwrap();
340 ///
341 /// assert_eq!(shortest_path.to_string(), "a -> b -> c");
342 /// # Ok(())}
343 /// ```
344 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
345 for (i, node_id) in self.path.iter().enumerate() {
346 if i == self.path.len()-1 {
347 // Last node
348 write!(f, "{}", node_id)?;
349 } else {
350 write!(f, "{} -> ", node_id)?;
351 }
352 }
353 Ok(())
354 }
355
356}
357
358#[doc(hidden)]
359impl<T: Display + Clone + Eq> TryFrom<&Rc<RefCell<Node<T>>>> for ShortestPath<T> {
360 type Error = &'static str;
361
362 /// Tries to read the shortest path from the node.
363 ///
364 /// Will fail on the following occasions:
365 ///
366 /// - When the node does not contain a shortest path and the distance is not 0
367 /// - when the distance is `i32::MAX`.
368 fn try_from(value: &Rc<RefCell<Node<T>>>) -> Result<ShortestPath<T>, &'static str> {
369 if value.borrow().distance == 0 {
370 // It is tried to parse the shortest path to the source node
371 return Ok(ShortestPath::new(vec![value.borrow().id.clone()]));
372 } else if value.borrow().distance == i32::MAX || value.borrow().shortest_path.is_empty() {
373 return Err("Unable to create shortest path from vector, vector is empty!");
374 }
375 let mut path = Vec::new();
376 for node in &value.borrow().shortest_path {
377 path.push(node.borrow().id.clone());
378 }
379 path.push(value.borrow().id.clone());
380 Ok(ShortestPath::new(path))
381 }
382}
383
384/// Errors that can occur when edges are added to the graph.
385///
386/// Variants specify what exact node is missing.
387#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
389pub enum AddEdgeError {
390 /// Indicates that the source node is missing from the graph,
391 SourceMissing,
392 /// Indicates that the target node is missing form the graph.
393 TargetMissing,
394 /// Indicates that either node is missing from the graph.
395 BothMissing,
396}
397
398impl ToString for AddEdgeError {
399 fn to_string(&self) -> String {
400 match self {
401 AddEdgeError::SourceMissing => String::from("SourceMissing"),
402 AddEdgeError::TargetMissing => String::from("TargetMissing"),
403 AddEdgeError::BothMissing => String::from("BothMissing"),
404 }
405 }
406}
407
408/// Graph variation used for testing
409#[cfg(test)]
410fn graph_1() -> Graph<&'static str> {
411 let mut graph = Graph::new();
412 graph.add_node("Berlin");
413 graph.add_node("New York");
414 graph.add_node("Brussels");
415 graph.add_node("Copenhagen");
416 graph.add_node("Oslo");
417 graph.add_node("London");
418 graph.add_edge(5, &"Berlin", &"New York");
419 graph.add_edge(6, &"Berlin", &"Brussels");
420 graph.add_edge(2, &"New York", &"Berlin");
421 graph.add_edge(9, &"New York", &"Copenhagen");
422 graph.add_edge(7, &"Brussels", &"Berlin");
423 graph.add_edge(2, &"Brussels", &"Copenhagen");
424 graph.add_edge(5, &"Copenhagen", &"Brussels");
425 graph.add_edge(1, &"Copenhagen", &"New York");
426 graph.add_double_edge(10, &"Copenhagen", &"Oslo");
427 graph
428}
429
430/// Graph variation used for testing
431#[cfg(test)]
432fn graph_2() -> Graph<char> {
433 let mut graph: Graph<char> = Graph::new();
434 graph.add_node('a');
435 graph.add_node('b');
436 graph.add_node('c');
437 graph.add_node('d');
438 graph.add_node('e');
439 graph.add_edge(3, &'a', &'b');
440 graph.add_edge(4, &'a', &'c');
441 graph.add_edge(5, &'b', &'a');
442 graph.add_edge(2, &'b', &'d');
443 graph.add_edge(9, &'c', &'a');
444 graph.add_edge(1, &'c', &'d');
445 graph.add_edge(3, &'d', &'b');
446 graph.add_edge(7, &'d', &'c');
447 graph
448}
449
450#[cfg(test)]
451mod tests {
452
453 mod shortest_path_tree {
454 use crate::{graph_2, algorithms::dijkstra, ShortestPath, graph, ShortestPathTree};
455
456 #[test]
457 fn add_result_test() {
458 let mut spt = ShortestPathTree::new('a');
459 let test_path = ShortestPath::new(vec!['a', 'd', 'c']);
460 spt.add_result('b', Some(5), Some(test_path.clone()));
461 let path = spt.shortest_path(&'b');
462 let distance = spt.shortest_distance(&'b');
463 assert!(path.is_some());
464 assert_eq!(path.unwrap(), &test_path);
465 assert_eq!(distance, Some(5));
466 }
467
468 #[test]
469 fn shortest_path_test() {
470 let mut graph = graph_2();
471 let spt = dijkstra(&mut graph, &'a');
472 assert!(spt.is_ok());
473 let should_path = vec!['a', 'b', 'd'];
474 let sp = ShortestPath::new(should_path);
475 assert_eq!(spt.as_ref().unwrap().shortest_path(&'d'), Some(&sp));
476 let should_path = vec!['a'];
477 let sp = ShortestPath::new(should_path);
478 assert_eq!(spt.unwrap().shortest_path(&'a'), Some(&sp));
479 let spt = dijkstra(&mut graph, &'d');
480 let should_path = vec!['d', 'b', 'a'];
481 let sp = ShortestPath::new(should_path);
482 assert_eq!(spt.unwrap().shortest_path(&'a'), Some(&sp));
483 }
484
485 #[test]
486 fn shortest_distance_test() {
487 let mut graph = graph_2();
488 let spt = dijkstra(&mut graph, &'c');
489 assert!(spt.is_ok());
490 let spt = spt.unwrap();
491 assert_eq!(spt.shortest_distance(&'b'), Some(4));
492 assert_eq!(spt.shortest_distance(&'a'), Some(9));
493 }
494
495 #[test]
496 fn from_graph_test() {
497 let mut graph = graph_2();
498 assert!(dijkstra(&mut graph, &'a').is_ok());
499 let spt = ShortestPathTree::from_graph(&graph, &'a');
500 assert_eq!(spt.source, 'a');
501 assert_eq!(spt.results[&'a'], Some((0, ShortestPath::new(vec!['a']))));
502 }
503 }
504
505 mod shortest_path {
506 use crate::{graph_2, algorithms::dijkstra, ShortestPath};
507
508
509 #[test]
510 fn source_test() {
511 let mut graph = graph_2();
512 let spt = dijkstra(&mut graph, &'a').unwrap();
513 assert_eq!(spt.shortest_path(&'a').unwrap().source(), Some(&'a'));
514 assert_eq!(spt.shortest_path(&'d').unwrap().source(), Some(&'a'));
515 let spt = dijkstra(&mut graph, &'d').unwrap();
516 assert_eq!(spt.shortest_path(&'a').unwrap().source(), Some(&'d'));
517 assert_eq!(spt.shortest_path(&'d').unwrap().source(), Some(&'d'));
518 }
519
520 #[test]
521 fn target_test() {
522 let mut graph = graph_2();
523 let spt = dijkstra(&mut graph, &'a').unwrap();
524 assert_eq!(spt.shortest_path(&'a').unwrap().target(), Some(&'a'));
525 assert_eq!(spt.shortest_path(&'b').unwrap().target(), Some(&'b'));
526 assert_eq!(spt.shortest_path(&'c').unwrap().target(), Some(&'c'));
527 assert_eq!(spt.shortest_path(&'d').unwrap().target(), Some(&'d'));
528 }
529
530 #[test]
531 fn path() {
532 let mut graph = graph_2();
533 let spt = dijkstra(&mut graph, &'a').unwrap();
534 assert_eq!(spt.shortest_path(&'a').unwrap().path(), &vec!['a']);
535 assert_eq!(spt.shortest_path(&'b').unwrap().path(), &vec!['a', 'b']);
536 assert_eq!(spt.shortest_path(&'c').unwrap().path(), &vec!['a', 'c']);
537 assert_eq!(spt.shortest_path(&'d').unwrap().path(), &vec!['a', 'b', 'd']);
538 }
539
540 #[test]
541 fn display() {
542 let mut graph = graph_2();
543 let spt = dijkstra(&mut graph, &'a').unwrap();
544 assert_eq!(spt.shortest_path(&'a').unwrap().to_string(), "a");
545 assert_eq!(spt.shortest_path(&'b').unwrap().to_string(), "a -> b");
546 assert_eq!(spt.shortest_path(&'c').unwrap().to_string(), "a -> c");
547 assert_eq!(spt.shortest_path(&'d').unwrap().to_string(), "a -> b -> d");
548 }
549
550 #[test]
551 fn try_from_rc_ref_cell_node() {
552 let mut graph = graph_2();
553 dijkstra(&mut graph, &'a').unwrap();
554 let node = graph.nodes[&'d'].clone();
555 let shortest_path = ShortestPath::try_from(&node);
556 assert!(shortest_path.is_ok());
557 let shortest_path = shortest_path.unwrap();
558 assert_eq!(shortest_path.source(), Some(&'a'));
559 assert_eq!(shortest_path.target(), Some(&'d'));
560 assert_eq!(shortest_path.path(), &vec!['a', 'b', 'd']);
561 assert_eq!(shortest_path.to_string(), "a -> b -> d");
562 }
563
564 }
565
566}