weavatrix_graph/view/
filtered.rs1use 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}