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}