haar_lib/ds/
potential_unionfind.rs1use crate::algebra::traits::*;
8use std::cell::{Cell, RefCell};
9
10pub struct PotentialUnionFind<G: Group> {
12 group: G,
13 n: usize,
14 count: usize,
15 parent: Vec<Cell<usize>>,
16 depth: Vec<usize>,
17 size: Vec<usize>,
18 potential: RefCell<Vec<G::Element>>,
19 inverse: Option<RefCell<Vec<G::Element>>>,
20}
21
22impl<G> PotentialUnionFind<G>
23where
24 G: AbelianGroup,
25 G::Element: Clone,
26{
27 pub fn new_commutative(group: G, n: usize) -> Self {
29 Self {
30 n,
31 count: n,
32 parent: (0..n).map(Cell::new).collect(),
33 depth: vec![1; n],
34 size: vec![1; n],
35 potential: RefCell::new(vec![group.id(); n]),
36 inverse: None,
37 group,
38 }
39 }
40}
41
42impl<G> PotentialUnionFind<G>
43where
44 G: Group,
45 G::Element: Clone,
46{
47 pub fn new_non_commutative(group: G, n: usize) -> Self {
49 Self {
50 n,
51 count: n,
52 parent: (0..n).map(Cell::new).collect(),
53 depth: vec![1; n],
54 size: vec![1; n],
55 potential: RefCell::new(vec![group.id(); n]),
56 inverse: Some(RefCell::new(vec![group.id(); n])),
57 group,
58 }
59 }
60
61 pub fn root_of(&self, i: usize) -> usize {
63 if self.parent[i].get() == i {
64 return i;
65 }
66 let p = self.parent[i].get();
67 let p = self.root_of(p);
68
69 let mut potential = self.potential.borrow_mut();
70 let t = potential[self.parent[i].get()].clone();
71 self.group.op_assign_l(&mut potential[i], t);
72
73 if let Some(inv) = self.inverse.as_ref() {
74 let mut inv = inv.borrow_mut();
75 let t = inv[self.parent[i].get()].clone();
76 self.group.op_assign_r(&mut inv[i], t);
77 }
78
79 self.parent[i].set(p);
80 self.parent[i].get()
81 }
82
83 pub fn potential_of(&self, i: usize) -> G::Element {
85 self.potential.borrow()[i].clone()
86 }
87
88 pub fn is_same(&self, i: usize, j: usize) -> bool {
90 self.root_of(i) == self.root_of(j)
91 }
92
93 pub fn diff(&self, i: usize, j: usize) -> Option<G::Element> {
95 self.is_same(i, j).then(|| {
96 let pi = self.potential_of(i);
97 if let Some(inv) = self.inverse.as_ref() {
98 self.group.op(inv.borrow()[j].clone(), pi)
99 } else {
100 self.group.op(self.group.inv(self.potential_of(j)), pi)
101 }
102 })
103 }
104
105 pub fn merge(&mut self, i: usize, j: usize, p: G::Element) -> usize {
108 let ri = self.root_of(i);
109 let rj = self.root_of(j);
110
111 if ri == rj {
112 return ri;
113 }
114
115 self.count -= 1;
116
117 let mut potential = self.potential.borrow_mut();
118 let (pi, pj) = (potential[i].clone(), potential[j].clone());
119
120 let g = &self.group;
121
122 if self.depth[ri] < self.depth[rj] {
123 self.parent[ri].set(rj);
124 self.size[rj] += self.size[ri];
125
126 if let Some(inv) = self.inverse.as_ref() {
127 let mut inv = inv.borrow_mut();
128 potential[ri] = g.fold_m([pj, p.clone(), inv[i].clone()]);
129 inv[ri] = g.fold_m([pi, g.inv(p), inv[j].clone()]);
130 } else {
131 potential[ri] = g.fold_m([pj, p, g.inv(pi)]);
132 }
133
134 j
135 } else {
136 self.parent[rj].set(ri);
137 self.size[ri] += self.size[rj];
138
139 if let Some(inv) = self.inverse.as_ref() {
140 let mut inv = inv.borrow_mut();
141 potential[rj] = g.fold_m([pi, g.inv(p.clone()), inv[j].clone()]);
142 inv[rj] = g.fold_m([pj, p, inv[i].clone()]);
143 } else {
144 potential[rj] = g.fold_m([pi, g.inv(p), g.inv(pj)]);
145 }
146
147 if self.depth[ri] == self.depth[rj] {
148 self.depth[i] += 1;
149 }
150
151 i
152 }
153 }
154
155 pub fn size_of(&self, i: usize) -> usize {
157 self.size[self.root_of(i)]
158 }
159
160 pub fn count_groups(&self) -> usize {
162 self.count
163 }
164
165 pub fn get_groups(&self) -> Vec<Vec<usize>> {
167 let mut ret = vec![vec![]; self.n];
168
169 for i in 0..self.n {
170 ret[self.root_of(i)].push(i);
171 }
172
173 ret.into_iter().filter(|x| !x.is_empty()).collect()
174 }
175}