modular_decomposition/md_tree/
functions.rs1use crate::{MDTree, ModuleIndex, ModuleKind};
2
3impl<NodeId: Copy + PartialEq> MDTree<NodeId> {
4 pub fn is_cograph(&self) -> bool {
6 self.module_kinds().all(|node| *node != ModuleKind::Prime)
7 }
8}
9
10struct TwinsBase<'tree, NodeId: Copy + PartialEq, P> {
11 md_tree: &'tree MDTree<NodeId>,
12 stack: Vec<ModuleIndex>,
13 pred: P,
14}
15
16impl<'tree, NodeId: Copy + PartialEq, P: FnMut(&ModuleKind<NodeId>) -> bool> TwinsBase<'tree, NodeId, P> {
17 fn new(md_tree: &'tree MDTree<NodeId>, pred: P) -> Self {
18 let stack = match md_tree.module_kind(md_tree.root()) {
19 Some(ModuleKind::Node(_)) => vec![],
20 _ => vec![md_tree.root()],
21 };
22 Self { md_tree, stack, pred }
23 }
24}
25
26impl<'tree, NodeId: Copy + PartialEq, P: FnMut(&ModuleKind<NodeId>) -> bool> Iterator for TwinsBase<'tree, NodeId, P> {
27 type Item = Vec<NodeId>;
28
29 fn next(&mut self) -> Option<Self::Item> {
30 while let Some(node) = self.stack.pop() {
34 let kind = self.md_tree.module_kind(node).expect("node is valid");
35 if (self.pred)(kind) {
36 let mut leaf_children = vec![];
37 for child in self.md_tree.children(node) {
38 if let Some(ModuleKind::Node(u)) = self.md_tree.module_kind(child) {
39 leaf_children.push(*u);
40 } else {
41 self.stack.push(child);
42 }
43 }
44 if leaf_children.len() >= 2 {
45 return Some(leaf_children);
46 }
47 } else {
48 let children = self
49 .md_tree
50 .children(node)
51 .filter(|child| !matches!(self.md_tree.module_kind(*child), Some(ModuleKind::Node(_))));
52 self.stack.extend(children);
53 }
54 }
55 None
56 }
57}
58
59impl<NodeId: Copy + PartialEq> MDTree<NodeId> {
60 pub fn twins(&self) -> impl Iterator<Item = Vec<NodeId>> + '_ {
84 TwinsBase::new(self, |kind| matches!(kind, ModuleKind::Series | ModuleKind::Parallel))
85 }
86
87 pub fn true_twins(&self) -> impl Iterator<Item = Vec<NodeId>> + '_ {
109 TwinsBase::new(self, |kind| kind == &ModuleKind::Series)
110 }
111
112 pub fn false_twins(&self) -> impl Iterator<Item = Vec<NodeId>> + '_ {
134 TwinsBase::new(self, |kind| kind == &ModuleKind::Parallel)
135 }
136}
137
138#[cfg(test)]
139mod test {
140 use petgraph::graph::{NodeIndex, UnGraph};
141
142 use crate::modular_decomposition;
143 use crate::tests;
144
145 fn to_usize(node_vecs: &[Vec<NodeIndex>]) -> Vec<Vec<usize>> {
146 let mut node_vecs: Vec<Vec<usize>> =
147 node_vecs.iter().map(|nodes| nodes.iter().map(|node| node.index()).collect()).collect();
148 node_vecs.iter_mut().for_each(|nodes| nodes.sort());
149 node_vecs.sort();
150 node_vecs
151 }
152
153 #[test]
154 fn cograph_k5() {
155 let graph = tests::complete_graph(5);
156 let md = modular_decomposition(&graph).unwrap();
157 assert!(md.is_cograph());
158 }
159
160 #[test]
161 fn cograph_e5() {
162 let graph = tests::empty_graph(5);
163 let md = modular_decomposition(&graph).unwrap();
164 assert!(md.is_cograph());
165 }
166
167 #[test]
168 fn cograph_p5() {
169 let graph = tests::path_graph(5);
170 let md = modular_decomposition(&graph).unwrap();
171 assert!(!md.is_cograph());
172 }
173
174 #[test]
175 fn twins_k1() {
176 let graph = tests::complete_graph(1);
177 let md = modular_decomposition(&graph).unwrap();
178 let twins: Vec<_> = md.twins().collect();
179 assert!(twins.is_empty());
180 let true_twins: Vec<_> = md.true_twins().collect();
181 assert!(true_twins.is_empty());
182 let false_twins: Vec<_> = md.false_twins().collect();
183 assert!(false_twins.is_empty());
184 }
185
186 #[test]
187 fn twins_k3() {
188 let graph = tests::complete_graph(3);
189 let md = modular_decomposition(&graph).unwrap();
190 let twins: Vec<_> = md.twins().collect();
191 assert_eq!(to_usize(&twins), [[0, 1, 2]]);
192 let true_twins: Vec<_> = md.true_twins().collect();
193 assert_eq!(to_usize(&true_twins), [[0, 1, 2]]);
194 let false_twins: Vec<_> = md.false_twins().collect();
195 assert_eq!(to_usize(&false_twins), Vec::<Vec<_>>::new());
196 }
197
198 #[test]
199 fn twins_e3() {
200 let graph = tests::empty_graph(3);
201 let md = modular_decomposition(&graph).unwrap();
202 let twins: Vec<_> = md.twins().collect();
203 assert_eq!(to_usize(&twins), [[0, 1, 2]]);
204 let true_twins: Vec<_> = md.true_twins().collect();
205 assert_eq!(to_usize(&true_twins), Vec::<Vec<_>>::new());
206 let false_twins: Vec<_> = md.false_twins().collect();
207 assert_eq!(to_usize(&false_twins), [[0, 1, 2]]);
208 }
209
210 #[test]
211 fn twins_k2_plus_2k1() {
212 let graph = UnGraph::<(), ()>::from_edges([(2, 3)]);
213 let md = modular_decomposition(&graph).unwrap();
214 let twins: Vec<_> = md.twins().collect();
215 assert_eq!(to_usize(&twins), [[0, 1], [2, 3]]);
216 let true_twins: Vec<_> = md.true_twins().collect();
217 assert_eq!(to_usize(&true_twins), [[2, 3]]);
218 let false_twins: Vec<_> = md.false_twins().collect();
219 assert_eq!(to_usize(&false_twins), [[0, 1]]);
220 }
221
222 #[test]
223 fn twins_k2_plus_2k1_complement() {
224 let graph = UnGraph::<(), ()>::from_edges([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)]);
225 let md = modular_decomposition(&graph).unwrap();
226 let twins: Vec<_> = md.twins().collect();
227 assert_eq!(to_usize(&twins), [[0, 1], [2, 3]]);
228 let true_twins: Vec<_> = md.true_twins().collect();
229 assert_eq!(to_usize(&true_twins), [[0, 1]]);
230 let false_twins: Vec<_> = md.false_twins().collect();
231 assert_eq!(to_usize(&false_twins), [[2, 3]]);
232 }
233
234 #[test]
235 fn twins_pace2023_exact_054() {
236 let graph = tests::pace2023_exact_054();
237 let md_tree = modular_decomposition(&graph).unwrap();
238
239 let mut twins: Vec<_> = md_tree.twins().collect();
240 twins.iter_mut().for_each(|nodes| nodes.sort());
241 twins.sort();
242 assert_eq!(
243 to_usize(&twins),
244 [
245 vec![24, 25],
246 vec![32, 35],
247 vec![44, 63, 64],
248 vec![45, 46],
249 vec![48, 49, 50],
250 vec![52, 70],
251 vec![53, 54],
252 vec![55, 56],
253 vec![57, 62],
254 vec![65, 67],
255 vec![68, 69],
256 vec![71, 72]
257 ]
258 );
259
260 let mut true_twins: Vec<_> = md_tree.true_twins().collect();
261 true_twins.iter_mut().for_each(|nodes| nodes.sort());
262 true_twins.sort();
263 assert_eq!(
264 to_usize(&true_twins),
265 [
266 vec![24, 25],
267 vec![45, 46],
268 vec![48, 49, 50],
269 vec![53, 54],
270 vec![55, 56],
271 vec![65, 67],
272 vec![68, 69],
273 vec![71, 72]
274 ]
275 );
276
277 let mut false_twins: Vec<_> = md_tree.false_twins().collect();
278 false_twins.iter_mut().for_each(|nodes| nodes.sort());
279 false_twins.sort();
280 assert_eq!(to_usize(&false_twins), [vec![32, 35], vec![44, 63, 64], vec![52, 70], vec![57, 62]]);
281 }
282}