gt_graph_path/
graph_path.rs

1use gt_graph::{Graph, Node};
2use std::fmt::{Debug, Error, Formatter};
3use std::ops::{Deref, DerefMut};
4
5#[derive(Clone)]
6pub struct GraphPath<'a> {
7    graph: &'a dyn Graph,
8    path: Vec<Node>,
9}
10
11impl<'a> PartialEq for GraphPath<'a> {
12    fn eq(&self, other: &Self) -> bool {
13        self.path == other.path
14    }
15}
16
17impl<'a> GraphPath<'a> {
18    #[inline(always)]
19    pub fn new(graph: &'a dyn Graph) -> Self {
20        Self {
21            graph,
22            path: Vec::new(),
23        }
24    }
25
26    #[inline(always)]
27    pub fn new_with_initial_size(graph: &'a dyn Graph, size: usize) -> Self {
28        Self {
29            graph,
30            path: Vec::with_capacity(size),
31        }
32    }
33
34    pub fn from_vec(graph: &'a dyn Graph, src: Vec<Node>) -> Self {
35        Self { graph, path: src }
36    }
37
38    #[inline(always)]
39    pub fn push_validate(&mut self, n: Node) -> Result<(), String> {
40        if self.path.last().is_none()
41            || (1..=self.graph.dimension())
42                .any(|n| self.graph.phi(n, *self.path.last().unwrap()) == n)
43        {
44            self.path.push(n);
45            Ok(())
46        } else {
47            Err("Invalid Path".into())
48        }
49    }
50
51    pub fn is_valid(&self) -> bool {
52        (0..self.path.len() - 1).all(|i| {
53            (1..=self.graph.dimension())
54                .any(|n| self.graph.phi(n, self.path[i]) == self.path[i + 1])
55        })
56    }
57}
58
59impl<'a> Deref for GraphPath<'a> {
60    type Target = Vec<Node>;
61
62    fn deref(&self) -> &Self::Target {
63        &self.path
64    }
65}
66
67impl<'a> DerefMut for GraphPath<'a> {
68    fn deref_mut(&mut self) -> &mut Self::Target {
69        &mut self.path
70    }
71}
72
73impl<'a> Debug for GraphPath<'a> {
74    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
75        let mut s = String::new();
76        if !self.path.is_empty() {
77            s.push_str(&format!(
78                "{:0dim$b}",
79                self.path[0],
80                dim = self.graph.dimension() as usize
81            ));
82            for p in self.path.iter().skip(1) {
83                s.push_str(&format!(
84                    " -> {:0dim$b}",
85                    p,
86                    dim = self.graph.dimension() as usize
87                ));
88            }
89        }
90        write!(f, "NodePath {{ {} }}", s)
91    }
92}
93
94pub trait PathsExt {
95    fn contains_node(&self, n: &Node) -> bool;
96}
97
98impl<'a> PathsExt for Vec<GraphPath<'a>> {
99    fn contains_node(&self, n: &Node) -> bool {
100        self.iter().any(|path| path.contains(n))
101    }
102}