linnet/half_edge/subgraph/
contracted.rs1use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive};
2
3use crate::half_edge::builder::HedgeNodeBuilder;
4use crate::half_edge::involution::HedgePair;
5use crate::half_edge::nodestore::NodeStorageOps;
6use crate::half_edge::subgraph::{SuBitGraph, SubGraphLike, SubGraphOps};
7use crate::half_edge::{Hedge, HedgeGraph};
8
9use super::{internal::InternalSubGraph, SubSetLike, SubSetOps};
10use super::{Inclusion, ModifySubSet, SubSetIter};
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
15pub struct ContractedSubGraph {
25 pub internal_graph: InternalSubGraph, pub allhedges: SuBitGraph, }
34
35impl Inclusion<Hedge> for ContractedSubGraph {
36 fn includes(&self, hedge_id: &Hedge) -> bool {
37 self.internal_graph.includes(hedge_id) || self.allhedges.includes(hedge_id)
38 }
39
40 fn intersects(&self, other: &Hedge) -> bool {
41 self.includes(other)
42 }
43}
44
45impl Inclusion<HedgePair> for ContractedSubGraph {
46 fn includes(&self, hedge_id: &HedgePair) -> bool {
47 self.internal_graph.includes(hedge_id) || self.allhedges.includes(hedge_id)
48 }
49
50 fn intersects(&self, other: &HedgePair) -> bool {
51 self.includes(other)
52 }
53}
54
55impl Inclusion<ContractedSubGraph> for ContractedSubGraph {
56 fn includes(&self, other: &ContractedSubGraph) -> bool {
57 self.internal_graph.includes(&other.internal_graph)
58 }
59
60 fn intersects(&self, other: &ContractedSubGraph) -> bool {
61 self.allhedges.intersects(&other.allhedges)
62 }
63}
64
65impl Inclusion<SuBitGraph> for ContractedSubGraph {
66 fn includes(&self, other: &SuBitGraph) -> bool {
67 self.internal_graph.includes(other) || self.allhedges.includes(other)
68 }
69
70 fn intersects(&self, other: &SuBitGraph) -> bool {
71 self.allhedges.intersects(other)
72 }
73}
74
75impl Inclusion<Range<Hedge>> for ContractedSubGraph {
76 fn includes(&self, other: &Range<Hedge>) -> bool {
77 self.allhedges.includes(other)
78 }
79
80 fn intersects(&self, other: &Range<Hedge>) -> bool {
81 self.allhedges.intersects(other)
82 }
83}
84
85impl Inclusion<RangeTo<Hedge>> for ContractedSubGraph {
86 fn includes(&self, other: &RangeTo<Hedge>) -> bool {
87 self.allhedges.includes(other)
88 }
89
90 fn intersects(&self, other: &RangeTo<Hedge>) -> bool {
91 (0..other.end.0).any(|a| self.includes(&Hedge(a)))
92 }
93}
94
95impl Inclusion<RangeToInclusive<Hedge>> for ContractedSubGraph {
96 fn includes(&self, other: &RangeToInclusive<Hedge>) -> bool {
97 self.allhedges.includes(other)
98 }
99
100 fn intersects(&self, other: &RangeToInclusive<Hedge>) -> bool {
101 (0..=other.end.0).any(|a| self.includes(&Hedge(a)))
102 }
103}
104
105impl Inclusion<RangeFrom<Hedge>> for ContractedSubGraph {
106 fn includes(&self, other: &RangeFrom<Hedge>) -> bool {
107 self.allhedges.includes(other)
108 }
109
110 fn intersects(&self, other: &RangeFrom<Hedge>) -> bool {
111 (other.start.0..).any(|a| self.includes(&Hedge(a)))
112 }
113}
114
115impl Inclusion<RangeInclusive<Hedge>> for ContractedSubGraph {
116 fn includes(&self, other: &RangeInclusive<Hedge>) -> bool {
117 self.allhedges.includes(other)
118 }
119
120 fn intersects(&self, other: &RangeInclusive<Hedge>) -> bool {
121 (other.start().0..=other.end().0).any(|a| self.includes(&Hedge(a)))
122 }
123}
124impl SubGraphLike for ContractedSubGraph {
125 fn nedges<E, V, H, N: NodeStorageOps<NodeData = V>>(
126 &self,
127 graph: &HedgeGraph<E, V, H, N>,
128 ) -> usize {
129 self.allhedges.nedges(graph)
130 }
131}
132impl SubSetLike for ContractedSubGraph {
133 type Base = SuBitGraph;
134 type BaseIter<'a> = SubSetIter<'a>;
135 fn n_included(&self) -> usize {
136 self.allhedges.n_included()
137 }
138
139 fn size(&self) -> usize {
140 self.allhedges.size()
141 }
142
143 fn has_greater(&self, hedge: Hedge) -> bool {
144 self.allhedges.has_greater(hedge)
145 }
146
147 fn join_mut(&mut self, other: Self) {
148 self.internal_graph.join_mut(other.internal_graph);
149 self.allhedges.join_mut(other.allhedges);
150 }
151
152 fn included(&self) -> &SuBitGraph {
153 self.allhedges.included()
154 }
155
156 fn included_iter(&self) -> Self::BaseIter<'_> {
157 self.allhedges.included_iter()
158 }
159
160 fn string_label(&self) -> String {
167 self.allhedges.string_label() + "⊛" + self.internal_graph.string_label().as_str()
168 }
169
170 fn is_empty(&self) -> bool {
171 self.allhedges.is_empty()
172 }
173 fn empty(size: usize) -> Self {
174 Self {
175 internal_graph: InternalSubGraph::empty(size),
176 allhedges: SuBitGraph::empty(size),
177 }
178 }
179
180 fn from_base62(label: &str, size: usize) -> Option<Self> {
181 let allhedges = SuBitGraph::from_base62(label, size)?;
182 Some(Self {
183 internal_graph: InternalSubGraph::empty(size),
184 allhedges,
185 })
186 }
187}
188
189impl SubGraphOps for ContractedSubGraph {
190 fn complement<E, V, H, N: NodeStorageOps<NodeData = V>>(
191 &self,
192 graph: &HedgeGraph<E, V, H, N>,
193 ) -> Self {
194 let externalhedges =
195 (!self.allhedges.clone()).intersection(&!self.internal_graph.filter.clone());
196
197 Self {
198 internal_graph: InternalSubGraph::empty(graph.n_hedges()),
199 allhedges: externalhedges,
200 }
201 }
202}
203impl SubSetOps for ContractedSubGraph {
204 fn union_with_iter(&mut self, other: impl Iterator<Item = Hedge>) {
205 for h in other {
206 self.allhedges.add(h);
207 }
208 }
209
210 fn union_with(&mut self, other: &Self) {
211 self.internal_graph.intersect_with(&other.internal_graph);
213 self.allhedges.union_with(&other.allhedges);
214 }
215
216 fn intersect_with(&mut self, other: &Self) {
217 self.internal_graph.union_with(&other.internal_graph);
219 self.allhedges.intersect_with(&other.allhedges);
220 }
221
222 fn sym_diff_with(&mut self, other: &Self) {
223 self.internal_graph.union_with(&other.internal_graph);
226 self.allhedges.sym_diff_with(&other.allhedges);
227 }
228
229 fn empty_intersection(&self, other: &Self) -> bool {
230 self.allhedges.empty_intersection(&other.allhedges)
231 }
232
233 fn empty_union(&self, other: &Self) -> bool {
234 self.allhedges.empty_union(&other.allhedges)
235 }
236
237 fn subtract_with(&mut self, other: &Self) {
238 self.internal_graph.union_with(&other.internal_graph);
239 self.allhedges.subtract_with(&other.allhedges);
240 }
241}
242
243impl ContractedSubGraph {
244 pub fn all_edges(&self) -> SuBitGraph {
245 self.internal_graph.filter.union(&self.allhedges)
246 }
247
248 pub fn weakly_disjoint(&self, other: &ContractedSubGraph) -> bool {
249 let internals = self
250 .internal_graph
251 .filter
252 .intersection(&other.internal_graph.filter);
253
254 internals.is_empty()
255 }
256
257 pub fn strongly_disjoint(&self, other: &ContractedSubGraph) -> bool {
258 let internals = self
259 .internal_graph
260 .filter
261 .intersection(&other.internal_graph.filter);
262
263 let externals_in_self = self.internal_graph.filter.intersection(&other.allhedges);
264 let externals_in_other = self.allhedges.intersection(&other.internal_graph.filter);
265
266 internals.is_empty() && externals_in_self.is_empty() && externals_in_other.is_empty()
267 }
268
269 pub fn internal_graph_union(&self, other: &ContractedSubGraph) -> InternalSubGraph {
270 InternalSubGraph {
271 filter: self
272 .internal_graph
273 .filter
274 .union(&other.internal_graph.filter),
275 loopcount: None,
276 }
277 }
278
279 pub fn from_builder<V>(builder: &HedgeNodeBuilder<V>, len: usize) -> Self {
280 let internal_graph = InternalSubGraph::empty(len);
281 let mut externalhedges = SuBitGraph::empty(len);
282
283 for hedge in &builder.hedges {
284 externalhedges.add(*hedge);
285 }
286
287 ContractedSubGraph {
288 internal_graph,
289 allhedges: externalhedges,
290 }
291 }
292
293 pub fn is_node(&self) -> bool {
294 self.internal_graph.is_empty()
295 }
296
297 pub fn is_subgraph(&self) -> bool {
298 !self.is_node()
299 }
300}