1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * Test of composite constructors/signature computation
21  * and congruence table
22  */
23 
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdbool.h>
27 #include <inttypes.h>
28 
29 #include "solvers/egraph/composites.h"
30 #include "solvers/egraph/egraph_printer.h"
31 #include "solvers/egraph/egraph_types.h"
32 #include "utils/arena.h"
33 
34 
35 /*
36  * Test partition: 11 terms, 4 classes
37  * class[0] = { true, a-, b+ }
38  * class[1] = { c+, d- }
39  * class[2] = { e+, f+, g+ }
40  * class[3] = { h+, i+, j+ }
41  *
42  * with classes 2 and 3 distinct
43  */
44 
45 #define NC 4
46 #define NT 11
47 
48 // fixed label array
49 static elabel_t label[NT];
50 
51 
52 static eterm_t a = 1;
53 static eterm_t b = 2;
54 static eterm_t c = 3;
55 static eterm_t d = 4;
56 static eterm_t e = 5;
57 static eterm_t f = 6;
58 static eterm_t g = 7;
59 static eterm_t h = 8;
60 static eterm_t i = 9;
61 static eterm_t j = 10;
62 
63 
64 #define NCMP 50
65 
66 static composite_t *composite[NCMP];
67 static signature_t sgn;
68 
69 
70 static congruence_table_t tbl;
71 
72 
73 /*
74  * Initialize the labels
75  */
init_labels(void)76 static void init_labels(void) {
77   label[0] = pos_label(0); // true
78   label[a] = neg_label(0);
79   label[b] = pos_label(0);
80 
81   label[c] = pos_label(1);
82   label[d] = neg_label(1);
83 
84   label[e] = pos_label(2);
85   label[f] = pos_label(2);
86   label[g] = pos_label(2);
87 
88   label[h] = pos_label(3);
89   label[i] = pos_label(3);
90   label[j] = pos_label(3);
91 };
92 
93 /*
94  * Test constructors
95  */
apply2(eterm_t f,occ_t x,occ_t y)96 static composite_t *apply2(eterm_t f, occ_t x, occ_t y) {
97   occ_t aux[2];
98 
99   aux[0] = x;
100   aux[1] = y;
101   return new_apply_composite(pos_occ(f), 2, aux);
102 }
103 
update2(eterm_t f,occ_t x,occ_t y,occ_t v)104 static composite_t *update2(eterm_t f, occ_t x, occ_t y, occ_t v) {
105   occ_t aux[2];
106 
107   aux[0] = x;
108   aux[1] = y;
109   return new_update_composite(pos_occ(f), 2, aux, v);
110 }
111 
pair(occ_t x,occ_t y)112 static composite_t *pair(occ_t x, occ_t y) {
113   occ_t aux[2];
114 
115   aux[0] = x;
116   aux[1] = y;
117   return new_tuple_composite(2, aux);
118 }
119 
lambda(occ_t x,int32_t tag)120 static composite_t *lambda(occ_t x, int32_t tag) {
121   return new_lambda_composite(x, tag);
122 }
123 
build_composites(void)124 static void build_composites(void) {
125   composite[0] = pair(pos_occ(a), neg_occ(a));
126   composite[0]->id = 100;
127   composite[1] = pair(pos_occ(a), pos_occ(a));
128   composite[1]->id = 101;
129   composite[2] = pair(neg_occ(a), pos_occ(a));
130   composite[2]->id = 102;
131   composite[3] = pair(neg_occ(a), neg_occ(a));
132   composite[3]->id = 103;
133 
134   composite[4] = pair(pos_occ(a), true_occ);
135   composite[4]->id = 104;
136   composite[5] = pair(pos_occ(a), false_occ);
137   composite[5]->id = 105;
138   composite[6] = pair(neg_occ(a), pos_occ(b));
139   composite[6]->id = 106;
140   composite[7] = pair(neg_occ(a), neg_occ(b));
141   composite[7]->id = 107;
142 
143   composite[8] = apply2(f, pos_occ(c), pos_occ(c));
144   composite[8]->id = 108;
145   composite[9] = update2(f, pos_occ(c), neg_occ(d), pos_occ(h));
146   composite[9]->id = 109;
147 
148   composite[10] = lambda(pos_occ(a), 0);
149   composite[10]->id = 110;
150   composite[11] = lambda(pos_occ(a), 1);
151   composite[11]->id = 110;
152 }
153 
delete_composites(uint32_t n)154 static void delete_composites(uint32_t n) {
155   uint32_t k;
156 
157   for (k=0; k<n; k++) {
158     safe_free(composite[k]);
159   }
160 }
161 
162 
print_composites(uint32_t n)163 static void print_composites(uint32_t n) {
164   uint32_t k;
165 
166   printf("==== Terms ====\n");
167   for (k=0; k<n; k++) {
168     printf("cmp[%"PRIu32"] = ", k);
169     print_composite(stdout, composite[k]);
170     printf("\n");
171   }
172   fflush(stdout);
173 }
174 
show_label(eterm_t t)175 static void show_label(eterm_t t) {
176   print_eterm_id(stdout, t);
177   printf(" ---> ");
178   print_label(stdout, label[t]);
179   printf("\n");
180 }
181 
print_labels(void)182 static void print_labels(void) {
183   eterm_t t;
184 
185   printf("==== Labels ====\n");
186   for (t=0; t<NT; t++) {
187     show_label(t);
188   }
189   fflush(stdout);
190 }
191 
test_signatures(uint32_t n)192 static void test_signatures(uint32_t n) {
193   uint32_t k;
194 
195   for (k=0; k<n; k++) {
196     printf("cmp[%"PRIu32"] = ", k);
197     print_composite(stdout, composite[k]);
198     printf("\n");
199     signature_composite(composite[k], label, &sgn);
200     printf("---> signature = ");
201     print_signature(stdout, &sgn);
202     printf("\n");
203   }
204 }
205 
test_eq(arena_t * m,occ_t t1,occ_t t2)206 static void test_eq(arena_t *m, occ_t t1, occ_t t2) {
207   composite_t *tmp;
208 
209   tmp = arena_eq_composite(m, t1, t2);
210   signature_composite(tmp, label, &sgn);
211   print_composite(stdout, tmp);
212   printf("\t---> signature = ");
213   print_signature(stdout, &sgn);
214   printf("\n");
215 }
216 
test_equalities(uint32_t n)217 static void test_equalities(uint32_t n) {
218   uint32_t k, l;
219   arena_t m;
220 
221   init_arena(&m);
222   for (k=0; k<n; k++) {
223     arena_push(&m);
224     for (l=0; l<n; l++) {
225       show_label(k);
226       if (k != l) show_label(l);
227 
228       test_eq(&m, pos_occ(k), pos_occ(l));
229       test_eq(&m, pos_occ(k), neg_occ(l));
230       test_eq(&m, neg_occ(k), pos_occ(l));
231       test_eq(&m, neg_occ(k), neg_occ(l));
232       printf("\n");
233     }
234     arena_pop(&m);
235   }
236   delete_arena(&m);
237 }
238 
239 
test_or3(arena_t * m,occ_t t1,occ_t t2,occ_t t3)240 static void test_or3(arena_t *m, occ_t t1, occ_t t2, occ_t t3) {
241   occ_t aux[3];
242   composite_t *tmp;
243 
244   aux[0] = t1;
245   aux[1] = t2;
246   aux[2] = t3;
247 
248   tmp = arena_or_composite(m, 3, aux);
249   signature_or(tmp, label, &sgn);
250   print_composite(stdout, tmp);
251   printf("\t---> signature = ");
252   print_signature(stdout, &sgn);
253   printf("\n");
254 }
255 
test_disjunctions(uint32_t n)256 static void test_disjunctions(uint32_t n) {
257   uint32_t t1, t2, t3;
258   arena_t m;
259 
260   init_arena(&m);
261   for (t1=0; t1<n; t1++) {
262     arena_push(&m);
263 
264     for (t2=0; t2<n; t2++) {
265       for (t3=0; t3<n; t3++) {
266 	show_label(t1);
267 	if (t1 != t2) show_label(t2);
268 	if (t1 != t3 && t2 != t3) show_label(t3);
269 	test_or3(&m, pos_occ(t1), pos_occ(t2), pos_occ(t3));
270 	printf("\n");
271       }
272     }
273 
274     arena_pop(&m);
275   }
276   delete_arena(&m);
277 }
278 
279 
test_congruences(uint32_t n)280 static void test_congruences(uint32_t n) {
281   uint32_t k;
282   composite_t *tmp, *root;
283   uint32_t nroots;
284   composite_t *roots[n];
285 
286 
287   nroots = 0;
288   for (k=0; k<n; k++) {
289     print_composite(stdout, composite[k]);
290     printf("\n");
291     signature_composite(composite[k], label, &sgn);
292     printf("---> signature = ");
293     print_signature(stdout, &sgn);
294     printf("\n");
295 
296     root = congruence_table_find(&tbl, &sgn, label);
297     if (root == NULL) {
298       printf("---> not in congruence table\n");
299     } else {
300       printf("---> congruent to term: ");
301       print_composite(stdout, root);
302       printf("\n");
303     }
304 
305     tmp = congruence_table_get(&tbl, composite[k], &sgn, label);
306     printf("---> get returns: ");
307     print_composite(stdout, tmp);
308     printf("\n");
309     if (tmp == composite[k] && root == NULL) {
310       printf("---> added as congruence root\n");
311       roots[nroots] = tmp;
312       nroots ++;
313     } else if (tmp == root && root != NULL) {
314       printf("---> confirmed congruence\n");
315     } else {
316       printf("\n*** BUG: get/find disagree ***\n");
317     }
318 
319     printf("\n");
320     fflush(stdout);
321   }
322 
323   for (k=0; k<nroots; k++) {
324     tmp = roots[k];
325     printf("---> removing root: ");
326     print_composite(stdout, tmp);
327     printf("\n");
328     congruence_table_remove(&tbl, tmp);
329   }
330 
331   printf("\n");
332   fflush(stdout);
333 }
334 
main(void)335 int main(void) {
336   init_labels();
337   init_sign_buffer(&sgn);
338   init_congruence_table(&tbl, 1);
339 
340   build_composites();
341   print_labels();
342   print_composites(12);
343   printf("\n");
344 
345   test_signatures(12);
346   printf("\n");
347 
348   test_equalities(12);
349   printf("\n");
350 
351   test_disjunctions(12);
352   printf("\n");
353 
354   test_congruences(12);
355 
356   delete_composites(12);
357   delete_congruence_table(&tbl);
358   delete_sign_buffer(&sgn);
359 
360   return 0;
361 }
362