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 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <inttypes.h>
23 
24 #include "solvers/egraph/egraph_types.h"
25 #include "solvers/egraph/theory_explanations.h"
26 
27 #ifdef MINGW
28 
29 /*
30  * Need some version of random()
31  * rand() exists on mingw
32  */
random(void)33 static inline long int random(void) {
34   return rand();
35 }
36 
37 #endif
38 
39 /*
40  * Theory explanation object:
41  * - av = atom vector
42  * - eqv = equality vector
43  * - dv = disequality vector (not used here)
44  */
show_atoms(atom_vector_t * av)45 static void show_atoms(atom_vector_t *av) {
46   uint32_t i, n, k;
47 
48   n = av->size;
49   k = 0;
50   for (i=0; i<n; i++) {
51     if (k == 30) {
52       k = 0;
53       printf("\n        ");
54     }
55     k ++;
56     printf(" %"PRId32, av->data[i]);
57   }
58 }
59 
show_eqs(eq_vector_t * eqv)60 static void show_eqs(eq_vector_t *eqv) {
61   uint32_t i, n, k;
62 
63   n = eqv->size;
64   k = 0;
65   for (i=0; i<n; i++) {
66     if (k == 8) {
67       k = 0;
68       printf("\n      ");
69     }
70     k ++;
71     printf(" (t%"PRId32" = t%"PRId32")", eqv->data[i].lhs, eqv->data[i].rhs);
72   }
73 }
74 
75 
show_th_explanation(th_explanation_t * e)76 static void show_th_explanation(th_explanation_t *e) {
77   literal_t *atm;
78   th_eq_t *eqs;
79   uint32_t na, ne;
80 
81   printf("  atoms:");
82   atm = e->atoms;
83   if (atm == NULL) {
84     na = 0;
85     printf(" none\n");
86   } else {
87     na = get_av_size(atm);
88     show_atoms(av_header(atm));
89     printf("\n");
90   }
91   printf("  eqs:");
92   eqs = e->eqs;
93   if (eqs == NULL) {
94     ne = 0;
95     printf(" none\n");
96   } else {
97     ne = get_eqv_size(eqs);
98     show_eqs(eqv_header(eqs));
99     printf("\n");
100   }
101   printf("  %"PRIu32" atoms, %"PRId32" equalities\n", na, ne);
102 }
103 
104 
105 /*
106  * Add n random atoms to e
107  */
add_atoms(th_explanation_t * e,uint32_t n)108 static void add_atoms(th_explanation_t *e, uint32_t n) {
109   int32_t x;
110 
111   while (n > 0) {
112     n --;
113     x = random() & 0x3f;
114     th_explanation_add_atom(e, x);
115   }
116 }
117 
118 
119 /*
120  * Add n random equalities
121  */
add_eqs(th_explanation_t * e,uint32_t n)122 static void add_eqs(th_explanation_t *e, uint32_t n) {
123   int32_t x, y;
124 
125   while (n > 0) {
126     n --;
127     x = random() & 0x1f;
128     y = random() & 0x1f;
129     th_explanation_add_eq(e, x, y);
130   }
131 }
132 
133 
134 /*
135  * Force a duplicate (provided e has some equalities)
136  */
duplicate_eq(th_explanation_t * e)137 static void duplicate_eq(th_explanation_t *e) {
138   th_eq_t *eqs;
139   uint32_t i, n;
140   int32_t x, y;
141 
142   eqs = e->eqs;
143   if (eqs != NULL) {
144     n = get_eqv_size(eqs);
145     if (n > 0) {
146       i = random() % n;
147       x = eqs[i].lhs;
148       y = eqs[i].rhs;
149       printf("  duplicate: (t%"PRId32" = t%"PRId32")\n", y, x);
150       th_explanation_add_eq(e, y, x);
151     }
152   }
153 }
154 
duplicate_eqs(th_explanation_t * e,uint32_t n)155 static void duplicate_eqs(th_explanation_t *e, uint32_t n) {
156   while (n > 0) {
157     n --;
158     duplicate_eq(e);
159   }
160 }
161 
162 
163 /*
164  * Random test with na = number of atoms, ne = number of equalities
165  */
random_test(th_explanation_t * e,uint32_t na,uint32_t ne)166 static void random_test(th_explanation_t *e, uint32_t na, uint32_t ne) {
167   printf("==== Random test ====\n");
168   add_atoms(e, na);
169   add_eqs(e, ne);
170   duplicate_eqs(e, 4);
171   show_th_explanation(e);
172   cleanup_th_explanation(e);
173   printf("After cleanup:\n");
174   show_th_explanation(e);
175   printf("\n");
176   reset_th_explanation(e);
177 }
178 
179 
180 /*
181  * Special cases for testing sort eqs
182  */
constant_test(th_explanation_t * e,uint32_t n)183 static void constant_test(th_explanation_t *e, uint32_t n) {
184   int32_t x, y;
185 
186   x = random() & 0x1f;
187   y = random() & 0x1f;
188   while (n > 0) {
189     n --;
190     th_explanation_add_eq(e, x, y);
191   }
192   printf("==== Constant test ====\n");
193   show_th_explanation(e);
194   cleanup_th_explanation(e);
195   printf("After cleanup:\n");
196   show_th_explanation(e);
197   printf("\n");
198   reset_th_explanation(e);
199 }
200 
decreasing_test(th_explanation_t * e,uint32_t n)201 static void decreasing_test(th_explanation_t *e, uint32_t n) {
202   int32_t x;
203 
204   x  = n + (((uint32_t) random()) & 0x1f);
205   while (n > 0) {
206     th_explanation_add_eq(e, n, x);
207     n --;
208   }
209 
210   printf("==== Decreasing test ====\n");
211   show_th_explanation(e);
212   cleanup_th_explanation(e);
213   printf("After cleanup:\n");
214   show_th_explanation(e);
215   printf("\n");
216   reset_th_explanation(e);
217 }
218 
increasing_test(th_explanation_t * e,uint32_t n)219 static void increasing_test(th_explanation_t *e, uint32_t n) {
220   uint32_t i;
221   int32_t x;
222 
223   x  = n + (((uint32_t) random()) & 0x1f);
224   for (i=1; i<=n; i++) {
225     th_explanation_add_eq(e, i, x);
226   }
227 
228   printf("==== Increasing test ====\n");
229   show_th_explanation(e);
230   cleanup_th_explanation(e);
231   printf("After cleanup:\n");
232   show_th_explanation(e);
233   printf("\n");
234   reset_th_explanation(e);
235 }
236 
237 
238 
main(void)239 int main(void) {
240   th_explanation_t test;
241   uint32_t i;
242 
243   init_th_explanation(&test);
244   for (i=10; i<50; i++) {
245     constant_test(&test, i);
246   }
247   delete_th_explanation(&test);
248 
249   init_th_explanation(&test);
250   for (i=10; i<50; i++) {
251     increasing_test(&test, i);
252   }
253   delete_th_explanation(&test);
254 
255   init_th_explanation(&test);
256   for (i=10; i<50; i++) {
257     decreasing_test(&test, i);
258   }
259   delete_th_explanation(&test);
260 
261   init_th_explanation(&test);
262   printf("==== Initialized ====\n");
263   show_th_explanation(&test);
264   for (i=0; i<20; i++) {
265     random_test(&test, 20, 0);
266   }
267   delete_th_explanation(&test);
268 
269   init_th_explanation(&test);
270   printf("==== Initialized ====\n");
271   show_th_explanation(&test);
272   for (i=0; i<20; i++) {
273     random_test(&test, 0, 20);
274   }
275   delete_th_explanation(&test);
276 
277   init_th_explanation(&test);
278   printf("==== Initialized ====\n");
279   show_th_explanation(&test);
280   for (i=0; i<30; i++) {
281     random_test(&test, 30, 30);
282   }
283   delete_th_explanation(&test);
284 
285   init_th_explanation(&test);
286   printf("==== Initialized ====\n");
287   show_th_explanation(&test);
288   for (i=0; i<40; i++) {
289     random_test(&test, 40, 40);
290   }
291   delete_th_explanation(&test);
292 
293   return 0;
294 }
295