slotted_egraphs/egraph/
check.rs1use vec_collections::AbstractVecSet;
2
3use crate::*;
4
5impl<L: Language, N: Analysis<L>> EGraph<L, N> {
6 #[track_caller]
8 pub(crate) fn mk_sem_applied_id(&self, i: Id, m: SlotMap) -> AppliedId {
9 let app_id = AppliedId::new(i, m);
10
11 if CHECKS {
12 self.check_sem_applied_id(&app_id);
13 }
14
15 app_id
16 }
17
18
19 #[track_caller]
21 pub fn mk_identity_applied_id(&self, i: Id) -> AppliedId {
22 self.mk_sem_identity_applied_id(i)
23 }
24
25 #[track_caller]
26 pub(crate) fn mk_sem_identity_applied_id(&self, i: Id) -> AppliedId {
27 self.mk_sem_applied_id(i, SlotMap::identity(&self.slots(i)))
28 }
29
30 #[track_caller]
31 pub(crate) fn check_sem_applied_id(&self, app_id: &AppliedId) {
32 app_id.check();
33 assert_eq!(
34 self.slots(app_id.id),
35 app_id.m.keys(),
36 "checking sem AppliedId failed: Wrong key-set, {app_id:?}"
37 );
38 }
39
40 #[track_caller]
42 pub(crate) fn mk_syn_applied_id(&self, i: Id, m: SlotMap) -> AppliedId {
43 let app_id = AppliedId::new(i, m);
44
45 if CHECKS {
46 self.check_syn_applied_id(&app_id);
47 }
48
49 app_id
50 }
51
52 #[track_caller]
53 pub(crate) fn mk_syn_identity_applied_id(&self, i: Id) -> AppliedId {
54 self.mk_syn_applied_id(i, SlotMap::identity(&self.syn_slots(i)))
55 }
56
57 #[track_caller]
58 pub(crate) fn check_syn_applied_id(&self, app_id: &AppliedId) {
59 app_id.check();
60 assert_eq!(
61 self.syn_slots(app_id.id),
62 app_id.m.keys(),
63 "checking syn AppliedId failed: Wrong key-set, {app_id:?}"
64 );
65 }
66
67 pub fn check(&self) {
68 let mut hashcons = HashMap::default();
71 let mut usages = HashMap::default();
72
73 for (i, _) in &self.classes {
74 usages.insert(*i, HashSet::default());
75 }
76
77 for (i, _) in &self.classes {
80 if !self.is_alive(*i) {
81 continue;
82 }
83
84 let sem = self.mk_sem_identity_applied_id(*i);
87 let sem2 = self.find_applied_id(&sem);
88 assert_eq!(sem, sem2);
89
90 #[cfg(feature = "explanations")]
91 {
92 let c = &self.classes[i];
93 let eq = self.proven_unionfind_get(*i).proof.equ();
94 let tmp = eq.l.m.compose_partial(&eq.r.m.inverse());
97 assert!(tmp.is_perm());
98 assert_eq!(c.slots, tmp.keys());
99 assert_eq!(c.slots, tmp.values());
100 }
101 }
102
103 for (i, c) in &self.classes {
104 for sh in c.nodes.keys() {
105 assert!(!hashcons.contains_key(sh));
106 hashcons.insert(sh.clone(), *i);
107
108 for ref_id in sh.ids() {
109 usages.get_mut(&ref_id).unwrap().insert(sh.clone());
110 }
111 }
112 }
113
114 assert_eq!(hashcons, self.hashcons);
115 for (i, c) in &self.classes {
116 assert_eq!(usages[&i], c.usages);
117 }
118
119 for (_, c) in &self.classes {
120 for p in c.group.all_perms() {
121 p.check();
122 }
123 }
124
125 let all_keys = self
127 .unionfind_iter()
128 .map(|(x, _)| x)
129 .collect::<HashSet<_>>();
130 let all_values = self
131 .unionfind_iter()
132 .map(|(_, x)| x.id)
133 .collect::<HashSet<_>>();
134 let all_classes = self.classes.keys().copied().collect::<HashSet<_>>();
135 let all: HashSet<Id> = &(&all_keys | &all_values) | &all_classes;
136 for i in all {
137 if self.is_alive(i) {
139 assert_eq!(self.unionfind_get(i), self.mk_sem_identity_applied_id(i));
140 } else {
141 assert!(self.classes[&i].nodes.is_empty());
142 for sh in &self.classes[&i].usages {
143 assert_eq!(self.pending.get(&sh), Some(&PendingType::Full));
144 }
145 }
146 }
147
148 for (_, c) in &self.classes {
150 assert!(!c.slots.contains(&Slot::numeric(0)));
151 }
152
153 for (_, app_id) in self.unionfind_iter() {
155 check_internal_applied_id::<L, N>(self, &app_id);
156 }
157
158 for (_, c) in &self.classes {
160 for (sh, ProvenSourceNode { elem: bij, .. }) in &c.nodes {
161 let real = sh.apply_slotmap(bij);
162 assert!(real.slots().is_superset(&c.slots));
163
164 if self.pending.get(&sh) == Some(&PendingType::Full) {
165 continue;
166 }
167
168 let (computed_sh, computed_bij) = self.shape(&real);
169 assert_eq!(&computed_sh, sh);
170
171 let perm = computed_bij.inverse().compose_partial(&bij);
174 assert!(c.group.contains(&perm));
175
176 for x in real.applied_id_occurrences() {
177 check_internal_applied_id::<L, N>(self, &x);
178 }
179 }
180 }
181
182 fn check_internal_applied_id<L: Language, N: Analysis<L>>(
183 eg: &EGraph<L, N>,
184 app_id: &AppliedId,
185 ) {
186 let y = eg.find_applied_id(app_id);
188 assert_eq!(app_id, &y);
189
190 assert_eq!(&app_id.m.keys(), &eg.classes[&app_id.id].slots);
192 }
193 }
194}