Skip to main content

weavatrix_graph/view/
filtered.rs

1use crate::{EdgeEndpoints, GraphView, IndexGraphView};
2
3#[derive(Debug, Clone, Copy)]
4pub struct EdgeFiltered<'graph, G, Predicate> {
5    graph: &'graph G,
6    predicate: Predicate,
7}
8
9impl<'graph, G, Predicate> EdgeFiltered<'graph, G, Predicate> {
10    #[must_use]
11    pub const fn new(graph: &'graph G, predicate: Predicate) -> Self {
12        Self { graph, predicate }
13    }
14
15    #[must_use]
16    pub const fn inner(&self) -> &'graph G {
17        self.graph
18    }
19}
20
21impl<G, Predicate> GraphView for EdgeFiltered<'_, G, Predicate>
22where
23    G: GraphView,
24    Predicate: Fn(G::Edge) -> bool,
25{
26    type Node = G::Node;
27    type Edge = G::Edge;
28
29    fn node_count(&self) -> usize {
30        self.graph.node_count()
31    }
32
33    fn edge_count(&self) -> usize {
34        self.edge_indices().count()
35    }
36
37    fn contains_node(&self, node: Self::Node) -> bool {
38        self.graph.contains_node(node)
39    }
40
41    fn contains_edge(&self, edge: Self::Edge) -> bool {
42        self.graph.contains_edge(edge) && (self.predicate)(edge)
43    }
44
45    fn node_indices(&self) -> impl Iterator<Item = Self::Node> + '_ {
46        self.graph.node_indices()
47    }
48
49    fn edge_indices(&self) -> impl Iterator<Item = Self::Edge> + '_ {
50        self.graph
51            .edge_indices()
52            .filter(|edge| (self.predicate)(*edge))
53    }
54
55    fn edge_endpoints(&self, edge: Self::Edge) -> Option<EdgeEndpoints<Self::Node>> {
56        self.contains_edge(edge)
57            .then(|| self.graph.edge_endpoints(edge))
58            .flatten()
59    }
60
61    fn outgoing_edges(&self, node: Self::Node) -> impl Iterator<Item = Self::Edge> + '_ {
62        self.graph
63            .outgoing_edges(node)
64            .filter(|edge| (self.predicate)(*edge))
65    }
66
67    fn incoming_edges(&self, node: Self::Node) -> impl Iterator<Item = Self::Edge> + '_ {
68        self.graph
69            .incoming_edges(node)
70            .filter(|edge| (self.predicate)(*edge))
71    }
72}
73
74impl<G, Predicate> IndexGraphView for EdgeFiltered<'_, G, Predicate>
75where
76    G: IndexGraphView,
77    Predicate: Fn(G::Edge) -> bool,
78{
79    fn node_bound(&self) -> usize {
80        self.graph.node_bound()
81    }
82
83    fn edge_bound(&self) -> usize {
84        self.graph.edge_bound()
85    }
86
87    fn node_slot(node: Self::Node) -> usize {
88        G::node_slot(node)
89    }
90
91    fn edge_slot(edge: Self::Edge) -> usize {
92        G::edge_slot(edge)
93    }
94}
95
96#[derive(Debug, Clone, Copy)]
97pub struct NodeFiltered<'graph, G, Predicate> {
98    graph: &'graph G,
99    predicate: Predicate,
100}
101
102impl<'graph, G, Predicate> NodeFiltered<'graph, G, Predicate> {
103    #[must_use]
104    pub const fn new(graph: &'graph G, predicate: Predicate) -> Self {
105        Self { graph, predicate }
106    }
107
108    #[must_use]
109    pub const fn inner(&self) -> &'graph G {
110        self.graph
111    }
112}
113
114impl<G, Predicate> NodeFiltered<'_, G, Predicate>
115where
116    G: GraphView,
117    Predicate: Fn(G::Node) -> bool,
118{
119    fn allows_edge(&self, edge: G::Edge) -> bool {
120        self.graph.edge_endpoints(edge).is_some_and(|endpoints| {
121            (self.predicate)(endpoints.source()) && (self.predicate)(endpoints.target())
122        })
123    }
124}
125
126impl<G, Predicate> GraphView for NodeFiltered<'_, G, Predicate>
127where
128    G: GraphView,
129    Predicate: Fn(G::Node) -> bool,
130{
131    type Node = G::Node;
132    type Edge = G::Edge;
133
134    fn node_count(&self) -> usize {
135        self.node_indices().count()
136    }
137
138    fn edge_count(&self) -> usize {
139        self.edge_indices().count()
140    }
141
142    fn contains_node(&self, node: Self::Node) -> bool {
143        self.graph.contains_node(node) && (self.predicate)(node)
144    }
145
146    fn contains_edge(&self, edge: Self::Edge) -> bool {
147        self.graph.contains_edge(edge) && self.allows_edge(edge)
148    }
149
150    fn node_indices(&self) -> impl Iterator<Item = Self::Node> + '_ {
151        self.graph
152            .node_indices()
153            .filter(|node| (self.predicate)(*node))
154    }
155
156    fn edge_indices(&self) -> impl Iterator<Item = Self::Edge> + '_ {
157        self.graph
158            .edge_indices()
159            .filter(|edge| self.allows_edge(*edge))
160    }
161
162    fn edge_endpoints(&self, edge: Self::Edge) -> Option<EdgeEndpoints<Self::Node>> {
163        self.contains_edge(edge)
164            .then(|| self.graph.edge_endpoints(edge))
165            .flatten()
166    }
167
168    fn outgoing_edges(&self, node: Self::Node) -> impl Iterator<Item = Self::Edge> + '_ {
169        self.graph
170            .outgoing_edges(node)
171            .filter(move |edge| self.contains_node(node) && self.allows_edge(*edge))
172    }
173
174    fn incoming_edges(&self, node: Self::Node) -> impl Iterator<Item = Self::Edge> + '_ {
175        self.graph
176            .incoming_edges(node)
177            .filter(move |edge| self.contains_node(node) && self.allows_edge(*edge))
178    }
179}
180
181impl<G, Predicate> IndexGraphView for NodeFiltered<'_, G, Predicate>
182where
183    G: IndexGraphView,
184    Predicate: Fn(G::Node) -> bool,
185{
186    fn node_bound(&self) -> usize {
187        self.graph.node_bound()
188    }
189
190    fn edge_bound(&self) -> usize {
191        self.graph.edge_bound()
192    }
193
194    fn node_slot(node: Self::Node) -> usize {
195        G::node_slot(node)
196    }
197
198    fn edge_slot(edge: Self::Edge) -> usize {
199        G::edge_slot(edge)
200    }
201}
202
203#[must_use]
204pub const fn edge_filtered<G, Predicate>(
205    graph: &G,
206    predicate: Predicate,
207) -> EdgeFiltered<'_, G, Predicate>
208where
209    G: GraphView,
210    Predicate: Fn(G::Edge) -> bool,
211{
212    EdgeFiltered::new(graph, predicate)
213}
214
215#[must_use]
216pub const fn induced_subgraph_view<G, Predicate>(
217    graph: &G,
218    predicate: Predicate,
219) -> NodeFiltered<'_, G, Predicate>
220where
221    G: GraphView,
222    Predicate: Fn(G::Node) -> bool,
223{
224    NodeFiltered::new(graph, predicate)
225}