1#![cfg_attr(feature = "unsafe_pointer", allow(dropping_references))]
8
9use std::cmp::Ordering;
10use std::num::NonZeroUsize;
11
12use crate::derivative::Derivative;
13
14use super::dual_module::*;
15use super::pointers::*;
16use super::primal_module::*;
17use super::util::*;
18use super::visualize::*;
19
20#[derive(Derivative)]
21#[derivative(Debug)]
22pub struct PrimalModuleSerial {
23 pub unit_index: usize,
25 pub nodes: Vec<Option<PrimalNodeInternalPtr>>,
27 pub nodes_length: usize,
29 pub is_fusion: bool,
31 pub possible_break: Vec<NodeIndex>,
33 pub debug_resolve_only_one: bool,
35 pub parent: Option<PrimalModuleSerialWeak>,
37 pub index_bias: NodeIndex,
39 pub children: Option<((PrimalModuleSerialWeak, NodeNum), (PrimalModuleSerialWeak, NodeNum))>,
42 pub max_tree_size: usize,
44}
45
46pub type PrimalModuleSerialPtr = ArcManualSafeLock<PrimalModuleSerial>;
47pub type PrimalModuleSerialWeak = WeakManualSafeLock<PrimalModuleSerial>;
48
49impl std::fmt::Debug for PrimalModuleSerialPtr {
50 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
51 let interface = self.read_recursive();
52 write!(f, "{}", interface.unit_index)
53 }
54}
55
56impl std::fmt::Debug for PrimalModuleSerialWeak {
57 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
58 self.upgrade_force().fmt(f)
59 }
60}
61
62#[derive(Derivative)]
63#[derivative(Debug)]
64pub struct AlternatingTreeNode {
65 pub root: PrimalNodeInternalWeak,
67 pub parent: Option<(PrimalNodeInternalWeak, DualNodeWeak)>,
69 pub children: Vec<(PrimalNodeInternalWeak, DualNodeWeak)>,
71 pub depth: usize,
73 pub tree_size: Option<NonZeroUsize>,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub enum MatchTarget {
79 Peer(PrimalNodeInternalWeak),
80 VirtualVertex(VertexIndex),
81}
82
83#[derive(Derivative)]
86#[derivative(Debug)]
87pub struct PrimalNodeInternal {
88 pub origin: DualNodeWeak,
90 pub index: NodeIndex,
92 pub tree_node: Option<AlternatingTreeNode>,
94 pub temporary_match: Option<(MatchTarget, DualNodeWeak)>,
96 pub belonging: PrimalModuleSerialWeak,
98}
99
100pub type PrimalNodeInternalPtr = ArcManualSafeLock<PrimalNodeInternal>;
101pub type PrimalNodeInternalWeak = WeakManualSafeLock<PrimalNodeInternal>;
102
103impl std::fmt::Debug for PrimalNodeInternalPtr {
104 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
105 self.update(); let primal_node_internal = self.read_recursive();
107 write!(f, "{}", primal_node_internal.index)
108 }
109}
110
111impl std::fmt::Debug for PrimalNodeInternalWeak {
112 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
113 self.upgrade_force().fmt(f)
114 }
115}
116
117impl PrimalNodeInternal {
118 pub fn is_free(&self) -> bool {
120 debug_assert!(
121 {
122 let origin_ptr = self.origin.upgrade_force();
123 let node = origin_ptr.read_recursive();
124 node.parent_blossom.is_none()
125 },
126 "do not call this function to a internal node, consider call PrimalModuleSerial::get_outer_node"
127 );
128 if self.tree_node.is_some() {
129 return false;
130 } if self.temporary_match.is_some() {
132 return false;
133 } true
135 }
136
137 pub fn change_sub_tree_root(&mut self, depth: usize, root: PrimalNodeInternalPtr) {
139 let tree_node = self.tree_node.as_mut().unwrap();
140 tree_node.depth = depth;
141 tree_node.root = root.downgrade();
142 for (child_weak, _) in tree_node.children.iter() {
143 let child_ptr = child_weak.upgrade_force();
144 lock_write!(child, child_ptr);
145 child.change_sub_tree_root(depth + 1, root.clone());
146 }
147 }
148}
149
150impl PrimalNodeInternalPtr {
151 pub fn update(&self) -> &Self {
153 let mut current_belonging = self.read_recursive().belonging.upgrade_force();
154 let mut bias = 0;
155 let mut node = self.write();
156 while current_belonging.read_recursive().parent.is_some() {
157 let belonging_module = current_belonging.read_recursive();
158 bias += belonging_module.index_bias;
159 let new_current_belonging = belonging_module.parent.clone().unwrap().upgrade_force();
160 drop(belonging_module);
161 current_belonging = new_current_belonging;
162 }
163 node.belonging = current_belonging.downgrade();
164 node.index += bias;
165 self
166 }
167}
168
169impl PrimalModuleImpl for PrimalModuleSerialPtr {
170 fn new_empty(_initializer: &SolverInitializer) -> Self {
171 Self::new_value(PrimalModuleSerial {
172 unit_index: 0, nodes: vec![],
174 nodes_length: 0,
175 is_fusion: false,
176 possible_break: vec![],
177 debug_resolve_only_one: false,
178 parent: None,
179 index_bias: 0,
180 children: None,
181 max_tree_size: usize::MAX,
185 })
186 }
187
188 fn clear(&mut self) {
189 let mut module = self.write();
190 module.nodes_length = 0; module.possible_break.clear();
192 module.is_fusion = false;
193 module.parent = None;
194 module.index_bias = 0;
195 module.children = None;
196 }
197
198 fn load_defect_dual_node(&mut self, dual_node_ptr: &DualNodePtr) {
199 let belonging = self.downgrade();
200 let node = dual_node_ptr.read_recursive();
201 debug_assert!(
202 matches!(node.class, DualNodeClass::DefectVertex { .. }),
203 "must load a fresh dual module interface, found a blossom"
204 );
205 let mut module = self.write();
206 let local_node_index = module.nodes_length;
207 let node_index = module.nodes_count();
208 debug_assert_eq!(node.index, node_index, "must load in order");
209 let primal_node_internal_ptr =
210 if !module.is_fusion && local_node_index < module.nodes.len() && module.nodes[local_node_index].is_some() {
211 let node_ptr = module.nodes[local_node_index].take().unwrap();
212 let mut node = node_ptr.write();
213 node.origin = dual_node_ptr.downgrade();
214 node.index = node_index;
215 node.tree_node = None;
216 node.temporary_match = None;
217 node.belonging = belonging;
218 drop(node);
219 node_ptr
220 } else {
221 PrimalNodeInternalPtr::new_value(PrimalNodeInternal {
222 origin: dual_node_ptr.downgrade(),
223 index: node_index,
224 tree_node: None,
225 temporary_match: None,
226 belonging,
227 })
228 };
229 module.nodes_length += 1;
230 if module.nodes.len() < module.nodes_length {
231 module.nodes.push(None);
232 }
233 module.nodes[local_node_index] = Some(primal_node_internal_ptr);
234 }
235
236 #[allow(clippy::collapsible_else_if)]
237 fn resolve<D: DualModuleImpl>(
238 &mut self,
239 mut group_max_update_length: GroupMaxUpdateLength,
240 interface_ptr: &DualModuleInterfacePtr,
241 dual_module: &mut D,
242 ) {
243 debug_assert!(!group_max_update_length.is_empty() && group_max_update_length.get_none_zero_growth().is_none());
244 let mut current_conflict_index = 0;
245 let debug_resolve_only_one = self.read_recursive().debug_resolve_only_one;
246 let max_tree_size = self.read_recursive().max_tree_size;
247 while let Some(conflict) = group_max_update_length.pop() {
248 current_conflict_index += 1;
249 if debug_resolve_only_one && current_conflict_index > 1 {
250 break;
252 }
253 match conflict {
255 MaxUpdateLength::Conflicting((node_ptr_1, touching_ptr_1), (node_ptr_2, touching_ptr_2)) => {
256 debug_assert!(
257 node_ptr_1 != node_ptr_2,
258 "one cannot conflict with itself, double check to avoid deadlock"
259 );
260 if self.get_primal_node_internal_ptr_option(&node_ptr_1).is_none() {
261 continue;
262 } if self.get_primal_node_internal_ptr_option(&node_ptr_2).is_none() {
264 continue;
265 } let primal_node_internal_ptr_1 = self.get_outer_node(self.get_primal_node_internal_ptr(&node_ptr_1));
268 let primal_node_internal_ptr_2 = self.get_outer_node(self.get_primal_node_internal_ptr(&node_ptr_2));
269 if primal_node_internal_ptr_1 == primal_node_internal_ptr_2 {
270 debug_assert!(
271 current_conflict_index != 1,
272 "the first conflict cannot be ignored, otherwise may cause hidden infinite loop"
273 );
274 continue; }
276 let mut primal_node_internal_1 = primal_node_internal_ptr_1.write();
277 let mut primal_node_internal_2 = primal_node_internal_ptr_2.write();
278 let grow_state_1 = primal_node_internal_1.origin.upgrade_force().read_recursive().grow_state;
279 let grow_state_2 = primal_node_internal_2.origin.upgrade_force().read_recursive().grow_state;
280 if !grow_state_1.is_against(&grow_state_2) {
281 debug_assert!(
282 current_conflict_index != 1,
283 "the first conflict cannot be ignored, otherwise may cause hidden infinite loop"
284 );
285 continue; }
287 let (free_1, free_2) = (primal_node_internal_1.is_free(), primal_node_internal_2.is_free());
289 if free_1 && free_2 {
290 primal_node_internal_1.temporary_match = Some((
292 MatchTarget::Peer(primal_node_internal_ptr_2.downgrade()),
293 touching_ptr_1.downgrade(),
294 ));
295 primal_node_internal_2.temporary_match = Some((
296 MatchTarget::Peer(primal_node_internal_ptr_1.downgrade()),
297 touching_ptr_2.downgrade(),
298 ));
299 interface_ptr.set_grow_state(
301 &primal_node_internal_1.origin.upgrade_force(),
302 DualNodeGrowState::Stay,
303 dual_module,
304 );
305 interface_ptr.set_grow_state(
306 &primal_node_internal_2.origin.upgrade_force(),
307 DualNodeGrowState::Stay,
308 dual_module,
309 );
310 continue;
311 }
312 if (free_1 && primal_node_internal_2.temporary_match.is_some())
314 || (free_2 && primal_node_internal_1.temporary_match.is_some())
315 {
316 let (
317 free_node_internal_ptr,
318 free_touching_ptr,
319 mut free_node_internal,
320 matched_node_internal_ptr,
321 matched_touching_ptr,
322 mut matched_node_internal,
323 ) = if free_1 {
324 (
325 primal_node_internal_ptr_1.clone(),
326 touching_ptr_1.clone(),
327 primal_node_internal_1,
328 primal_node_internal_ptr_2.clone(),
329 touching_ptr_2.clone(),
330 primal_node_internal_2,
331 )
332 } else {
333 (
334 primal_node_internal_ptr_2.clone(),
335 touching_ptr_2.clone(),
336 primal_node_internal_2,
337 primal_node_internal_ptr_1.clone(),
338 touching_ptr_1.clone(),
339 primal_node_internal_1,
340 )
341 };
342 let (match_target, matched_touching_grandson) =
344 matched_node_internal.temporary_match.as_ref().unwrap().clone();
345 match &match_target {
346 MatchTarget::Peer(leaf_node_internal_weak) => {
347 let leaf_node_internal_ptr = leaf_node_internal_weak.upgrade_force();
348 let mut leaf_node_internal = leaf_node_internal_ptr.write();
349 let mut tree_size = free_node_internal.origin.upgrade_force().read_recursive().defect_size;
350 tree_size = tree_size.saturating_add(
351 matched_node_internal
352 .origin
353 .upgrade_force()
354 .read_recursive()
355 .defect_size
356 .get(),
357 );
358 tree_size = tree_size.saturating_add(
359 leaf_node_internal.origin.upgrade_force().read_recursive().defect_size.get(),
360 );
361 free_node_internal.tree_node = Some(AlternatingTreeNode {
362 root: free_node_internal_ptr.downgrade(),
363 parent: None,
364 children: vec![(matched_node_internal_ptr.downgrade(), free_touching_ptr.downgrade())],
365 depth: 0,
366 tree_size: Some(tree_size),
367 });
368 matched_node_internal.tree_node = Some(AlternatingTreeNode {
369 root: free_node_internal_ptr.downgrade(),
370 parent: Some((free_node_internal_ptr.downgrade(), matched_touching_ptr.downgrade())),
371 children: vec![(leaf_node_internal_weak.clone(), matched_touching_grandson)],
372 depth: 1,
373 tree_size: None, });
375 matched_node_internal.temporary_match = None;
376 leaf_node_internal.tree_node = Some(AlternatingTreeNode {
377 root: free_node_internal_ptr.downgrade(),
378 parent: Some((
379 matched_node_internal_ptr.downgrade(),
380 leaf_node_internal.temporary_match.as_ref().unwrap().1.clone(),
381 )),
382 children: vec![],
383 depth: 2,
384 tree_size: None, });
386 leaf_node_internal.temporary_match = None;
387 if tree_size.get() > max_tree_size {
389 drop(free_node_internal);
390 drop(matched_node_internal);
391 drop(leaf_node_internal);
392 self.collapse_tree(free_node_internal_ptr, interface_ptr, dual_module);
393 } else {
394 interface_ptr.set_grow_state(
395 &free_node_internal.origin.upgrade_force(),
396 DualNodeGrowState::Grow,
397 dual_module,
398 );
399 interface_ptr.set_grow_state(
400 &matched_node_internal.origin.upgrade_force(),
401 DualNodeGrowState::Shrink,
402 dual_module,
403 );
404 interface_ptr.set_grow_state(
405 &leaf_node_internal.origin.upgrade_force(),
406 DualNodeGrowState::Grow,
407 dual_module,
408 );
409 }
410 continue;
411 }
412 MatchTarget::VirtualVertex(_) => {
413 free_node_internal.temporary_match = Some((
415 MatchTarget::Peer(matched_node_internal_ptr.downgrade()),
416 free_touching_ptr.downgrade(),
417 ));
418 matched_node_internal.temporary_match = Some((
419 MatchTarget::Peer(free_node_internal_ptr.downgrade()),
420 matched_touching_ptr.downgrade(),
421 ));
422 interface_ptr.set_grow_state(
424 &free_node_internal.origin.upgrade_force(),
425 DualNodeGrowState::Stay,
426 dual_module,
427 );
428 interface_ptr.set_grow_state(
429 &matched_node_internal.origin.upgrade_force(),
430 DualNodeGrowState::Stay,
431 dual_module,
432 );
433 continue;
434 }
435 }
436 }
437 if (free_1 && primal_node_internal_2.tree_node.is_some())
439 || (primal_node_internal_1.tree_node.is_some() && free_2)
440 {
441 let (
442 tree_node_internal_ptr,
443 tree_touching_ptr,
444 tree_node_internal,
445 free_node_internal_ptr,
446 free_touching_ptr,
447 mut free_node_internal,
448 ) = if primal_node_internal_1.tree_node.is_some() {
449 (
450 primal_node_internal_ptr_1.clone(),
451 touching_ptr_1.clone(),
452 primal_node_internal_1,
453 primal_node_internal_ptr_2.clone(),
454 touching_ptr_2.clone(),
455 primal_node_internal_2,
456 )
457 } else {
458 (
459 primal_node_internal_ptr_2.clone(),
460 touching_ptr_2.clone(),
461 primal_node_internal_2,
462 primal_node_internal_ptr_1.clone(),
463 touching_ptr_1.clone(),
464 primal_node_internal_1,
465 )
466 };
467 free_node_internal.temporary_match = Some((
468 MatchTarget::Peer(tree_node_internal_ptr.downgrade()),
469 free_touching_ptr.downgrade(),
470 ));
471 interface_ptr.set_grow_state(
472 &free_node_internal.origin.upgrade_force(),
473 DualNodeGrowState::Stay,
474 dual_module,
475 );
476 drop(tree_node_internal); Self::augment_tree_given_matched(
478 tree_node_internal_ptr,
479 free_node_internal_ptr,
480 tree_touching_ptr.downgrade(),
481 interface_ptr,
482 dual_module,
483 );
484 continue;
485 }
486 if (primal_node_internal_1.tree_node.is_some() && primal_node_internal_2.temporary_match.is_some())
488 || (primal_node_internal_1.temporary_match.is_some() && primal_node_internal_2.tree_node.is_some())
489 {
490 let (
491 tree_node_internal_ptr,
492 tree_touching_ptr,
493 mut tree_node_internal,
494 matched_node_internal_ptr,
495 matched_touching_ptr,
496 mut matched_node_internal,
497 ) = if primal_node_internal_1.tree_node.is_some() {
498 (
499 primal_node_internal_ptr_1.clone(),
500 touching_ptr_1.clone(),
501 primal_node_internal_1,
502 primal_node_internal_ptr_2.clone(),
503 touching_ptr_2.clone(),
504 primal_node_internal_2,
505 )
506 } else {
507 (
508 primal_node_internal_ptr_2.clone(),
509 touching_ptr_2.clone(),
510 primal_node_internal_2,
511 primal_node_internal_ptr_1.clone(),
512 touching_ptr_1.clone(),
513 primal_node_internal_1,
514 )
515 };
516 let match_target = matched_node_internal.temporary_match.as_ref().unwrap().0.clone();
517 match &match_target {
518 MatchTarget::Peer(leaf_node_internal_weak) => {
519 let leaf_node_internal_ptr = leaf_node_internal_weak.upgrade_force();
520 let tree_node = tree_node_internal.tree_node.as_mut().unwrap();
521 debug_assert!(tree_node.depth % 2 == 0, "conflicting one must be + node");
522 tree_node
524 .children
525 .push((matched_node_internal_ptr.downgrade(), tree_touching_ptr.downgrade()));
526 matched_node_internal.tree_node = Some(AlternatingTreeNode {
528 root: tree_node.root.clone(),
529 parent: Some((tree_node_internal_ptr.downgrade(), matched_touching_ptr.downgrade())),
530 children: vec![(
531 leaf_node_internal_weak.clone(),
532 matched_node_internal.temporary_match.as_ref().unwrap().1.clone(),
533 )],
534 depth: tree_node.depth + 1,
535 tree_size: None,
536 });
537 matched_node_internal.temporary_match = None;
538 let mut leaf_node_internal = leaf_node_internal_ptr.write();
539 leaf_node_internal.tree_node = Some(AlternatingTreeNode {
540 root: tree_node.root.clone(),
541 parent: Some((
542 matched_node_internal_ptr.downgrade(),
543 leaf_node_internal.temporary_match.as_ref().unwrap().1.clone(),
544 )),
545 children: vec![],
546 depth: tree_node.depth + 2,
547 tree_size: None,
548 });
549 leaf_node_internal.temporary_match = None;
550 let root_node_ptr = &tree_node.root.clone().upgrade_force();
552 drop(tree_node_internal);
553 let mut root_node = root_node_ptr.write();
554 let root_tree_node = root_node.tree_node.as_mut().unwrap();
555 let mut tree_size = *root_tree_node.tree_size.as_ref().unwrap();
556 tree_size = tree_size.saturating_add(
557 matched_node_internal
558 .origin
559 .upgrade_force()
560 .read_recursive()
561 .defect_size
562 .get(),
563 );
564 tree_size = tree_size.saturating_add(
565 leaf_node_internal.origin.upgrade_force().read_recursive().defect_size.get(),
566 );
567 root_tree_node.tree_size = Some(tree_size);
568 if tree_size.get() > max_tree_size {
570 drop(matched_node_internal);
571 drop(leaf_node_internal);
572 self.collapse_tree(root_node_ptr.clone(), interface_ptr, dual_module);
573 } else {
574 interface_ptr.set_grow_state(
575 &matched_node_internal.origin.upgrade_force(),
576 DualNodeGrowState::Shrink,
577 dual_module,
578 );
579 interface_ptr.set_grow_state(
580 &leaf_node_internal.origin.upgrade_force(),
581 DualNodeGrowState::Grow,
582 dual_module,
583 );
584 }
585 continue;
586 }
587 MatchTarget::VirtualVertex(_) => {
588 matched_node_internal.temporary_match = Some((
590 MatchTarget::Peer(tree_node_internal_ptr.downgrade()),
591 matched_touching_ptr.downgrade(),
592 ));
593 drop(matched_node_internal); drop(tree_node_internal); Self::augment_tree_given_matched(
596 tree_node_internal_ptr,
597 matched_node_internal_ptr,
598 tree_touching_ptr.downgrade(),
599 interface_ptr,
600 dual_module,
601 );
602 continue;
603 }
604 }
605 }
606 if primal_node_internal_1.tree_node.is_some() && primal_node_internal_2.tree_node.is_some() {
608 let root_1 = primal_node_internal_1.tree_node.as_ref().unwrap().root.clone();
609 let root_2 = primal_node_internal_2.tree_node.as_ref().unwrap().root.clone();
610 if root_1 == root_2 {
612 let root_weak = primal_node_internal_1.tree_node.as_ref().unwrap().root.clone();
614 drop(primal_node_internal_1);
615 drop(primal_node_internal_2);
616 let tree_size = {
617 let root_ptr = root_weak.upgrade_force();
618 let tree_size = root_ptr.read_recursive().tree_node.as_ref().unwrap().tree_size;
619 tree_size.unwrap()
620 };
621 let (lca_ptr, path_1, path_2) = self.find_lowest_common_ancestor(
623 primal_node_internal_ptr_1.clone(),
624 primal_node_internal_ptr_2.clone(),
625 );
626 let nodes_circle = {
627 let mut nodes_circle: Vec<DualNodePtr> =
628 path_1.iter().map(|ptr| ptr.read_recursive().origin.upgrade_force()).collect();
629 nodes_circle.push(lca_ptr.read_recursive().origin.upgrade_force());
630 for i in (0..path_2.len()).rev() {
631 nodes_circle.push(path_2[i].read_recursive().origin.upgrade_force());
632 }
633 nodes_circle
634 };
635 let touching_children = {
637 let mut touching_children = Vec::<(DualNodeWeak, DualNodeWeak)>::new();
638 if !path_1.is_empty() {
639 for (idx, ptr) in path_1.iter().enumerate() {
640 let node = ptr.read_recursive();
641 let tree_node = node.tree_node.as_ref().unwrap();
642 let left_touching_ptr = if idx == 0 {
643 touching_ptr_1.downgrade()
644 } else {
645 let last_ptr = path_1[idx - 1].downgrade();
646 let idx = tree_node
647 .children
648 .iter()
649 .position(|(ptr, _)| ptr == &last_ptr)
650 .expect("should find child");
651 tree_node.children[idx].1.clone()
652 };
653 let right_touching_ptr = tree_node.parent.as_ref().unwrap().1.clone();
654 touching_children.push((left_touching_ptr, right_touching_ptr));
655 }
656 }
657 {
658 let node = lca_ptr.read_recursive();
660 let tree_node = node.tree_node.as_ref().unwrap();
661 let left_touching_ptr = if path_1.is_empty() {
662 touching_ptr_1.downgrade()
663 } else {
664 let left_ptr = path_1[path_1.len() - 1].downgrade();
665 let left_idx = tree_node
666 .children
667 .iter()
668 .position(|(ptr, _)| ptr == &left_ptr)
669 .expect("should find child");
670 tree_node.children[left_idx].1.clone()
671 };
672 let right_touching_ptr = if path_2.is_empty() {
673 touching_ptr_2.downgrade()
674 } else {
675 let right_ptr = path_2[path_2.len() - 1].downgrade();
676 let right_idx = tree_node
677 .children
678 .iter()
679 .position(|(ptr, _)| ptr == &right_ptr)
680 .expect("should find child");
681 tree_node.children[right_idx].1.clone()
682 };
683 touching_children.push((left_touching_ptr, right_touching_ptr));
684 }
685 if !path_2.is_empty() {
686 for (idx, ptr) in path_2.iter().enumerate().rev() {
687 let node = ptr.read_recursive();
688 let tree_node = node.tree_node.as_ref().unwrap();
689 let left_touching_ptr = tree_node.parent.as_ref().unwrap().1.clone();
690 let right_touching_ptr = if idx == 0 {
691 touching_ptr_2.downgrade()
692 } else {
693 let last_ptr = path_2[idx - 1].downgrade();
694 let idx = tree_node
695 .children
696 .iter()
697 .position(|(ptr, _)| ptr == &last_ptr)
698 .expect("should find child");
699 tree_node.children[idx].1.clone()
700 };
701 touching_children.push((left_touching_ptr, right_touching_ptr));
702 }
703 }
704 touching_children
705 };
706 let blossom_node_ptr =
707 interface_ptr.create_blossom(nodes_circle, touching_children, dual_module);
708 let primal_node_internal_blossom_ptr = {
709 let belonging = self.downgrade();
711 let mut module = self.write();
712 let local_node_index = module.nodes_length;
713 let node_index = module.nodes_count();
714 let primal_node_internal_blossom_ptr = if !module.is_fusion
715 && local_node_index < module.nodes.len()
716 && module.nodes[local_node_index].is_some()
717 {
718 let node_ptr = module.nodes[local_node_index].take().unwrap();
719 let mut node = node_ptr.write();
720 node.origin = blossom_node_ptr.downgrade();
721 node.index = node_index;
722 node.tree_node = None;
723 node.temporary_match = None;
724 node.belonging = belonging;
725 drop(node);
726 node_ptr
727 } else {
728 PrimalNodeInternalPtr::new_value(PrimalNodeInternal {
729 origin: blossom_node_ptr.downgrade(),
730 index: node_index,
731 tree_node: None,
732 temporary_match: None,
733 belonging,
734 })
735 };
736 module.nodes_length += 1;
737 if module.nodes.len() < module.nodes_length {
738 module.nodes.push(None);
739 }
740 let cloned_primal_node_internal_blossom_ptr = primal_node_internal_blossom_ptr.clone();
741 module.nodes[local_node_index] = Some(primal_node_internal_blossom_ptr); cloned_primal_node_internal_blossom_ptr
743 };
744 let mut children = vec![];
746 for path in [&path_1, &path_2] {
747 if !path.is_empty() {
748 let mut last_ptr = path[0].downgrade();
749 for (height, ptr) in path.iter().enumerate() {
750 let mut node = ptr.write();
751 if height == 0 {
752 let tree_node = node.tree_node.as_ref().unwrap();
753 for (child_ptr, child_touching_ptr) in tree_node.children.iter() {
754 children.push((child_ptr.clone(), child_touching_ptr.clone()));
755 }
756 } else {
757 if height % 2 == 0 {
758 let tree_node = node.tree_node.as_ref().unwrap();
759 for (child_ptr, child_touching_ptr) in tree_node.children.iter() {
760 if child_ptr != &last_ptr {
761 children.push((child_ptr.clone(), child_touching_ptr.clone()));
763 }
764 }
765 }
766 }
767 node.tree_node = None; last_ptr = ptr.downgrade();
769 }
770 }
771 }
772 let mut lca = lca_ptr.write();
773 let lca_tree_node = lca.tree_node.as_ref().unwrap();
774 {
775 for (child_ptr, child_touching_ptr) in lca_tree_node.children.iter() {
777 if !path_1.is_empty() && &path_1[path_1.len() - 1].downgrade() == child_ptr {
778 continue;
779 }
780 if !path_2.is_empty() && &path_2[path_2.len() - 1].downgrade() == child_ptr {
781 continue;
782 }
783 children.push((child_ptr.clone(), child_touching_ptr.clone()));
784 }
785 }
786 if lca_tree_node.parent.is_some() || !children.is_empty() {
787 let mut primal_node_internal_blossom = primal_node_internal_blossom_ptr.write();
788 let new_tree_root = if lca_tree_node.depth == 0 {
789 primal_node_internal_blossom_ptr.clone()
790 } else {
791 lca_tree_node.root.upgrade_force()
792 };
793 let tree_node = AlternatingTreeNode {
794 root: new_tree_root.downgrade(),
795 parent: lca_tree_node.parent.clone(),
796 children,
797 depth: lca_tree_node.depth,
798 tree_size: if lca_tree_node.depth == 0 { Some(tree_size) } else { None },
799 };
800 if lca_tree_node.parent.is_some() {
801 let (parent_weak, _) = lca_tree_node.parent.as_ref().unwrap();
802 let parent_ptr = parent_weak.upgrade_force();
803 lock_write!(parent, parent_ptr);
804 let parent_tree_node = parent.tree_node.as_mut().unwrap();
805 debug_assert!(
806 parent_tree_node.children.len() == 1,
807 "lca's parent should be a - node with only one child"
808 );
809 let touching_ptr = parent_tree_node.children[0].1.clone(); parent_tree_node.children.clear();
811 parent_tree_node
812 .children
813 .push((primal_node_internal_blossom_ptr.downgrade(), touching_ptr));
814 }
815 if !tree_node.children.is_empty() {
816 for (child_weak, _) in tree_node.children.iter() {
818 let child_ptr = child_weak.upgrade_force();
819 lock_write!(child, child_ptr);
820 let child_tree_node = child.tree_node.as_mut().unwrap();
821 debug_assert!(child_tree_node.parent.is_some(), "child should have a parent");
822 let touching_ptr = child_tree_node.parent.as_ref().unwrap().1.clone(); child_tree_node.parent =
824 Some((primal_node_internal_blossom_ptr.downgrade(), touching_ptr));
825 }
826 primal_node_internal_blossom.tree_node = Some(tree_node);
827 primal_node_internal_blossom.change_sub_tree_root(lca_tree_node.depth, new_tree_root);
828 } else {
829 primal_node_internal_blossom.tree_node = Some(tree_node);
830 }
831 }
832 lca.tree_node = None;
833 continue;
834 } else {
835 drop(primal_node_internal_1); drop(primal_node_internal_2); Self::augment_tree_given_matched(
838 primal_node_internal_ptr_1.clone(),
839 primal_node_internal_ptr_2.clone(),
840 touching_ptr_1.downgrade(),
841 interface_ptr,
842 dual_module,
843 );
844 Self::augment_tree_given_matched(
845 primal_node_internal_ptr_2.clone(),
846 primal_node_internal_ptr_1.clone(),
847 touching_ptr_2.downgrade(),
848 interface_ptr,
849 dual_module,
850 );
851 continue;
852 }
853 }
854 unreachable!()
855 }
856 MaxUpdateLength::TouchingVirtual((node_ptr, touching_ptr), (virtual_vertex_index, is_mirror)) => {
857 if self.get_primal_node_internal_ptr_option(&node_ptr).is_none() {
858 continue;
859 } let primal_node_internal_ptr = self.get_outer_node(self.get_primal_node_internal_ptr(&node_ptr));
861 let mut primal_node_internal = primal_node_internal_ptr.write();
862 let grow_state = primal_node_internal.origin.upgrade_force().read_recursive().grow_state;
863 if grow_state != DualNodeGrowState::Grow {
864 debug_assert!(
865 current_conflict_index != 1,
866 "the first conflict cannot be ignored, otherwise may cause hidden infinite loop"
867 );
868 continue; }
870 if primal_node_internal.is_free() {
872 primal_node_internal.temporary_match =
873 Some((MatchTarget::VirtualVertex(virtual_vertex_index), touching_ptr.downgrade()));
874 if is_mirror {
875 lock_write!(module, self);
876 module.possible_break.push(primal_node_internal.index);
877 }
878 interface_ptr.set_grow_state(
879 &primal_node_internal.origin.upgrade_force(),
880 DualNodeGrowState::Stay,
881 dual_module,
882 );
883 continue;
884 }
885 if primal_node_internal.tree_node.is_some() {
887 if is_mirror {
888 lock_write!(module, self);
889 module.possible_break.push(primal_node_internal.index);
890 }
891 drop(primal_node_internal);
892 self.augment_tree_given_virtual_vertex(
893 primal_node_internal_ptr,
894 virtual_vertex_index,
895 touching_ptr.downgrade(),
896 interface_ptr,
897 dual_module,
898 );
899 continue;
900 }
901 unreachable!()
902 }
903 MaxUpdateLength::BlossomNeedExpand(node_ptr) => {
904 if self.get_primal_node_internal_ptr_option(&node_ptr).is_none() {
905 continue;
906 } let primal_node_internal_ptr = self.get_primal_node_internal_ptr(&node_ptr);
910 let outer_primal_node_internal_ptr = self.get_outer_node(primal_node_internal_ptr.clone());
911 if outer_primal_node_internal_ptr != primal_node_internal_ptr {
912 debug_assert!(
914 current_conflict_index != 1,
915 "the first conflict cannot be ignored, otherwise may cause hidden infinite loop"
916 );
917 continue;
918 }
919 let primal_node_internal = primal_node_internal_ptr.read_recursive();
920 let grow_state = primal_node_internal.origin.upgrade_force().read_recursive().grow_state;
921 if grow_state != DualNodeGrowState::Shrink {
922 debug_assert!(
923 current_conflict_index != 1,
924 "the first conflict cannot be ignored, otherwise may cause hidden infinite loop"
925 );
926 continue; }
928 let (nodes_circle, touching_children) = {
930 let blossom = node_ptr.read_recursive();
931 match &blossom.class {
932 DualNodeClass::Blossom {
933 nodes_circle,
934 touching_children,
935 } => (nodes_circle.clone(), touching_children.clone()),
936 _ => unreachable!("the expanding node is not a blossom"),
937 }
938 };
939 debug_assert!(
940 primal_node_internal.tree_node.is_some(),
941 "expanding blossom must belong to an alternating tree"
942 );
943 let tree_node = primal_node_internal.tree_node.as_ref().unwrap();
944 debug_assert!(
945 tree_node.depth % 2 == 1,
946 "expanding blossom must a '-' node in an alternating tree"
947 );
948 let (parent_ptr, parent_touching_ptr, parent_touching_child_ptr) = {
949 let (parent_weak, parent_touching_child_ptr) = &tree_node.parent.as_ref().unwrap();
951 let parent_ptr = parent_weak.upgrade_force();
952 lock_write!(parent, parent_ptr);
953 let parent_tree_node = parent.tree_node.as_mut().unwrap();
954 let idx = parent_tree_node
955 .children
956 .iter()
957 .position(|ptr| ptr.0 == primal_node_internal_ptr.downgrade())
958 .expect("should find");
959 let parent_touching_ptr = parent_tree_node.children[idx].1.clone();
960 parent_tree_node.children.remove(idx);
961 parent_tree_node
962 .children
963 .retain(|ptr| ptr.0 != primal_node_internal_ptr.downgrade());
964 (
965 parent_ptr.clone(),
966 parent_touching_ptr,
967 parent_touching_child_ptr
968 .upgrade_force()
969 .get_secondary_ancestor_blossom()
970 .downgrade(),
971 )
972 };
973 let (child_ptr, child_touching_ptr, child_touching_child_ptr) = {
974 debug_assert!(tree_node.children.len() == 1, "a - node must have exactly ONE child");
976 let child_weak = &tree_node.children[0].0;
977 let child_touching_child_ptr = tree_node.children[0]
978 .1
979 .upgrade_force()
980 .get_secondary_ancestor_blossom()
981 .downgrade();
982 let child_ptr = child_weak.upgrade_force();
983 let child = child_ptr.read_recursive();
984 let child_tree_node = child.tree_node.as_ref().unwrap();
985 (
987 child_ptr.clone(),
988 child_tree_node.parent.as_ref().unwrap().1.clone(),
989 child_touching_child_ptr,
990 )
991 };
992 interface_ptr.expand_blossom(node_ptr, dual_module);
993 let parent_touching_index = nodes_circle
995 .iter()
996 .position(|ptr| ptr == &parent_touching_child_ptr)
997 .expect("touching node should be in the blossom circle");
998 let child_touching_index = nodes_circle
999 .iter()
1000 .position(|ptr| ptr == &child_touching_child_ptr)
1001 .expect("touching node should be in the blossom circle");
1002 let mut is_tree_sequence_ascending = true;
1003 let (match_sequence, tree_sequence) = {
1004 let mut match_sequence = Vec::new();
1006 let mut tree_sequence = Vec::new();
1007 match parent_touching_index.cmp(&child_touching_index) {
1008 Ordering::Equal => {
1009 tree_sequence.push(parent_touching_index);
1010 for i in parent_touching_index + 1..nodes_circle.len() {
1011 match_sequence.push(i);
1012 }
1013 for i in 0..parent_touching_index {
1014 match_sequence.push(i);
1015 }
1016 }
1017 Ordering::Greater => {
1018 if (parent_touching_index - child_touching_index) % 2 == 0 {
1019 for i in (child_touching_index..parent_touching_index + 1).rev() {
1021 tree_sequence.push(i);
1022 }
1023 is_tree_sequence_ascending = false;
1024 for i in parent_touching_index + 1..nodes_circle.len() {
1025 match_sequence.push(i);
1026 }
1027 for i in 0..child_touching_index {
1028 match_sequence.push(i);
1029 }
1030 } else {
1031 for i in parent_touching_index..nodes_circle.len() {
1033 tree_sequence.push(i);
1034 }
1035 for i in 0..child_touching_index + 1 {
1036 tree_sequence.push(i);
1037 }
1038 for i in child_touching_index + 1..parent_touching_index {
1039 match_sequence.push(i);
1040 }
1041 }
1042 }
1043 Ordering::Less => {
1044 if (child_touching_index - parent_touching_index) % 2 == 0 {
1045 for i in parent_touching_index..child_touching_index + 1 {
1047 tree_sequence.push(i);
1048 }
1049 for i in child_touching_index + 1..nodes_circle.len() {
1050 match_sequence.push(i);
1051 }
1052 for i in 0..parent_touching_index {
1053 match_sequence.push(i);
1054 }
1055 } else {
1056 for i in (0..parent_touching_index + 1).rev() {
1058 tree_sequence.push(i);
1059 }
1060 for i in (child_touching_index..nodes_circle.len()).rev() {
1061 tree_sequence.push(i);
1062 }
1063 is_tree_sequence_ascending = false;
1064 for i in parent_touching_index + 1..child_touching_index {
1065 match_sequence.push(i);
1066 }
1067 }
1068 }
1069 }
1070 (match_sequence, tree_sequence)
1071 };
1072 debug_assert!(
1073 match_sequence.len() % 2 == 0 && tree_sequence.len() % 2 == 1,
1074 "parity of sequence wrong"
1075 );
1076 for i in (0..match_sequence.len()).step_by(2) {
1078 let primal_node_internal_ptr_1 =
1079 self.get_primal_node_internal_ptr(&nodes_circle[match_sequence[i]].upgrade_force());
1080 let primal_node_internal_ptr_2 =
1081 self.get_primal_node_internal_ptr(&nodes_circle[match_sequence[i + 1]].upgrade_force());
1082 debug_assert!(
1083 (match_sequence[i] + 1) % nodes_circle.len() == match_sequence[i + 1],
1084 "match sequence should be ascending"
1085 );
1086 let touching_ptr_1 = touching_children[match_sequence[i]].1.clone(); let touching_ptr_2 = touching_children[match_sequence[i + 1]].0.clone(); let mut primal_node_internal_1 = primal_node_internal_ptr_1.write();
1089 let mut primal_node_internal_2 = primal_node_internal_ptr_2.write();
1090 primal_node_internal_1.temporary_match =
1091 Some((MatchTarget::Peer(primal_node_internal_ptr_2.downgrade()), touching_ptr_1));
1092 primal_node_internal_2.temporary_match =
1093 Some((MatchTarget::Peer(primal_node_internal_ptr_1.downgrade()), touching_ptr_2));
1094 interface_ptr.set_grow_state(
1095 &primal_node_internal_1.origin.upgrade_force(),
1096 DualNodeGrowState::Stay,
1097 dual_module,
1098 );
1099 interface_ptr.set_grow_state(
1100 &primal_node_internal_2.origin.upgrade_force(),
1101 DualNodeGrowState::Stay,
1102 dual_module,
1103 );
1104 }
1105 for (idx, current_i) in tree_sequence.iter().enumerate() {
1107 debug_assert!(
1108 {
1109 if idx + 1 < tree_sequence.len() {
1110 if is_tree_sequence_ascending {
1111 (tree_sequence[idx] + 1) % nodes_circle.len() == tree_sequence[idx + 1]
1112 } else {
1113 (tree_sequence[idx + 1] + 1) % nodes_circle.len() == tree_sequence[idx]
1114 }
1115 } else {
1116 true
1117 }
1118 },
1119 "tree sequence orientation must be consistent"
1120 );
1121 let current_parent_ptr = if idx == 0 {
1122 parent_ptr.clone()
1123 } else {
1124 self.get_primal_node_internal_ptr(&nodes_circle[tree_sequence[idx - 1]].upgrade_force())
1125 };
1126 let current_parent_touching_ptr = if idx == 0 {
1127 tree_node.parent.as_ref().unwrap().1.clone()
1128 } else {
1129 if is_tree_sequence_ascending {
1130 touching_children[*current_i].0.clone()
1131 } else {
1132 touching_children[*current_i].1.clone()
1133 }
1134 };
1135 let current_child_ptr = if idx == tree_sequence.len() - 1 {
1136 child_ptr.clone()
1137 } else {
1138 self.get_primal_node_internal_ptr(&nodes_circle[tree_sequence[idx + 1]].upgrade_force())
1139 };
1140 let current_child_touching_ptr = if idx == tree_sequence.len() - 1 {
1141 tree_node.children[0].1.clone()
1142 } else {
1143 if is_tree_sequence_ascending {
1144 touching_children[*current_i].1.clone()
1145 } else {
1146 touching_children[*current_i].0.clone()
1147 }
1148 };
1149 let current_ptr = self.get_primal_node_internal_ptr(&nodes_circle[*current_i].upgrade_force());
1150 let mut current = current_ptr.write();
1151 current.tree_node = Some(AlternatingTreeNode {
1152 root: tree_node.root.clone(),
1153 parent: Some((current_parent_ptr.downgrade(), current_parent_touching_ptr)),
1154 children: vec![(current_child_ptr.downgrade(), current_child_touching_ptr)],
1155 depth: tree_node.depth + idx,
1156 tree_size: None,
1157 });
1158 interface_ptr.set_grow_state(
1159 ¤t.origin.upgrade_force(),
1160 if idx % 2 == 0 {
1161 DualNodeGrowState::Shrink
1162 } else {
1163 DualNodeGrowState::Grow
1164 },
1165 dual_module,
1166 );
1167 }
1168 {
1169 lock_write!(parent, parent_ptr);
1171 let parent_tree_node = parent.tree_node.as_mut().unwrap();
1172 let child_ptr = self.get_primal_node_internal_ptr(&nodes_circle[tree_sequence[0]].upgrade_force());
1173 parent_tree_node.children.push((child_ptr.downgrade(), parent_touching_ptr));
1174 }
1175 {
1176 lock_write!(child, child_ptr);
1178 let child_tree_node = child.tree_node.as_mut().unwrap();
1179 let parent_ptr = self.get_primal_node_internal_ptr(
1180 &nodes_circle[tree_sequence[tree_sequence.len() - 1]].upgrade_force(),
1181 );
1182 child_tree_node.parent = Some((parent_ptr.downgrade(), child_touching_ptr));
1183 child.change_sub_tree_root(tree_node.depth + tree_sequence.len(), tree_node.root.upgrade_force());
1184 }
1185 {
1186 lock_write!(module, self);
1188 debug_assert_eq!(
1189 module.get_node(primal_node_internal.index),
1190 Some(primal_node_internal_ptr.clone()),
1191 "index wrong"
1192 );
1193 module.remove_node(primal_node_internal.index);
1194 }
1195 }
1196 MaxUpdateLength::VertexShrinkStop(_) => {
1197 if current_conflict_index == 1 {
1198 unreachable!("VertexShrinkStop conflict cannot be solved by primal module, and should be sorted to the last of the heap")
1200 }
1201 }
1203 _ => unreachable!("should not resolve these issues"),
1204 }
1205 }
1206 }
1207
1208 fn intermediate_matching<D: DualModuleImpl>(
1209 &mut self,
1210 _interface: &DualModuleInterfacePtr,
1211 _dual_module: &mut D,
1212 ) -> IntermediateMatching {
1213 let mut immediate_matching = IntermediateMatching::new();
1214 let mut flattened_nodes = vec![];
1215 self.flatten_nodes(&mut flattened_nodes);
1216 for primal_node_internal_ptr in flattened_nodes.iter().flatten() {
1217 let primal_node_internal = primal_node_internal_ptr.read_recursive();
1218 debug_assert!(
1219 primal_node_internal.tree_node.is_none(),
1220 "cannot compute perfect matching with active alternating tree"
1221 );
1222 let origin_ptr = primal_node_internal.origin.upgrade_force();
1223 let interface_node = origin_ptr.read_recursive();
1224 if interface_node.parent_blossom.is_some() {
1225 debug_assert_eq!(
1226 primal_node_internal.temporary_match, None,
1227 "blossom internal nodes should not be matched"
1228 );
1229 continue; }
1231 if let Some((match_target, match_touching_ptr)) = primal_node_internal.temporary_match.as_ref() {
1232 match match_target {
1233 MatchTarget::Peer(peer_internal_weak) => {
1234 let peer_internal_ptr = peer_internal_weak.upgrade_force();
1235 let peer_internal = peer_internal_ptr.read_recursive();
1236 if primal_node_internal.index < peer_internal.index {
1237 let peer_touching_ptr = peer_internal.temporary_match.as_ref().unwrap().1.clone();
1239 immediate_matching.peer_matchings.push((
1240 (primal_node_internal.origin.upgrade_force(), match_touching_ptr.clone()),
1241 (peer_internal.origin.upgrade_force(), peer_touching_ptr),
1242 ));
1243 }
1244 }
1245 MatchTarget::VirtualVertex(virtual_vertex) => {
1246 immediate_matching.virtual_matchings.push((
1247 (primal_node_internal.origin.upgrade_force(), match_touching_ptr.clone()),
1248 *virtual_vertex,
1249 ));
1250 }
1251 }
1252 } else {
1253 panic!(
1254 "cannot compute final matching with unmatched outer node {:?}",
1255 primal_node_internal_ptr
1256 );
1257 }
1258 }
1259 immediate_matching
1260 }
1261}
1262
1263impl FusionVisualizer for PrimalModuleSerialPtr {
1264 fn snapshot(&self, abbrev: bool) -> serde_json::Value {
1265 let flattened_nodes = self.sanity_check().unwrap();
1267 let mut primal_nodes = Vec::<serde_json::Value>::new();
1268 for primal_node_ptr in flattened_nodes.iter() {
1269 if let Some(primal_node_ptr) = &primal_node_ptr {
1270 let primal_node = primal_node_ptr.read_recursive();
1271 primal_nodes.push(json!({
1272 if abbrev { "m" } else { "temporary_match" }: primal_node.temporary_match.as_ref().map(|(match_target, touching_ptr)| {
1273 match match_target {
1274 MatchTarget::Peer(peer_weak) => {
1275 let peer_ptr = peer_weak.upgrade_force();
1276 json!({
1277 if abbrev { "p" } else { "peer" }: peer_ptr.read_recursive().index,
1278 if abbrev { "t" } else { "touching" }: touching_ptr.upgrade_force().read_recursive().index,
1279 })
1280 },
1281 MatchTarget::VirtualVertex(vertex_idx) => json!({
1282 if abbrev { "v" } else { "virtual_vertex" }: vertex_idx,
1283 if abbrev { "t" } else { "touching" }: touching_ptr.upgrade_force().read_recursive().index,
1284 }),
1285 }
1286 }),
1287 if abbrev { "t" } else { "tree_node" }: primal_node.tree_node.as_ref().map(|tree_node| {
1288 json!({
1289 if abbrev { "r" } else { "root" }: tree_node.root.upgrade_force().read_recursive().index,
1290 if abbrev { "p" } else { "parent" }: tree_node.parent.as_ref().map(|(weak, _)| weak.upgrade_force().read_recursive().index),
1291 if abbrev { "pt" } else { "parent_touching" }: tree_node.parent.as_ref().map(|(_, weak)| weak.upgrade_force().read_recursive().index),
1292 if abbrev { "c" } else { "children" }: tree_node.children.iter().map(|(weak, _)| weak.upgrade_force().read_recursive().index).collect::<Vec<NodeIndex>>(),
1293 if abbrev { "ct" } else { "children_touching" }: tree_node.children.iter().map(|(_, weak)| weak.upgrade_force().read_recursive().index).collect::<Vec<NodeIndex>>(),
1294 if abbrev { "d" } else { "depth" }: tree_node.depth,
1295 })
1296 }),
1297 }));
1298 } else {
1299 primal_nodes.push(json!(null));
1300 }
1301 }
1302 json!({
1303 "primal_nodes": primal_nodes,
1304 })
1305 }
1306}
1307
1308impl PrimalModuleSerial {
1309 pub fn nodes_count(&self) -> NodeNum {
1311 let mut count = self.nodes_length as NodeNum;
1312 if let Some(((_, left_count), (_, right_count))) = &self.children {
1313 count += left_count + right_count;
1314 }
1315 count
1316 }
1317
1318 #[allow(clippy::unnecessary_cast)]
1320 pub fn get_node(&self, relative_node_index: NodeIndex) -> Option<PrimalNodeInternalPtr> {
1321 debug_assert!(relative_node_index < self.nodes_count(), "cannot find node in this module");
1322 let mut bias = 0;
1323 if let Some(((left_weak, left_count), (right_weak, right_count))) = &self.children {
1324 if relative_node_index < *left_count {
1325 return left_weak.upgrade_force().read_recursive().get_node(relative_node_index);
1327 } else if relative_node_index < *left_count + *right_count {
1328 return right_weak
1330 .upgrade_force()
1331 .read_recursive()
1332 .get_node(relative_node_index - *left_count);
1333 }
1334 bias = left_count + right_count;
1335 }
1336 self.nodes[(relative_node_index - bias) as usize].clone()
1337 }
1338
1339 #[allow(clippy::unnecessary_cast)]
1341 pub fn remove_node(&mut self, relative_node_index: NodeIndex) {
1342 debug_assert!(relative_node_index < self.nodes_count(), "cannot find node in this module");
1343 let mut bias = 0;
1344 if let Some(((left_weak, left_count), (right_weak, right_count))) = &self.children {
1345 if relative_node_index < *left_count {
1346 left_weak.upgrade_force().write().remove_node(relative_node_index);
1348 return;
1349 } else if relative_node_index < *left_count + *right_count {
1350 right_weak
1352 .upgrade_force()
1353 .write()
1354 .remove_node(relative_node_index - *left_count);
1355 return;
1356 }
1357 bias = left_count + right_count;
1358 }
1359 self.nodes[(relative_node_index - bias) as usize] = None;
1360 }
1361}
1362
1363impl PrimalModuleSerialPtr {
1364 pub fn get_primal_node_internal_ptr_option(&self, dual_node_ptr: &DualNodePtr) -> Option<PrimalNodeInternalPtr> {
1365 let module = self.read_recursive();
1366 let dual_node = dual_node_ptr.read_recursive();
1367 let primal_node_internal_ptr = module.get_node(dual_node.index);
1368 if let Some(primal_node_internal_ptr) = &primal_node_internal_ptr {
1369 if module.is_fusion {
1370 primal_node_internal_ptr.update(); }
1372 debug_assert!(
1373 dual_node_ptr == &primal_node_internal_ptr.read_recursive().origin.upgrade_force(),
1374 "dual node and primal internal node must corresponds to each other"
1375 );
1376 }
1377 primal_node_internal_ptr
1378 }
1379
1380 pub fn get_primal_node_internal_ptr(&self, dual_node_ptr: &DualNodePtr) -> PrimalNodeInternalPtr {
1381 self.get_primal_node_internal_ptr_option(dual_node_ptr)
1382 .expect("internal primal node must exists")
1383 }
1384
1385 pub fn get_outer_node(&self, primal_node_internal_ptr: PrimalNodeInternalPtr) -> PrimalNodeInternalPtr {
1387 let node = primal_node_internal_ptr.read_recursive();
1388 let origin_ptr = node.origin.upgrade_force();
1389 let interface_node = origin_ptr.read_recursive();
1390 if let Some(parent_dual_node_weak) = &interface_node.parent_blossom {
1391 let parent_dual_node_ptr = parent_dual_node_weak.upgrade_force();
1392 let parent_primal_node_internal_ptr = self.get_primal_node_internal_ptr(&parent_dual_node_ptr);
1393 self.get_outer_node(parent_primal_node_internal_ptr)
1394 } else {
1395 primal_node_internal_ptr.clone()
1396 }
1397 }
1398
1399 pub fn find_lowest_common_ancestor(
1401 &self,
1402 mut primal_node_internal_ptr_1: PrimalNodeInternalPtr,
1403 mut primal_node_internal_ptr_2: PrimalNodeInternalPtr,
1404 ) -> (PrimalNodeInternalPtr, Vec<PrimalNodeInternalPtr>, Vec<PrimalNodeInternalPtr>) {
1405 let (depth_1, depth_2) = {
1406 let primal_node_internal_1 = primal_node_internal_ptr_1.read_recursive();
1407 let primal_node_internal_2 = primal_node_internal_ptr_2.read_recursive();
1408 let tree_node_1 = primal_node_internal_1.tree_node.as_ref().unwrap();
1409 let tree_node_2 = primal_node_internal_2.tree_node.as_ref().unwrap();
1410 debug_assert_eq!(tree_node_1.root, tree_node_2.root, "must belong to the same tree");
1411 (tree_node_1.depth, tree_node_2.depth)
1412 };
1413 let mut path_1 = vec![];
1414 let mut path_2 = vec![];
1415 match depth_1.cmp(&depth_2) {
1416 Ordering::Greater => loop {
1417 let ptr = primal_node_internal_ptr_1.clone();
1418 let primal_node_internal = ptr.read_recursive();
1419 let tree_node = primal_node_internal.tree_node.as_ref().unwrap();
1420 if tree_node.depth == depth_2 {
1421 break;
1422 }
1423 path_1.push(primal_node_internal_ptr_1.clone());
1424 primal_node_internal_ptr_1 = tree_node.parent.as_ref().unwrap().0.upgrade_force();
1425 },
1426 Ordering::Less => loop {
1427 let ptr = primal_node_internal_ptr_2.clone();
1428 let primal_node_internal = ptr.read_recursive();
1429 let tree_node = primal_node_internal.tree_node.as_ref().unwrap();
1430 if tree_node.depth == depth_1 {
1431 break;
1432 }
1433 path_2.push(primal_node_internal_ptr_2.clone());
1434 primal_node_internal_ptr_2 = tree_node.parent.as_ref().unwrap().0.upgrade_force();
1435 },
1436 Ordering::Equal => {}
1437 }
1438 loop {
1440 if primal_node_internal_ptr_1 == primal_node_internal_ptr_2 {
1441 return (primal_node_internal_ptr_1, path_1, path_2);
1442 }
1443 let ptr_1 = primal_node_internal_ptr_1.clone();
1444 let ptr_2 = primal_node_internal_ptr_2.clone();
1445 let primal_node_internal_1 = ptr_1.read_recursive();
1446 let primal_node_internal_2 = ptr_2.read_recursive();
1447 let tree_node_1 = primal_node_internal_1.tree_node.as_ref().unwrap();
1448 let tree_node_2 = primal_node_internal_2.tree_node.as_ref().unwrap();
1449 path_1.push(primal_node_internal_ptr_1.clone());
1450 path_2.push(primal_node_internal_ptr_2.clone());
1451 primal_node_internal_ptr_1 = tree_node_1.parent.as_ref().unwrap().0.upgrade_force();
1452 primal_node_internal_ptr_2 = tree_node_2.parent.as_ref().unwrap().0.upgrade_force();
1453 }
1454 }
1455
1456 pub fn match_subtree<D: DualModuleImpl>(
1458 tree_node_internal_ptr: PrimalNodeInternalPtr,
1459 interface_ptr: &DualModuleInterfacePtr,
1460 dual_module: &mut D,
1461 ) {
1462 let mut tree_node_internal = tree_node_internal_ptr.write();
1463 let tree_node = tree_node_internal.tree_node.as_ref().unwrap();
1464 debug_assert!(tree_node.depth % 2 == 1, "only match - node is possible");
1465 let child_node_internal_ptr = tree_node.children[0].0.upgrade_force();
1466 tree_node_internal.temporary_match = Some((
1467 MatchTarget::Peer(child_node_internal_ptr.downgrade()),
1468 tree_node.children[0].1.clone(),
1469 ));
1470 interface_ptr.set_grow_state(
1471 &tree_node_internal.origin.upgrade_force(),
1472 DualNodeGrowState::Stay,
1473 dual_module,
1474 );
1475 tree_node_internal.tree_node = None;
1476 let mut child_node_internal = child_node_internal_ptr.write();
1477 let child_touching_ptr = child_node_internal
1478 .tree_node
1479 .as_ref()
1480 .unwrap()
1481 .parent
1482 .as_ref()
1483 .unwrap()
1484 .1
1485 .clone();
1486 child_node_internal.temporary_match =
1487 Some((MatchTarget::Peer(tree_node_internal_ptr.downgrade()), child_touching_ptr));
1488 let child_tree_node = child_node_internal.tree_node.as_ref().unwrap();
1489 interface_ptr.set_grow_state(
1490 &child_node_internal.origin.upgrade_force(),
1491 DualNodeGrowState::Stay,
1492 dual_module,
1493 );
1494 for (grandson_ptr, _) in child_tree_node.children.iter() {
1495 Self::match_subtree(grandson_ptr.upgrade_force(), interface_ptr, dual_module);
1496 }
1497 child_node_internal.tree_node = None;
1498 }
1499
1500 pub fn augment_tree_given_matched<D: DualModuleImpl>(
1503 tree_node_internal_ptr: PrimalNodeInternalPtr,
1504 match_node_internal_ptr: PrimalNodeInternalPtr,
1505 tree_touching_ptr: DualNodeWeak,
1506 interface_ptr: &DualModuleInterfacePtr,
1507 dual_module: &mut D,
1508 ) {
1509 let mut tree_node_internal = tree_node_internal_ptr.write();
1510 tree_node_internal.temporary_match =
1511 Some((MatchTarget::Peer(match_node_internal_ptr.downgrade()), tree_touching_ptr));
1512 interface_ptr.set_grow_state(
1513 &tree_node_internal.origin.upgrade_force(),
1514 DualNodeGrowState::Stay,
1515 dual_module,
1516 );
1517 let tree_node = tree_node_internal.tree_node.as_ref().unwrap();
1518 debug_assert!(tree_node.depth % 2 == 0, "only augment + node is possible");
1519 for (child_ptr, _) in tree_node.children.iter() {
1520 if child_ptr != &match_node_internal_ptr.downgrade() {
1521 Self::match_subtree(child_ptr.upgrade_force(), interface_ptr, dual_module);
1522 }
1523 }
1524 if tree_node.depth != 0 {
1525 let parent_node_internal_weak = tree_node.parent.as_ref().unwrap().0.clone();
1527 let parent_node_internal_ptr = parent_node_internal_weak.upgrade_force();
1528 let grandparent_node_internal_ptr = {
1529 let mut parent_node_internal = parent_node_internal_ptr.write();
1531 let parent_tree_node = parent_node_internal.tree_node.as_ref().unwrap();
1532 let grandparent_node_internal_weak = parent_tree_node.parent.as_ref().unwrap().0.clone();
1533 parent_node_internal.temporary_match = Some((
1534 MatchTarget::Peer(grandparent_node_internal_weak.clone()),
1535 parent_tree_node.parent.as_ref().unwrap().1.clone(),
1536 ));
1537 parent_node_internal.tree_node = None;
1538 interface_ptr.set_grow_state(
1539 &parent_node_internal.origin.upgrade_force(),
1540 DualNodeGrowState::Stay,
1541 dual_module,
1542 );
1543 grandparent_node_internal_weak.upgrade_force()
1544 };
1545 let grandparent_touching_ptr = {
1546 let grandparent_node_internal = grandparent_node_internal_ptr.read_recursive();
1547 let grandparent_tree_node = grandparent_node_internal.tree_node.as_ref().unwrap();
1548 let idx = grandparent_tree_node
1549 .children
1550 .iter()
1551 .position(|(ptr, _)| ptr == &parent_node_internal_weak)
1552 .expect("should find child");
1553 grandparent_tree_node.children[idx].1.clone()
1554 };
1555 Self::augment_tree_given_matched(
1556 grandparent_node_internal_ptr,
1557 parent_node_internal_ptr,
1558 grandparent_touching_ptr,
1559 interface_ptr,
1560 dual_module,
1561 );
1562 }
1563 tree_node_internal.tree_node = None;
1564 }
1565
1566 pub fn augment_tree_given_virtual_vertex<D: DualModuleImpl>(
1568 &self,
1569 tree_node_internal_ptr: PrimalNodeInternalPtr,
1570 virtual_vertex_index: VertexIndex,
1571 tree_touching_ptr: DualNodeWeak,
1572 interface_ptr: &DualModuleInterfacePtr,
1573 dual_module: &mut D,
1574 ) {
1575 let mut tree_node_internal = tree_node_internal_ptr.write();
1576 tree_node_internal.temporary_match = Some((MatchTarget::VirtualVertex(virtual_vertex_index), tree_touching_ptr));
1577 interface_ptr.set_grow_state(
1578 &tree_node_internal.origin.upgrade_force(),
1579 DualNodeGrowState::Stay,
1580 dual_module,
1581 );
1582 let tree_node = tree_node_internal.tree_node.as_ref().unwrap();
1583 debug_assert!(tree_node.depth % 2 == 0, "only augment + node is possible");
1584 for (child_ptr, _) in tree_node.children.iter() {
1585 Self::match_subtree(child_ptr.upgrade_force(), interface_ptr, dual_module);
1586 }
1587 if tree_node.depth != 0 {
1588 let parent_node_internal_weak = tree_node.parent.as_ref().unwrap().0.clone();
1590 let parent_node_internal_ptr = parent_node_internal_weak.upgrade_force();
1591 let grandparent_node_internal_ptr = {
1592 let mut parent_node_internal = parent_node_internal_ptr.write();
1594 let parent_tree_node = parent_node_internal.tree_node.as_ref().unwrap();
1595 let grandparent_node_internal_weak = parent_tree_node.parent.as_ref().unwrap().0.clone();
1596 parent_node_internal.temporary_match = Some((
1597 MatchTarget::Peer(grandparent_node_internal_weak.clone()),
1598 parent_tree_node.parent.as_ref().unwrap().1.clone(),
1599 ));
1600 parent_node_internal.tree_node = None;
1601 interface_ptr.set_grow_state(
1602 &parent_node_internal.origin.upgrade_force(),
1603 DualNodeGrowState::Stay,
1604 dual_module,
1605 );
1606 grandparent_node_internal_weak.upgrade_force()
1607 };
1608 let grandparent_touching_ptr = {
1609 let grandparent_node_internal = grandparent_node_internal_ptr.read_recursive();
1610 let grandparent_tree_node = grandparent_node_internal.tree_node.as_ref().unwrap();
1611 let idx = grandparent_tree_node
1612 .children
1613 .iter()
1614 .position(|(ptr, _)| ptr == &parent_node_internal_weak)
1615 .expect("should find child");
1616 grandparent_tree_node.children[idx].1.clone()
1617 };
1618 Self::augment_tree_given_matched(
1619 grandparent_node_internal_ptr,
1620 parent_node_internal_ptr,
1621 grandparent_touching_ptr,
1622 interface_ptr,
1623 dual_module,
1624 );
1625 }
1626 tree_node_internal.tree_node = None;
1627 }
1628
1629 #[allow(clippy::unnecessary_cast)]
1631 pub fn flatten_nodes(&self, flattened_nodes: &mut Vec<Option<PrimalNodeInternalPtr>>) {
1632 let module = self.read_recursive();
1633 let flattened_nodes_length = flattened_nodes.len();
1634 if let Some(((left_child_weak, _), (right_child_weak, _))) = &module.children {
1636 left_child_weak.upgrade_force().flatten_nodes(flattened_nodes);
1637 right_child_weak.upgrade_force().flatten_nodes(flattened_nodes);
1638 }
1639 for node_index in 0..module.nodes_length {
1640 let primal_node_internal_ptr = &module.nodes[node_index];
1641 if let Some(primal_node_internal_ptr) = primal_node_internal_ptr {
1642 primal_node_internal_ptr.update();
1643 primal_node_internal_ptr.read_recursive().origin.upgrade_force().update();
1644 }
1645 flattened_nodes.push(primal_node_internal_ptr.clone());
1646 }
1647 debug_assert_eq!(flattened_nodes.len() - flattened_nodes_length, module.nodes_count() as usize);
1648 }
1649
1650 #[allow(clippy::unnecessary_cast)]
1652 pub fn slow_fuse(&self, left: &Self, right: &Self) {
1653 let mut module = self.write();
1654 module.is_fusion = true; for other in [left, right] {
1656 let mut other_module = other.write();
1657 other_module.is_fusion = true; let bias = module.nodes_length as NodeIndex;
1659 for other_node_index in 0..other_module.nodes_length as NodeIndex {
1660 let node_ptr = &other_module.nodes[other_node_index as usize];
1661 if let Some(node_ptr) = node_ptr {
1662 let mut node = node_ptr.write();
1663 debug_assert_eq!(node.index, other_node_index);
1664 node.index += bias;
1665 }
1666 module.nodes_length += 1;
1667 if module.nodes.len() < module.nodes_length {
1668 module.nodes.push(None);
1669 }
1670 module.nodes[(bias + other_node_index) as usize] = node_ptr.clone();
1671 }
1672 for node_index in other_module.possible_break.iter() {
1674 module.possible_break.push(*node_index + bias);
1675 }
1676 }
1677 }
1678
1679 pub fn fuse(&self, left: &Self, right: &Self) {
1681 let parent_weak = self.downgrade();
1682 let left_weak = left.downgrade();
1683 let right_weak = right.downgrade();
1684 let mut module = self.write();
1685 module.is_fusion = true; debug_assert_eq!(module.nodes_length, 0, "fast fuse doesn't support non-empty fuse");
1687 debug_assert!(module.children.is_none(), "cannot fuse twice");
1688 let mut left_module = left.write();
1689 let mut right_module = right.write();
1690 debug_assert!(left_module.parent.is_none(), "cannot fuse an module twice");
1691 debug_assert!(right_module.parent.is_none(), "cannot fuse an module twice");
1692 left_module.parent = Some(parent_weak.clone());
1693 right_module.parent = Some(parent_weak);
1694 left_module.index_bias = 0;
1695 right_module.index_bias = left_module.nodes_count();
1696 module.children = Some((
1697 (left_weak, left_module.nodes_count()),
1698 (right_weak, right_module.nodes_count()),
1699 ));
1700 for other_module in [left_module, right_module] {
1702 for node_index in other_module.possible_break.iter() {
1703 module.possible_break.push(*node_index + other_module.index_bias);
1704 }
1705 }
1706 }
1707
1708 #[allow(clippy::collapsible_else_if)]
1710 pub fn sanity_check(&self) -> Result<Vec<Option<PrimalNodeInternalPtr>>, String> {
1711 let mut flattened_nodes = vec![];
1712 self.flatten_nodes(&mut flattened_nodes);
1713 for (index, primal_module_internal_ptr) in flattened_nodes.iter().enumerate() {
1714 if let Some(primal_module_internal_ptr) = primal_module_internal_ptr {
1715 let primal_module_internal = primal_module_internal_ptr.read_recursive();
1716 if primal_module_internal.index != index as NodeIndex {
1717 return Err(format!(
1718 "primal node index wrong: expected {}, actual {}",
1719 index, primal_module_internal.index
1720 ));
1721 }
1722 let origin_ptr = primal_module_internal.origin.upgrade_force();
1723 let origin_node = origin_ptr.read_recursive();
1724 if origin_node.index != primal_module_internal.index {
1725 return Err(format!(
1726 "origin index wrong: expected {}, actual {}",
1727 index, origin_node.index
1728 ));
1729 }
1730 if primal_module_internal.temporary_match.is_some() && primal_module_internal.tree_node.is_some() {
1731 return Err(format!("{} temporary match and tree node cannot both exists", index));
1732 }
1733 if origin_node.parent_blossom.is_some() {
1734 if primal_module_internal.tree_node.is_some() {
1735 return Err(format!("blossom internal node {index} is still in a tree"));
1736 }
1737 if primal_module_internal.temporary_match.is_some() {
1738 return Err(format!("blossom internal node {index} is still matched"));
1739 }
1740 }
1741 if let Some((match_target, _)) = primal_module_internal.temporary_match.as_ref() {
1742 if origin_node.grow_state != DualNodeGrowState::Stay {
1743 return Err(format!("matched node {index} is not set to Stay"));
1744 }
1745 match match_target {
1746 MatchTarget::Peer(peer_weak) => {
1747 let peer_ptr = peer_weak.upgrade_force();
1748 let peer = peer_ptr.read_recursive();
1749 if let Some((peer_match_target, _)) = peer.temporary_match.as_ref() {
1750 if peer_match_target != &MatchTarget::Peer(primal_module_internal_ptr.downgrade()) {
1751 return Err(format!(
1752 "match peer {} is not matched with {}, instead it's {:?}",
1753 peer.index, index, peer_match_target
1754 ));
1755 }
1756 } else {
1757 return Err("match peer is not marked as matched".to_string());
1758 }
1759 }
1760 MatchTarget::VirtualVertex(_vertex_idx) => {} }
1762 }
1763 if let Some(tree_node) = primal_module_internal.tree_node.as_ref() {
1764 for (child_weak, _) in tree_node.children.iter() {
1766 let child_ptr = child_weak.upgrade_force();
1767 let child = child_ptr.read_recursive();
1768 if let Some(child_tree_node) = child.tree_node.as_ref() {
1769 if child_tree_node.parent.as_ref().map(|x| &x.0) != Some(&primal_module_internal_ptr.downgrade())
1770 {
1771 return Err(format!(
1772 "{}'s child {} has a different parent, link broken",
1773 index, child.index
1774 ));
1775 }
1776 } else {
1777 return Err(format!(
1778 "{}'s child {} doesn't belong to any tree, link broken",
1779 index, child.index
1780 ));
1781 }
1782 let module = self.read_recursive();
1784 if child.index >= module.nodes_count() || module.get_node(child.index).is_none() {
1785 return Err(format!("child's index {} is not in the interface", child.index));
1786 }
1787 let tracked_child_ptr = module.get_node(child.index).unwrap();
1788 if tracked_child_ptr != child_ptr {
1789 return Err(format!(
1790 "the tracked ptr of child {} is not what's being pointed",
1791 child.index
1792 ));
1793 }
1794 }
1795 if let Some((parent_weak, _)) = tree_node.parent.as_ref() {
1797 let parent_ptr = parent_weak.upgrade_force();
1798 let parent = parent_ptr.read_recursive();
1799 if let Some(parent_tree_node) = parent.tree_node.as_ref() {
1800 let mut found_match_count = 0;
1801 for (node_ptr, _) in parent_tree_node.children.iter() {
1802 if node_ptr == &primal_module_internal_ptr.downgrade() {
1803 found_match_count += 1;
1804 }
1805 }
1806 if found_match_count != 1 {
1807 return Err(format!(
1808 "{} is the parent of {} but the child only presents {} times",
1809 parent.index, index, found_match_count
1810 ));
1811 }
1812 } else {
1813 return Err(format!(
1814 "{}'s parent {} doesn't belong to any tree, link broken",
1815 index, parent.index
1816 ));
1817 }
1818 let module = self.read_recursive();
1820 if parent.index >= module.nodes_count() || module.get_node(parent.index).is_none() {
1821 return Err(format!("parent's index {} is not in the interface", parent.index));
1822 }
1823 let tracked_parent_ptr = module.get_node(parent.index).unwrap();
1824 if tracked_parent_ptr != parent_ptr {
1825 return Err(format!(
1826 "the tracked ptr of child {} is not what's being pointed",
1827 parent.index
1828 ));
1829 }
1830 } else {
1831 if tree_node.root != primal_module_internal_ptr.downgrade() {
1832 return Err(format!("{} is not the root of the tree, yet it has no parent", index));
1833 }
1834 }
1835 let mut current_ptr = primal_module_internal_ptr.clone();
1837 let mut current_up = 0;
1838 loop {
1839 let current = current_ptr.read_recursive();
1840 let module = self.read_recursive();
1842 if current.index >= module.nodes_count() || module.get_node(current.index).is_none() {
1843 return Err(format!("current's index {} is not in the interface", current.index));
1844 }
1845 let tracked_current_ptr = module.get_node(current.index).unwrap();
1846 if tracked_current_ptr != current_ptr {
1847 return Err(format!(
1848 "the tracked ptr of current {} is not what's being pointed",
1849 current.index
1850 ));
1851 }
1852 if let Some(current_tree_node) = current.tree_node.as_ref() {
1854 if let Some((current_parent_ptr, _)) = current_tree_node.parent.as_ref() {
1855 let current_parent_ptr = current_parent_ptr.clone();
1856 drop(current);
1857 current_ptr = current_parent_ptr.upgrade_force();
1858 current_up += 1;
1859 } else {
1860 if current_tree_node.root != current_ptr.downgrade() {
1862 return Err(format!(
1863 "current {} is not the root of the tree, yet it has no parent",
1864 current.index
1865 ));
1866 }
1867 break;
1868 }
1869 } else {
1870 return Err(format!(
1871 "climbing up from {} to {} but it doesn't belong to a tree anymore",
1872 index, current.index
1873 ));
1874 }
1875 }
1876 if current_up != tree_node.depth {
1877 return Err(format!(
1878 "{} is marked with depth {} but the real depth is {}",
1879 index, tree_node.depth, current_up
1880 ));
1881 }
1882 if current_ptr.downgrade() != tree_node.root {
1883 return Err(format!(
1884 "{} is marked with root {:?} but the real root is {:?}",
1885 index, tree_node.root, current_ptr
1886 ));
1887 }
1888 }
1889 }
1890 }
1891 Ok(flattened_nodes)
1892 }
1893
1894 pub fn collapse_tree<D: DualModuleImpl>(
1896 &self,
1897 primal_node_internal_ptr: PrimalNodeInternalPtr,
1898 interface_ptr: &DualModuleInterfacePtr,
1899 dual_module: &mut D,
1900 ) {
1901 let mut children = vec![];
1902 primal_node_internal_ptr.flatten_tree(&mut children);
1903 let nodes_circle: Vec<_> = children
1904 .iter()
1905 .map(|ptr| ptr.read_recursive().origin.clone().upgrade_force())
1906 .collect();
1907 let touching_children: Vec<_> = children
1909 .iter()
1910 .map(|ptr| {
1911 let node = ptr.read_recursive();
1912 let tree_node = node.tree_node.as_ref().unwrap();
1913 let touching = if let Some((_, touching)) = tree_node.parent.as_ref() {
1914 touching.clone()
1915 } else {
1916 tree_node.children[0].1.clone()
1917 };
1918 (touching.clone(), touching) })
1920 .collect();
1921 let blossom_node_ptr = interface_ptr.create_blossom(nodes_circle, touching_children, dual_module);
1922 {
1924 let belonging = self.downgrade();
1926 let mut module = self.write();
1927 let local_node_index = module.nodes_length;
1928 let node_index = module.nodes_count();
1929 let primal_node_internal_blossom_ptr =
1930 if !module.is_fusion && local_node_index < module.nodes.len() && module.nodes[local_node_index].is_some() {
1931 let node_ptr = module.nodes[local_node_index].take().unwrap();
1932 let mut node = node_ptr.write();
1933 node.origin = blossom_node_ptr.downgrade();
1934 node.index = node_index;
1935 node.tree_node = None;
1936 node.temporary_match = None;
1937 node.belonging = belonging;
1938 drop(node);
1939 node_ptr
1940 } else {
1941 PrimalNodeInternalPtr::new_value(PrimalNodeInternal {
1942 origin: blossom_node_ptr.downgrade(),
1943 index: node_index,
1944 tree_node: None,
1945 temporary_match: None,
1946 belonging,
1947 })
1948 };
1949 module.nodes_length += 1;
1950 if module.nodes.len() < module.nodes_length {
1951 module.nodes.push(None);
1952 }
1953 module.nodes[local_node_index] = Some(primal_node_internal_blossom_ptr.clone());
1954 };
1955 for ptr in children.iter() {
1957 let mut node = ptr.write();
1958 node.tree_node = None;
1959 }
1960 }
1961}
1962
1963impl PrimalNodeInternalPtr {
1964 pub fn flatten_tree(&self, flattened_nodes: &mut Vec<PrimalNodeInternalPtr>) {
1966 flattened_nodes.push(self.clone());
1967 let node = self.read_recursive();
1968 let tree_node = node.tree_node.as_ref().unwrap();
1969 for (child_weak, _) in tree_node.children.iter() {
1970 let child_ptr = child_weak.upgrade_force();
1971 child_ptr.flatten_tree(flattened_nodes);
1972 }
1973 }
1974}
1975
1976#[cfg(test)]
1977pub mod tests {
1978 use super::super::dual_module_serial::*;
1979 use super::super::example_codes::*;
1980 #[cfg(feature = "blossom_v")]
1981 use super::super::*;
1982 use super::*;
1983
1984 pub fn primal_module_serial_basic_standard_syndrome_optional_viz(
1985 d: VertexNum,
1986 visualize_filename: Option<String>,
1987 defect_vertices: Vec<VertexIndex>,
1988 final_dual: Weight,
1989 ) -> (DualModuleInterfacePtr, PrimalModuleSerialPtr, DualModuleSerial) {
1990 primal_module_serial_basic_standard_syndrome_optional_viz_max_tree_size(
1991 d,
1992 visualize_filename,
1993 defect_vertices,
1994 final_dual,
1995 usize::MAX,
1996 )
1997 }
1998
1999 pub fn primal_module_serial_basic_standard_syndrome_optional_viz_max_tree_size(
2000 d: VertexNum,
2001 visualize_filename: Option<String>,
2002 defect_vertices: Vec<VertexIndex>,
2003 final_dual: Weight,
2004 max_tree_size: usize,
2005 ) -> (DualModuleInterfacePtr, PrimalModuleSerialPtr, DualModuleSerial) {
2006 println!("{defect_vertices:?}");
2007 let half_weight = 500;
2008 let mut code = CodeCapacityPlanarCode::new(d, 0.1, half_weight);
2009 let mut visualizer = match visualize_filename.as_ref() {
2010 Some(visualize_filename) => {
2011 let visualizer = Visualizer::new(
2012 Some(visualize_data_folder() + visualize_filename.as_str()),
2013 code.get_positions(),
2014 true,
2015 )
2016 .unwrap();
2017 print_visualize_link(visualize_filename.clone());
2018 Some(visualizer)
2019 }
2020 None => None,
2021 };
2022 let initializer = code.get_initializer();
2024 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2025 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2027 primal_module.write().debug_resolve_only_one = true; primal_module.write().max_tree_size = max_tree_size;
2030 code.set_defect_vertices(&defect_vertices);
2031 let interface_ptr = DualModuleInterfacePtr::new_empty();
2032 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, visualizer.as_mut());
2033 let perfect_matching = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2034 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2035 subgraph_builder.load_perfect_matching(&perfect_matching);
2036 let subgraph = subgraph_builder.get_subgraph();
2037 if let Some(visualizer) = visualizer.as_mut() {
2038 visualizer
2039 .snapshot_combined(
2040 "perfect matching and subgraph".to_string(),
2041 vec![
2042 &interface_ptr,
2043 &dual_module,
2044 &perfect_matching,
2045 &VisualizeSubgraph::new(&subgraph),
2046 ],
2047 )
2048 .unwrap();
2049 }
2050 assert_eq!(
2051 interface_ptr.sum_dual_variables(),
2052 subgraph_builder.total_weight(),
2053 "unmatched sum dual variables"
2054 );
2055 assert_eq!(
2056 interface_ptr.sum_dual_variables(),
2057 final_dual * 2 * half_weight,
2058 "unexpected final dual variable sum"
2059 );
2060 (interface_ptr, primal_module, dual_module)
2061 }
2062
2063 pub fn primal_module_serial_basic_standard_syndrome(
2064 d: VertexNum,
2065 visualize_filename: String,
2066 defect_vertices: Vec<VertexIndex>,
2067 final_dual: Weight,
2068 ) -> (DualModuleInterfacePtr, PrimalModuleSerialPtr, DualModuleSerial) {
2069 primal_module_serial_basic_standard_syndrome_optional_viz(d, Some(visualize_filename), defect_vertices, final_dual)
2070 }
2071
2072 #[test]
2074 fn primal_module_serial_basic_1() {
2075 let visualize_filename = "primal_module_serial_basic_1.json".to_string();
2077 let defect_vertices = vec![18, 26, 34];
2078 primal_module_serial_basic_standard_syndrome(7, visualize_filename, defect_vertices, 4);
2079 }
2080
2081 #[test]
2083 fn primal_module_serial_basic_2() {
2084 let visualize_filename = "primal_module_serial_basic_2.json".to_string();
2086 let defect_vertices = vec![16];
2087 primal_module_serial_basic_standard_syndrome(7, visualize_filename, defect_vertices, 1);
2088 }
2089
2090 #[test]
2092 fn primal_module_serial_basic_3() {
2093 let visualize_filename = "primal_module_serial_basic_3.json".to_string();
2095 let defect_vertices = vec![16, 26];
2096 primal_module_serial_basic_standard_syndrome(7, visualize_filename, defect_vertices, 3);
2097 }
2098
2099 #[test]
2101 fn primal_module_serial_basic_4() {
2102 let visualize_filename = "primal_module_serial_basic_4.json".to_string();
2104 let defect_vertices = vec![16, 52, 65, 76, 112];
2105 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 10);
2106 }
2107
2108 #[test]
2110 fn primal_module_serial_basic_5() {
2111 let visualize_filename = "primal_module_serial_basic_5.json".to_string();
2113 let defect_vertices = vec![39, 51, 61, 62, 63, 64, 65, 75, 87, 67];
2114 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 6);
2115 }
2116
2117 #[test]
2119 fn primal_module_serial_basic_6() {
2120 let visualize_filename = "primal_module_serial_basic_6.json".to_string();
2122 let defect_vertices = vec![39, 51, 61, 62, 63, 64, 65, 75, 87];
2123 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 6);
2124 }
2125
2126 #[test]
2128 fn primal_module_serial_basic_7() {
2129 let visualize_filename = "primal_module_serial_basic_7.json".to_string();
2131 let defect_vertices = vec![37, 61, 63, 66, 68, 44];
2132 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 7);
2133 }
2134
2135 #[test]
2137 fn primal_module_serial_basic_8() {
2138 let visualize_filename = "primal_module_serial_basic_8.json".to_string();
2140 let defect_vertices = vec![61, 64, 67];
2141 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 5);
2142 }
2143
2144 #[test]
2146 fn primal_module_serial_basic_9() {
2147 let visualize_filename = "primal_module_serial_basic_9.json".to_string();
2149 let defect_vertices = vec![60, 63, 66, 30];
2150 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 6);
2151 }
2152
2153 #[test]
2155 fn primal_module_serial_basic_10() {
2156 let visualize_filename = "primal_module_serial_basic_10.json".to_string();
2158 let defect_vertices = vec![39, 52, 63, 90, 100];
2159 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 9);
2160 }
2161
2162 #[test]
2164 fn primal_module_union_find_basic_10() {
2165 let visualize_filename = "primal_module_union_find_basic_10.json".to_string();
2167 let defect_vertices = vec![39, 52, 63, 90, 100];
2168 let func = primal_module_serial_basic_standard_syndrome_optional_viz_max_tree_size;
2169 func(11, Some(visualize_filename), defect_vertices, 9, 0);
2170 }
2172
2173 #[test]
2175 fn primal_module_serial_default_example() {
2176 let visualize_filename = static_visualize_data_filename();
2178 let defect_vertices = vec![39, 52, 63, 90, 100];
2179 primal_module_serial_basic_standard_syndrome(11, visualize_filename, defect_vertices, 9);
2180 }
2181
2182 #[test]
2185 fn primal_module_serial_basic_11() {
2186 let visualize_filename = "primal_module_serial_basic_11.json".to_string();
2188 let defect_vertices = vec![
2189 13, 29, 52, 53, 58, 60, 71, 74, 76, 87, 96, 107, 112, 118, 121, 122, 134, 137, 141, 145, 152, 153, 154, 156,
2190 157, 169, 186, 202, 203, 204, 230, 231,
2191 ];
2192 primal_module_serial_basic_standard_syndrome(15, visualize_filename, defect_vertices, 20);
2193 }
2194
2195 #[test]
2197 #[cfg(feature = "blossom_v")]
2198 fn primal_module_debug_1() {
2199 let visualize_filename = "primal_module_debug_1.json".to_string();
2201 let defect_vertices = vec![
2202 34, 35, 84, 89, 92, 100, 141, 145, 149, 164, 193, 201, 205, 220, 235, 242, 243, 260, 261, 290, 300, 308, 309,
2203 315, 317,
2204 ];
2205 let max_half_weight = 500;
2206 let mut code = CircuitLevelPlanarCode::new(7, 7, 0.01, max_half_weight);
2207 let mut visualizer = Visualizer::new(
2208 Some(visualize_data_folder() + visualize_filename.as_str()),
2209 code.get_positions(),
2210 true,
2211 )
2212 .unwrap();
2213 print_visualize_link(visualize_filename.clone());
2214 let initializer = code.get_initializer();
2215 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2217 println!("blossom_mwpm_result: {blossom_mwpm_result:?}");
2218 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2219 let mut blossom_total_weight = 0;
2220 for detail in blossom_details.iter() {
2221 println!(" {detail:?}");
2222 blossom_total_weight += detail.weight;
2223 }
2224 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2226 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2228 primal_module.write().debug_resolve_only_one = true; code.set_defect_vertices(&defect_vertices);
2231 let interface_ptr = DualModuleInterfacePtr::new_empty();
2232 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2233 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2234 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2235 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2236 let mut fusion_total_weight = 0;
2237 for detail in fusion_details.iter() {
2238 println!(" {detail:?}");
2239 fusion_total_weight += detail.weight;
2240 }
2241 assert_eq!(
2242 fusion_total_weight, blossom_total_weight,
2243 "unexpected final dual variable sum"
2244 );
2245 {
2246 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2248 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2249 assert_eq!(
2250 subgraph_builder.total_weight(),
2251 blossom_total_weight,
2252 "unexpected final dual variable sum"
2253 );
2254 }
2255 assert_eq!(
2256 interface_ptr.sum_dual_variables(),
2257 blossom_total_weight,
2258 "unexpected final dual variable sum"
2259 );
2260 }
2261
2262 #[test]
2264 #[cfg(feature = "blossom_v")]
2265 fn primal_module_debug_2() {
2266 let visualize_filename = "primal_module_debug_2.json".to_string();
2268 let defect_vertices = vec![
2269 7, 8, 10, 22, 23, 24, 25, 37, 38, 39, 40, 42, 43, 69, 57, 59, 60, 72, 76, 93, 109, 121, 123, 125, 135, 136, 137,
2270 138, 139, 140, 141, 150, 151, 153, 154, 155, 166, 171, 172, 181, 183, 184, 188, 200, 204, 219, 233,
2271 ];
2272 let max_half_weight = 500;
2273 let mut code = CodeCapacityPlanarCode::new(15, 0.3, max_half_weight);
2274 let mut visualizer = Visualizer::new(
2275 Some(visualize_data_folder() + visualize_filename.as_str()),
2276 code.get_positions(),
2277 true,
2278 )
2279 .unwrap();
2280 print_visualize_link(visualize_filename.clone());
2281 let initializer = code.get_initializer();
2282 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2284 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2285 let mut blossom_total_weight = 0;
2286 for detail in blossom_details.iter() {
2287 println!(" {detail:?}");
2288 blossom_total_weight += detail.weight;
2289 }
2290 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2292 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2294 primal_module.write().debug_resolve_only_one = true; code.set_defect_vertices(&defect_vertices);
2297 let interface_ptr = DualModuleInterfacePtr::new_empty();
2298 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2299 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2300 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2301 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2302 let mut fusion_total_weight = 0;
2303 for detail in fusion_details.iter() {
2304 println!(" {detail:?}");
2305 fusion_total_weight += detail.weight;
2306 }
2307 assert_eq!(
2308 fusion_total_weight, blossom_total_weight,
2309 "unexpected final dual variable sum"
2310 );
2311 {
2312 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2314 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2315 assert_eq!(
2316 subgraph_builder.total_weight(),
2317 blossom_total_weight,
2318 "unexpected final dual variable sum"
2319 );
2320 }
2321 assert_eq!(
2322 interface_ptr.sum_dual_variables(),
2323 blossom_total_weight,
2324 "unexpected final dual variable sum"
2325 );
2326 }
2327
2328 #[test]
2330 #[cfg(feature = "blossom_v")]
2331 fn primal_module_debug_3() {
2332 let visualize_filename = "primal_module_debug_3.json".to_string();
2334 let defect_vertices = vec![
2335 17, 34, 36, 54, 55, 74, 95, 96, 112, 113, 114, 115, 116, 130, 131, 132, 134, 150, 151, 154, 156, 171, 172, 173,
2336 190,
2337 ];
2338 let max_half_weight = 500;
2339 let mut code = CodeCapacityPlanarCode::new(19, 0.499, max_half_weight);
2340 let mut visualizer = Visualizer::new(
2341 Some(visualize_data_folder() + visualize_filename.as_str()),
2342 code.get_positions(),
2343 true,
2344 )
2345 .unwrap();
2346 print_visualize_link(visualize_filename.clone());
2347 let initializer = code.get_initializer();
2348 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2350 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2351 let mut blossom_total_weight = 0;
2352 for detail in blossom_details.iter() {
2353 println!(" {detail:?}");
2354 blossom_total_weight += detail.weight;
2355 }
2356 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2358 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2360 primal_module.write().debug_resolve_only_one = true; code.set_defect_vertices(&defect_vertices);
2363 let interface_ptr = DualModuleInterfacePtr::new_empty();
2364 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2365 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2366 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2367 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2368 let mut fusion_total_weight = 0;
2369 for detail in fusion_details.iter() {
2370 println!(" {detail:?}");
2371 fusion_total_weight += detail.weight;
2372 }
2373 assert_eq!(
2374 fusion_total_weight, blossom_total_weight,
2375 "unexpected final dual variable sum"
2376 );
2377 {
2378 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2380 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2381 assert_eq!(
2382 subgraph_builder.total_weight(),
2383 blossom_total_weight,
2384 "unexpected final dual variable sum"
2385 );
2386 }
2387 assert_eq!(
2388 interface_ptr.sum_dual_variables(),
2389 blossom_total_weight,
2390 "unexpected final dual variable sum"
2391 );
2392 }
2393
2394 #[test]
2396 #[cfg(feature = "blossom_v")]
2397 fn primal_module_debug_4() {
2398 let visualize_filename = "primal_module_debug_4.json".to_string();
2400 let defect_vertices = vec![1, 3, 6, 8, 9, 11, 13];
2401 let max_half_weight = 500;
2402 let mut code = CodeCapacityRepetitionCode::new(15, 0.499, max_half_weight);
2403 let mut visualizer = Visualizer::new(
2404 Some(visualize_data_folder() + visualize_filename.as_str()),
2405 code.get_positions(),
2406 true,
2407 )
2408 .unwrap();
2409 print_visualize_link(visualize_filename.clone());
2410 let initializer = code.get_initializer();
2411 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2413 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2414 let mut blossom_total_weight = 0;
2415 for detail in blossom_details.iter() {
2416 println!(" {detail:?}");
2417 blossom_total_weight += detail.weight;
2418 }
2419 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2421 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2423 primal_module.write().debug_resolve_only_one = true; code.set_defect_vertices(&defect_vertices);
2426 let interface_ptr = DualModuleInterfacePtr::new_empty();
2427 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2428 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2429 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2430 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2431 let mut fusion_total_weight = 0;
2432 for detail in fusion_details.iter() {
2433 println!(" {detail:?}");
2434 fusion_total_weight += detail.weight;
2435 }
2436 assert_eq!(
2437 fusion_total_weight, blossom_total_weight,
2438 "unexpected final dual variable sum"
2439 );
2440 {
2441 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2443 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2444 assert_eq!(
2445 subgraph_builder.total_weight(),
2446 blossom_total_weight,
2447 "unexpected final dual variable sum"
2448 );
2449 }
2450 assert_eq!(
2451 interface_ptr.sum_dual_variables(),
2452 blossom_total_weight,
2453 "unexpected final dual variable sum"
2454 );
2455 }
2456
2457 #[test]
2459 #[cfg(feature = "blossom_v")]
2460 fn primal_module_debug_5() {
2461 let visualize_filename = "primal_module_debug_5.json".to_string();
2463 let defect_vertices = vec![0, 1, 3, 8, 9];
2464 let max_half_weight = 500;
2465 let mut code = CodeCapacityRepetitionCode::new(11, 0.03, max_half_weight);
2466 let mut visualizer = Visualizer::new(
2467 Some(visualize_data_folder() + visualize_filename.as_str()),
2468 code.get_positions(),
2469 true,
2470 )
2471 .unwrap();
2472 print_visualize_link(visualize_filename.clone());
2473 let initializer = code.get_initializer();
2474 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2476 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2477 let mut blossom_total_weight = 0;
2478 for detail in blossom_details.iter() {
2479 println!(" {detail:?}");
2480 blossom_total_weight += detail.weight;
2481 }
2482 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2484 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2486 code.set_defect_vertices(&defect_vertices);
2488 let interface_ptr = DualModuleInterfacePtr::new_empty();
2489 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2490 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2491 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2492 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2493 let mut fusion_total_weight = 0;
2494 for detail in fusion_details.iter() {
2495 println!(" {detail:?}");
2496 fusion_total_weight += detail.weight;
2497 }
2498 assert_eq!(
2499 fusion_total_weight, blossom_total_weight,
2500 "unexpected final dual variable sum"
2501 );
2502 {
2503 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2505 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2506 assert_eq!(
2507 subgraph_builder.total_weight(),
2508 blossom_total_weight,
2509 "unexpected final dual variable sum"
2510 );
2511 }
2512 assert_eq!(
2513 interface_ptr.sum_dual_variables(),
2514 blossom_total_weight,
2515 "unexpected final dual variable sum"
2516 );
2517 }
2518
2519 #[test]
2520 fn primal_module_serial_perfect_matching_1() {
2521 let defect_vertices = vec![39, 51, 61, 62, 63, 64, 65, 75, 87, 67];
2523 let (interface_ptr, mut primal_module, mut dual_module) =
2524 primal_module_serial_basic_standard_syndrome_optional_viz(11, None, defect_vertices, 6);
2525 let intermediate_matching = primal_module.intermediate_matching(&interface_ptr, &mut dual_module);
2526 println!("intermediate_matching: {intermediate_matching:?}");
2527 let perfect_matching = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2528 println!("perfect_matching: {perfect_matching:?}");
2529 }
2530
2531 #[test]
2533 #[cfg(feature = "blossom_v")]
2534 fn primal_module_debug_6() {
2535 let visualize_filename = "primal_module_debug_6.json".to_string();
2537 let defect_vertices = vec![13, 34, 87, 107, 276, 296];
2538 let erasures = [13, 33, 174, 516];
2539 let max_half_weight = 500;
2540 let mut code = CodeCapacityPlanarCode::new(19, 0., max_half_weight);
2541 code.set_erasure_probability(0.003);
2542 let mut visualizer = Visualizer::new(
2543 Some(visualize_data_folder() + visualize_filename.as_str()),
2544 code.get_positions(),
2545 true,
2546 )
2547 .unwrap();
2548 print_visualize_link(visualize_filename.clone());
2549 let mut initializer = code.get_initializer();
2550 for edge_index in erasures.iter() {
2551 let (vertex_idx_1, vertex_idx_2, _) = &initializer.weighted_edges[*edge_index];
2552 initializer.weighted_edges[*edge_index] = (*vertex_idx_1, *vertex_idx_2, 0);
2553 }
2554 let blossom_mwpm_result = blossom_v_mwpm(&initializer, &defect_vertices);
2556 let blossom_details = detailed_matching(&initializer, &defect_vertices, &blossom_mwpm_result);
2557 let mut blossom_total_weight = 0;
2558 for detail in blossom_details.iter() {
2559 println!(" {detail:?}");
2560 blossom_total_weight += detail.weight;
2561 }
2562 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2564 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2566 code.set_defect_vertices(&defect_vertices);
2568 let interface_ptr = DualModuleInterfacePtr::new_empty();
2569 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2570 let fusion_mwpm = primal_module.perfect_matching(&interface_ptr, &mut dual_module);
2571 let fusion_mwpm_result = fusion_mwpm.legacy_get_mwpm_result(defect_vertices.clone());
2572 let fusion_details = detailed_matching(&initializer, &defect_vertices, &fusion_mwpm_result);
2573 let mut fusion_total_weight = 0;
2574 for detail in fusion_details.iter() {
2575 println!(" {detail:?}");
2576 fusion_total_weight += detail.weight;
2577 }
2578 assert_eq!(
2579 fusion_total_weight, blossom_total_weight,
2580 "unexpected final dual variable sum"
2581 );
2582 {
2583 let mut subgraph_builder = SubGraphBuilder::new(&initializer);
2585 subgraph_builder.load_perfect_matching(&fusion_mwpm);
2586 assert_eq!(
2587 subgraph_builder.total_weight(),
2588 blossom_total_weight,
2589 "unexpected final dual variable sum"
2590 );
2591 }
2592 assert_eq!(
2593 interface_ptr.sum_dual_variables(),
2594 blossom_total_weight,
2595 "unexpected final dual variable sum"
2596 );
2597 }
2598
2599 #[test]
2601 fn primal_module_debug_7() {
2602 let visualize_filename = "primal_module_debug_7.json".to_string();
2604 let defect_vertices = vec![10, 11, 19, 21, 29, 34, 37, 40, 43, 49, 50, 51, 53];
2605 let max_half_weight = 500;
2606 let mut code = CodeCapacityPlanarCode::new(7, 0.1, max_half_weight);
2607 let mut visualizer = Visualizer::new(
2608 Some(visualize_data_folder() + visualize_filename.as_str()),
2609 code.get_positions(),
2610 true,
2611 )
2612 .unwrap();
2613 print_visualize_link(visualize_filename.clone());
2614 let initializer = code.get_initializer();
2615 let mut dual_module = DualModuleSerial::new_empty(&initializer);
2616 let mut primal_module = PrimalModuleSerialPtr::new_empty(&initializer);
2617 code.set_defect_vertices(&defect_vertices);
2618 let interface_ptr = DualModuleInterfacePtr::new_empty();
2619 primal_module.solve_visualizer(&interface_ptr, &code.get_syndrome(), &mut dual_module, Some(&mut visualizer));
2620 }
2621}