Thanks to visit codestin.com
Credit goes to docs.rs

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}