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

simple_graph_algorithms/
graph.rs

1use std::{fmt::Display, rc::Rc, cell::RefCell, hash::Hash, collections::HashMap};
2
3use crate::{Node, Edge, Graph, AddEdgeError};
4
5// Node implementations
6
7impl<T: Display + Eq + Clone> Node<T> {
8    
9    /// Creates a new node with id `id`.
10    /// 
11    /// The id is used to compare this node with other nodes and to address this node when searching for a shortest way.
12    fn new(id: T) -> Self {
13        Self {
14            id,
15            edges: Vec::new(),
16            distance: i32::MAX,
17            shortest_path: Vec::new(),
18        }
19    }
20
21}
22
23impl<T: Display + Eq> PartialEq for Node<T> {
24    fn eq(&self, other: &Self) -> bool {
25        self.id == other.id
26    }
27}
28
29impl<T: Display + Eq> Display for Node<T> {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        write!(f, "{}", self.id)
32    }
33}
34
35impl<T: Display + Eq> PartialOrd for Node<T> {
36    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
37        Some(self.distance.cmp(&other.distance).reverse())
38    }
39}
40
41impl<T: Display + Eq> Ord for Node<T> {
42    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
43        self.distance.cmp(&other.distance).reverse()
44    }
45}
46
47// Edge implementations
48
49impl<T: Display + Eq> Edge<T> {
50    /// Creates a new edge
51    /// # Params
52    /// - `weight` the weight of this edge
53    /// - `parent` the node from which the edge originates
54    /// - `target` the node to which the edge lands
55    fn new(weight: i32, parent: Rc<RefCell<Node<T>>>, target: Rc<RefCell<Node<T>>>) -> Self {
56        Self {
57            weight,
58            parent,
59            target,
60        }
61    }
62}
63
64impl<T: Display + Eq> PartialEq for Edge<T> {
65    fn eq(&self, other: &Self) -> bool {
66        self.parent.borrow().id.eq(&other.parent.borrow().id) 
67            && self.target.borrow().id.eq(&other.target.borrow().id)
68            && self.weight.eq(&other.weight)
69    }
70}
71
72// Graph implementations
73
74impl<T: Display + Clone + Eq + Hash> Graph<T> {
75    
76    /// Creates a new and empty graph.
77    pub fn new() -> Self {
78        Self {
79            nodes: HashMap::new(),
80        }
81    }
82
83    /// Adds a new node with id `id` to the graph.
84    /// 
85    /// The `id` is the unique identifier of this node,
86    /// it is used to adddress this node in all other functions.
87    /// 
88    /// Return value indicates if the node was added to
89    /// the graph or if a node with this id already exists.
90    /// 
91    /// # Example
92    /// ```
93    /// use simple_graph_algorithms::Graph;
94    /// 
95    /// let mut graph = Graph::new();
96    /// 
97    /// assert_eq!(graph.add_node("a"), true);
98    /// assert_eq!(graph.add_node("b"), true);
99    /// 
100    /// // Returns false because node with id `b` was already added to the graph.
101    /// assert_eq!(graph.add_node("b"), false);
102    /// ```
103    pub fn add_node(&mut self, id: T) -> bool {
104        if self.nodes.contains_key(&id) {
105            false
106        } else {
107            self.nodes.insert(id.clone(), Rc::new(RefCell::new(Node::new(id))));
108            true
109        }
110    }
111
112    /// Adds new nodes to the graph.
113    /// 
114    /// For each entry in the `ids` vector a new node is added, the entry being the unique identifier of the new node.
115    /// 
116    /// Return value indicates how many nodes where not added because a node with the id already exists.
117    /// 
118    /// # Example
119    /// ```
120    /// use simple_graph_algorithms::Graph;
121    /// 
122    /// let mut graph = Graph::new();
123    /// let ids = vec!["a", "b", "c"];
124    /// 
125    /// assert_eq!(graph.add_nodes(ids.clone()), 0);
126    /// 
127    /// assert_eq!(graph.contains_node(&"a"), true);
128    /// assert_eq!(graph.contains_node(&"b"), true);
129    /// assert_eq!(graph.contains_node(&"c"), true);
130    /// 
131    /// // Add nodes again, returns 3 because all nodes already exist in the graph.
132    /// assert_eq!(graph.add_nodes(ids), 3);
133    /// ```
134    pub fn add_nodes(&mut self, ids: Vec<T>) -> i32 {
135        let mut duplicates = 0;
136        for id in ids {
137            if !self.add_node(id) {
138                duplicates += 1;
139            }
140        }
141        duplicates
142    }
143
144    /// Checks if node with id `id` is contained inside this graph.
145    /// 
146    /// # Example
147    /// ```
148    /// use simple_graph_algorithms::Graph;
149    /// 
150    /// let mut graph = Graph::new();
151    /// 
152    /// graph.add_node("a");
153    /// 
154    /// assert_eq!(graph.contains_node(&"a"), true);
155    /// assert_eq!(graph.contains_node(&"b"), false);
156    /// ```
157    pub fn contains_node(&self, id: &T) -> bool {
158        self.nodes.contains_key(id)
159    }
160
161    /// Adds a new edge to the graph that connects two nodes in a single direction from source to target.
162    /// For that to succeed both nodes are required to be contained within the graph.
163    /// 
164    /// The `weight` defines "the distance" between the nodes with ids `source_id` and `target_id`.
165    /// 
166    /// Returns `true` if the edge was added, if `false` is returned either node is missing in the graph.
167    /// 
168    /// Use [Graph::try_add_edge(&mut self, i32, &T, &T)](struct.Graph.html#method.try_add_edge) instead if you need to know why the edge could not be added.
169    /// 
170    /// # Example
171    /// ```
172    /// use simple_graph_algorithms::Graph;
173    /// use simple_graph_algorithms::AddEdgeError;
174    /// 
175    /// let mut graph = Graph::new();
176    /// 
177    /// graph.add_node("a");
178    /// graph.add_node("b");
179    /// 
180    /// assert_eq!(graph.add_edge(1, &"a", &"b"), true);
181    /// assert_eq!(graph.add_edge(1, &"c", &"d"), false);
182    /// ```
183    pub fn add_edge(&mut self, weight: i32, source_id: &T, target_id: &T) -> bool {
184        if !self.nodes.contains_key(source_id) && !self.nodes.contains_key(target_id) {
185            return false;
186        }
187        let parent = Rc::clone(self.nodes.get(source_id).unwrap());
188        let target = Rc::clone(self.nodes.get(target_id).unwrap());
189        self.nodes.get(source_id).unwrap().borrow_mut().edges.push(Edge::new(weight, parent, target));
190        true
191    }
192
193    /// Tries to add a new edge to the graph that connects two nodes in a single direction from source to target.
194    /// 
195    /// The `weight` defines "the distance" between the nodes with ids `source_id` and `target_id`.
196    /// 
197    /// Returns `Ok(())` when the edge was added or an [AddEdgeError](enum.AddEdgeError.html)
198    /// specifing because of which missing node(s) the edge could not be added.
199    /// 
200    /// # Example
201    /// ```
202    /// use simple_graph_algorithms::Graph;
203    /// use simple_graph_algorithms::AddEdgeError;
204    /// 
205    /// let mut graph = Graph::new();
206    /// 
207    /// graph.add_node("a");
208    /// graph.add_node("b");
209    /// 
210    /// assert_eq!(graph.try_add_edge(1, &"a", &"b"), Ok(()));
211    /// 
212    /// // Errors because node "c" is missing from the graph
213    /// assert_eq!(graph.try_add_edge(1, &"c", &"b"), Err(AddEdgeError::SourceMissing));
214    /// 
215    /// // Errors because node "d" is missing from the graph
216    /// assert_eq!(graph.try_add_edge(1, &"a", &"d"), Err(AddEdgeError::TargetMissing));
217    /// 
218    /// // Errors because nodes "c" and  "d" are missing from the graph
219    /// assert_eq!(graph.try_add_edge(1, &"c", &"d"), Err(AddEdgeError::BothMissing));
220    /// ```
221    pub fn try_add_edge(&mut self, weight: i32, source_id: &T, target_id: &T) -> Result<(), AddEdgeError> {
222        if !self.nodes.contains_key(source_id) && !self.nodes.contains_key(target_id) {
223            return Err(AddEdgeError::BothMissing);
224        } else if !self.nodes.contains_key(source_id) {
225            return Err(AddEdgeError::SourceMissing);
226        } else if !self.nodes.contains_key(target_id) {
227            return Err(AddEdgeError::TargetMissing);
228        }
229        let parent = Rc::clone(self.nodes.get(source_id).unwrap());
230        let target = Rc::clone(self.nodes.get(target_id).unwrap());
231        self.nodes.get(source_id).unwrap().borrow_mut().edges.push(Edge::new(weight, parent, target));
232        Ok(())
233    }
234
235    /// Adds a new edge to the graph that connects two nodes in a both directions.
236    /// For that to succeed both nodes are required to be contained within the graph.
237    /// 
238    /// The `weight` defines "the distance" between the nodes with ids `source_id` and `target_id`.
239    /// 
240    /// Returns `true` if the edge was added, if `false` is returned either node is missing in the graph.
241    /// 
242    /// Use [Graph::try_add_double_edge(&mut self, i32, &T, &T)](struct.Graph.html#method.try_add_double_edge) instead if you need to know why the edge could not be added.
243    /// 
244    /// # Example
245    /// ```
246    /// use simple_graph_algorithms::Graph;
247    /// 
248    /// let mut graph = Graph::new();
249    /// 
250    /// graph.add_node("a");
251    /// graph.add_node("b");
252    /// 
253    /// assert_eq!(graph.add_double_edge(1, &"a", &"b"), true);
254    /// assert_eq!(graph.add_double_edge(1, &"c", &"d"), false);
255    /// ```
256    pub fn add_double_edge(&mut self, weight: i32, source_id: &T, target: &T) -> bool {
257        if !self.nodes.contains_key(source_id) && !self.nodes.contains_key(target) {
258            return false;
259        }
260        let parent = Rc::clone(self.nodes.get(source_id).unwrap());
261        let destination = Rc::clone(self.nodes.get(target).unwrap());
262        self.nodes.get(source_id).unwrap().borrow_mut().edges.push(Edge::new(weight, parent.clone(), destination.clone()));
263        self.nodes.get(target).unwrap().borrow_mut().edges.push(Edge::new(weight, destination, parent));
264        true
265    }
266
267    /// Tries to add a new edge to the graph that connects two nodes in a single direction from source to target.
268    /// 
269    /// The `weight` defines "the distance" between the nodes with ids `source_id` and `target_id`.
270    /// 
271    /// Returns `Ok(())` when the edge was added or an [AddEdgeError](enum.AddEdgeError.html)
272    /// specifing because of which missing node(s) the edge could not be added.
273    /// 
274    /// # Example
275    /// ```
276    /// use simple_graph_algorithms::Graph;
277    /// use simple_graph_algorithms::AddEdgeError;
278    /// 
279    /// let mut graph = Graph::new();
280    /// 
281    /// graph.add_node("a");
282    /// graph.add_node("b");
283    /// 
284    /// assert_eq!(graph.try_add_double_edge(1, &"a", &"b"), Ok(()));
285    /// 
286    /// // Errors because node "c" is missing from the graph
287    /// assert_eq!(graph.try_add_double_edge(1, &"c", &"b"), Err(AddEdgeError::SourceMissing));
288    /// 
289    /// // Errors because node "d" is missing from the graph
290    /// assert_eq!(graph.try_add_double_edge(1, &"a", &"d"), Err(AddEdgeError::TargetMissing));
291    /// 
292    /// // Errors because nodes "c" and  "d" are missing from the graph
293    /// assert_eq!(graph.try_add_double_edge(1, &"c", &"d"), Err(AddEdgeError::BothMissing));
294    /// ```
295    pub fn try_add_double_edge(&mut self, weight: i32, source_id: &T, target_id: &T) -> Result<(), AddEdgeError> {
296        if !self.nodes.contains_key(source_id) && !self.nodes.contains_key(target_id) {
297            return Err(AddEdgeError::BothMissing);
298        } else if !self.nodes.contains_key(source_id) {
299            return Err(AddEdgeError::SourceMissing);
300        } else if !self.nodes.contains_key(target_id) {
301            return Err(AddEdgeError::TargetMissing);
302        }
303        let parent = Rc::clone(self.nodes.get(source_id).unwrap());
304        let destination = Rc::clone(self.nodes.get(target_id).unwrap());
305        self.nodes.get(source_id).unwrap().borrow_mut().edges.push(Edge::new(weight, parent.clone(), destination.clone()));
306        self.nodes.get(target_id).unwrap().borrow_mut().edges.push(Edge::new(weight, destination, parent));
307        Ok(())
308    }
309
310    /// Checks if the graph contains an edge from node with id `source_id` to node with id `target_id`.
311    /// 
312    /// # Example
313    /// ```
314    /// use simple_graph_algorithms::Graph;
315    /// 
316    /// let mut graph = Graph::new();
317    /// 
318    /// graph.add_node("a");
319    /// graph.add_node("b");
320    /// graph.add_edge(1, &"a", &"b");
321    /// 
322    /// assert_eq!(graph.contains_edge(&"a", &"b"), true);
323    /// assert_eq!(graph.contains_edge(&"c", &"d"), false);
324    /// ```
325    pub fn contains_edge(&self, source_id: &T, target_id: &T) -> bool {
326        if !self.nodes.contains_key(source_id) {
327            return false;
328        }
329        for edge in &self.nodes.get(source_id).unwrap().borrow().edges {
330            if &edge.target.borrow().id == target_id {
331                return true;
332            }
333        }
334        false
335    }    
336
337    /// Returns the size of this graph, determined by the amount of nodes contained.
338    /// 
339    /// # Example
340    /// ```
341    /// use simple_graph_algorithms::Graph;
342    /// 
343    /// let mut graph = Graph::new();
344    /// 
345    /// graph.add_node("a");
346    /// graph.add_node("b");
347    /// 
348    /// assert_eq!(graph.size(), 2);
349    /// ```
350    pub fn size(&self) -> usize {
351        self.nodes.len()
352    }
353
354    /// Clears the graph, removing all nodes. Keeps the allocated memory for reuse.
355    /// 
356    /// # Example
357    /// ```
358    /// use simple_graph_algorithms::Graph;
359    /// 
360    /// let mut graph = Graph::new();
361    /// 
362    /// graph.add_node("a");
363    /// graph.add_node("b");
364    /// 
365    /// assert_eq!(graph.size(), 2);
366    /// 
367    /// graph.clear();
368    /// 
369    /// assert_eq!(graph.size(), 0);
370    /// ```
371    pub fn clear(&mut self) {
372        self.nodes.clear();
373    }
374
375}
376
377impl<T: Display + Clone + Eq + Hash> Default for Graph<T> {
378    fn default() -> Self {
379        Self::new()
380    }
381}
382
383impl<T: Display + Eq + Hash> Display for Graph<T> {
384    /// Formats the graph to show all edges between nodes
385    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
386        let mut graph = String::new();
387        graph.push_str(&format!("{:13} | {:08} | edges\n", "id", "distance"));
388        graph.push_str("--------------------------------------------------------------------\n");
389        for node in self.nodes.values() {
390            let id = &node.borrow().id;
391            let distance = node.borrow().distance;
392            if distance != i32::MAX {
393                graph.push_str(&format!("{:13} | {:8} | ", id, distance));
394            } else {
395                graph.push_str(&format!("{:13} | {:8} | ", id, ""));
396            }
397            for edge in &node.borrow().edges {
398                graph.push_str(&format!("(--({})-> {})", edge.weight, edge.target.borrow().id));
399            }
400            graph.push('\n');
401        }
402        write!(f, "{}", graph)
403    }
404}
405
406impl<T: Display + Clone + Eq + Hash + From<String>> From<&Vec<Vec<i32>>> for Graph<T> {
407
408    /// Create a graph from a 2D vector containing i32.
409    /// 
410    /// The i32 value is the edge weight of each edge leading into that node.
411    /// # Example
412    /// ```
413    /// use simple_graph_algorithms::Graph;
414    /// 
415    /// // Prepare example vector
416    /// let mut vec: Vec<Vec<i32>> = Vec::new();
417    /// let vec_inner_1 = vec![3, 4, 5];
418    /// let vec_inner_2 = vec![1, 2, 3];
419    /// let vec_inner_3 = vec![1, 8, 2];
420    /// vec.push(vec_inner_1);
421    /// vec.push(vec_inner_2);
422    /// vec.push(vec_inner_3);
423    /// 
424    /// // Create graph from example vector
425    /// let mut graph = Graph::<String>::from(&vec);
426    /// 
427    /// // Run dijkstra's algorithm
428    /// //assert_eq!(8, dijkstra(&mut graph, &String::from("[0|0]"), &String::from("[2|2]")).unwrap_or(-1));
429    /// ```
430    fn from(value: &Vec<Vec<i32>>) -> Self {
431        let mut graph: Graph<T> = Graph::new();
432        for (i_y, y) in value.iter().enumerate() {
433            for (i_x, _x) in y.iter().enumerate() {
434                graph.add_node(format!("[{}|{}]", i_x, i_y).into());
435            }
436        }
437        for (i_y, y) in value.iter().enumerate() {
438            let max_x_size = y.len();
439            for (i_x, x) in y.iter().enumerate() {
440                for neighbor in neighbor_positions((i_x, i_y), max_x_size, value.len()) {
441                    graph.add_edge(*x, &format!("[{}|{}]", neighbor.0, neighbor.1).into(), &format!("[{}|{}]", i_x, i_y).into());
442                }
443            }
444        }
445        graph
446    }
447}
448
449/// Returns the neighboring positions for a position in a 2D graph.
450/// 
451/// # Example
452/// ```ignore
453/// let neighbors = neighbor_positions((2,2), 10, 10);
454/// assert_eq!((1, 2), neighbors[0]);
455/// assert_eq!((2, 1), neighbors[1]);
456/// assert_eq!((3, 2), neighbors[2]);
457/// assert_eq!((2, 3), neighbors[3]);
458/// ```
459fn neighbor_positions(pos: (usize, usize), max_x_size: usize, max_y_size: usize) -> Vec<(usize, usize)> {
460    let mut positions = Vec::new();
461    if pos.0 != 0 {
462        positions.push((pos.0-1, pos.1));
463    }
464    if pos.1 != 0 {
465        positions.push((pos.0, pos.1-1));
466    }
467    if pos.0 != max_x_size-1 {
468        positions.push((pos.0+1, pos.1));
469    }
470    if pos.1 != max_y_size-1 {
471        positions.push((pos.0, pos.1+1));
472    }
473    positions
474}
475
476#[cfg(test)]
477mod tests {
478    use crate::{Graph, algorithms::dijkstra, graph_1, graph_2};
479
480    fn simple_graph() -> Graph<&'static str> {
481        let mut graph = Graph::new();
482        graph.add_node("a");
483        graph.add_node("b");
484        graph
485    }
486
487    #[test]
488    fn node_test() {
489        let graph = simple_graph();
490        assert!(graph.contains_node(&"a"));
491        assert!(graph.contains_node(&"b"));
492    }
493
494    #[test]
495    fn add_nodes_test() {
496        let mut graph = Graph::new();
497        let vec = vec!["a", "b", "c"];
498        assert_eq!(graph.add_nodes(vec.clone()), 0);
499        assert_eq!(graph.add_nodes(vec), 3);
500
501        let vec = vec!["c", "d", "e"];
502        assert_eq!(graph.add_nodes(vec), 1);
503    }
504
505    #[test]
506    fn add_edge_test() {
507        let mut graph = simple_graph();
508        assert_eq!(graph.add_edge(1, &"a", &"b"), true);
509        assert_eq!(graph.add_edge(1, &"c", &"d"), false);
510        assert!(graph.contains_edge(&"a", &"b"));
511        assert!(!graph.contains_edge(&"b", &"a"));
512    }
513
514    #[test]
515    fn add_double_edge_test() {
516        let mut graph = simple_graph();
517        assert_eq!(graph.add_double_edge(1, &"a", &"b"), true);
518        assert!(graph.contains_edge(&"a", &"b"));
519        assert!(graph.contains_edge(&"b", &"a"));
520    }
521
522    #[test]
523    fn try_add_edge_errors_test() {
524        let mut graph = simple_graph();
525        assert_eq!(graph.try_add_edge(1, &"c", &"b"), Err(crate::AddEdgeError::SourceMissing));
526        assert_eq!(graph.try_add_edge(1, &"b", &"d"), Err(crate::AddEdgeError::TargetMissing));
527        assert_eq!(graph.try_add_edge(1, &"c", &"d"), Err(crate::AddEdgeError::BothMissing));
528    }
529
530    #[test]
531    fn try_add_double_edge_errors_test() {
532        let mut graph = simple_graph();
533        assert_eq!(graph.try_add_double_edge(1, &"c", &"b"), Err(crate::AddEdgeError::SourceMissing));
534        assert_eq!(graph.try_add_double_edge(1, &"b", &"d"), Err(crate::AddEdgeError::TargetMissing));
535        assert_eq!(graph.try_add_double_edge(1, &"c", &"d"), Err(crate::AddEdgeError::BothMissing));
536    }
537
538    #[test]
539    fn graph_from_vec_vec_i32_test() {
540        let mut vec: Vec<Vec<i32>> = Vec::new();
541        let vec_inner_1 = vec![3, 4, 5];
542        let vec_inner_2 = vec![1, 2, 3];
543        let vec_inner_3 = vec![1, 8, 2];
544        vec.push(vec_inner_1);
545        vec.push(vec_inner_2);
546        vec.push(vec_inner_3);
547     
548        let mut graph = Graph::<String>::from(&vec);
549        assert_eq!(graph.size(), 9);
550        assert_eq!(graph.contains_node(&String::from("[0|0]")), true);
551        assert_eq!(graph.contains_node(&String::from("[3|3]")), false);
552        assert_eq!(graph.contains_edge(&String::from("[1|1]"), &String::from("[0|1]")), true);
553        assert_eq!(graph.contains_edge(&String::from("[1|1]"), &String::from("[0|0]")), false);
554    }
555}