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  * ATTEMPT TO LEARN CONSTRAINTS ON VARIABLES FROM CONDITIONAL DEFINITIONS
21  */
22 
23 #include <assert.h>
24 
25 #include "context/conditional_definitions.h"
26 #include "context/context_utils.h"
27 #include "terms/rba_buffer_terms.h"
28 #include "terms/term_manager.h"
29 #include "terms/term_utils.h"
30 #include "utils/memalloc.h"
31 #include "utils/ptr_array_sort2.h"
32 
33 
34 #define TRACE 0
35 
36 #if TRACE
37 
38 #include <stdio.h>
39 #include <inttypes.h>
40 
41 #include "io/term_printer.h"
42 
43 #endif
44 
45 
46 /*
47  * SET OF TERMS (BOOLEAN VARIABLES)
48  */
49 
50 /*
51  * We store sets of variables using harray_t.
52  * A set if represented as a sorted array of terms.
53  */
54 /*
55  * Check that array a of n term is sorted and has no duplicates
56  */
57 #ifndef NDEBUG
array_is_sorted(term_t * a,uint32_t n)58 static bool array_is_sorted(term_t *a, uint32_t n) {
59   uint32_t i;
60 
61   for (i=0; i+1<n; i++) {
62     if (a[i] >= a[i+1]) return false;
63   }
64   return true;
65 }
66 
vector_is_sorted(ivector_t * v)67 static bool vector_is_sorted(ivector_t *v) {
68   return array_is_sorted(v->data, v->size);
69 }
70 
harray_is_sorted(harray_t * a)71 static bool harray_is_sorted(harray_t *a) {
72   return array_is_sorted(a->data, a->nelems);
73 }
74 
75 #endif
76 
77 
78 /*
79  * Insert t into vector v
80  * - v is assumed sorted in increasing order
81  * - do nothing if t is already in v
82  */
add_var_to_vector(ivector_t * v,term_t t)83 static void add_var_to_vector(ivector_t *v, term_t t) {
84   uint32_t i, j, k;
85 
86   assert(vector_is_sorted(v));
87 
88   // binary search
89   i = 0;
90   j = v->size;
91   while (i < j) {
92     k = (i+j) >> 1; // (i+j) can't overflow since v->size <= MAX_IVECTOR_SIZE
93     assert(i <= k && k < j);
94     if (v->data[k] < t) {
95       i = k+1;
96     } else {
97       j = k;
98     }
99   }
100 
101   j = v->size;
102   if (i == j) {
103     // all elements are smaller than t
104     ivector_push(v, t);
105   } else {
106     assert(i < v->size && v->data[i] >= t);
107     if (v->data[i] > t) {
108       // insert t in v->data[i] and shift everything
109       ivector_push(v, 0); // make room
110       while (j > i) {
111 	v->data[j] = v->data[j-1];
112 	j --;
113       }
114       v->data[j] = t;
115     }
116   }
117 
118   assert(vector_is_sorted(v) && i < v->size && v->data[i] == t);
119 }
120 
121 
122 /*
123  * Add all elements of a to vector v:
124  * - we could use a merge here?
125  */
add_vars_to_vector(ivector_t * v,harray_t * a)126 static void add_vars_to_vector(ivector_t *v, harray_t *a) {
127   uint32_t i, n;
128 
129   assert(vector_is_sorted(v) && harray_is_sorted(a));
130 
131   n = a->nelems;
132   for (i=0; i<n; i++) {
133     add_var_to_vector(v, a->data[i]);
134   }
135 }
136 
137 
138 
139 /*
140  * Build sets
141  */
empty_set(int_array_hset_t * store)142 static harray_t *empty_set(int_array_hset_t *store) {
143   return int_array_hset_get(store, 0, NULL); // this returns a non-NULL harray
144 }
145 
singleton(int_array_hset_t * store,term_t t)146 static harray_t *singleton(int_array_hset_t *store, term_t t) {
147   assert(is_pos_term(t));
148   return int_array_hset_get(store, 1, &t);
149 }
150 
vector_to_set(int_array_hset_t * store,ivector_t * v)151 static harray_t *vector_to_set(int_array_hset_t *store, ivector_t *v) {
152   assert(vector_is_sorted(v));
153   return int_array_hset_get(store, v->size, v->data);
154 }
155 
156 
157 
158 
159 
160 
161 /*
162  * BOOLEAN CONDITIONS
163  */
164 
165 /*
166  * Initialize collect:
167  * - ctx = relevant context
168  * - store = hash_array structure
169  */
init_bool_var_collector(bool_var_collector_t * collect,context_t * ctx,int_array_hset_t * store)170 static void init_bool_var_collector(bool_var_collector_t *collect, context_t *ctx, int_array_hset_t *store) {
171   collect->ctx = ctx;
172   collect->terms = ctx->terms;
173   collect->store = store;
174   init_simple_cache(&collect->cache, 0);
175   init_pstack(&collect->stack);
176   init_ivector(&collect->buffer, 10);
177   collect->budget = 0;
178 }
179 
180 /*
181  * Free memory
182  */
delete_bool_var_collector(bool_var_collector_t * collect)183 static void delete_bool_var_collector(bool_var_collector_t *collect) {
184   delete_simple_cache(&collect->cache);
185   delete_pstack(&collect->stack);
186   delete_ivector(&collect->buffer);
187 }
188 
189 
190 /*
191  * Cache for bool_var_collector:
192  * - the value for a term index i is a pointer (to harray_t)
193  * - the value is NULL if i is not a pure Boolean term
194  * - otherwise the value is the set of Boolean variables occurring in i
195  */
cache_bool_var_set(bool_var_collector_t * collect,int32_t i,harray_t * a)196 static void cache_bool_var_set(bool_var_collector_t *collect, int32_t i, harray_t *a) {
197   assert(good_term_idx(collect->terms, i));
198   simple_cache_store_ptr(&collect->cache, i, 0, a); // tag = 0 (not used)
199 }
200 
201 
202 /*
203  * Check whether term t is purely Boolean and compute the set of variables
204  * - return NULL if t is not purely Boolean
205  * - return the set of variables of t otherwise
206  */
207 static harray_t *bool_vars_of_term(bool_var_collector_t *collect, term_t t);
208 
209 // recursively explore a composite term d
bool_vars_of_composite(bool_var_collector_t * collect,composite_term_t * d)210 static harray_t *bool_vars_of_composite(bool_var_collector_t *collect, composite_term_t *d) {
211   void **a;
212   harray_t *set;
213   ivector_t *v;
214   uint32_t i, n;
215 
216   set = NULL;
217 
218   n = d->arity;
219   a = alloc_pstack_array(&collect->stack, n);
220   for (i=0; i<n; i++) {
221     a[i] = bool_vars_of_term(collect, d->arg[i]);
222     if (a[i] == NULL) goto done;
223   }
224 
225   // compute the union of a[0 ... n-1]
226   v = &collect->buffer;
227   assert(v->size == 0);
228   for (i=0; i<n; i++) {
229     add_vars_to_vector(v, a[i]);
230   }
231   set = vector_to_set(collect->store, v);
232   ivector_reset(v);
233 
234  done:
235   free_pstack_array(&collect->stack, a);
236   return set;
237 }
238 
239 
bool_vars_of_term(bool_var_collector_t * collect,term_t t)240 static harray_t *bool_vars_of_term(bool_var_collector_t *collect, term_t t) {
241   context_t *ctx;
242   term_table_t *terms;
243   simple_cache_entry_t *e;
244   harray_t *set;
245   composite_term_t *eq;
246   term_t r;
247   int32_t i;
248 
249   assert(is_boolean_term(collect->terms, t));
250 
251   set = NULL;
252 
253   if (collect->budget > 0) {
254     collect->budget --;
255 
256     ctx = collect->ctx;
257     r = intern_tbl_get_root(&ctx->intern, t);
258     if (term_is_true(ctx, r) || term_is_false(ctx, r)) {
259       set = empty_set(collect->store);
260 
261     } else {
262 
263       i = index_of(r);
264       assert(good_term_idx(collect->terms, i));
265 
266       terms = collect->terms;
267       switch (kind_for_idx(terms, i)) {
268       case UNINTERPRETED_TERM:
269 	set = singleton(collect->store, pos_occ(i));
270 	break;
271 
272       case ITE_TERM:
273       case ITE_SPECIAL:
274       case OR_TERM:
275       case XOR_TERM:
276 	e = simple_cache_find(&collect->cache, i);
277 	if (e != NULL) {
278 	  assert(e->key == i && e->tag == 0);
279 	  set =  e->val.ptr;
280 	} else {
281 	  set = bool_vars_of_composite(collect, composite_for_idx(terms, i));
282 	  cache_bool_var_set(collect, i, set);
283 	}
284 	break;
285 
286       case EQ_TERM:
287 	eq = composite_for_idx(terms, i);
288 	if (is_boolean_term(terms, eq->arg[0])) {
289 	  // treat i as (IFF t1 t2)
290 	  e = simple_cache_find(&collect->cache, i);
291 	  if (e != NULL) {
292 	    assert(e->key == i && e->tag == 0);
293 	    set =  e->val.ptr;
294 	  } else {
295 	    set = bool_vars_of_composite(collect, eq);
296 	    cache_bool_var_set(collect, i, set);
297 	  }
298 	}
299 	break;
300 
301       default:
302 	// not a pure Boolean term
303 	break;
304       }
305     }
306   }
307 
308   return set;
309 }
310 
311 
312 /*
313  * Check whether t is purely Boolean
314  * - set a budget of 100 = max number of recursive calls to bool_vars_of_term
315  */
bool_term_is_pure(bool_var_collector_t * collect,term_t t)316 static bool bool_term_is_pure(bool_var_collector_t *collect, term_t t) {
317   collect->budget = 100;
318   return bool_vars_of_term(collect, t) != NULL;
319 }
320 
321 
322 /*
323  * Collect the variables of t when t is known to be small and pure Boolean
324  */
get_bool_vars_of_term(bool_var_collector_t * collect,term_t t)325 static harray_t *get_bool_vars_of_term(bool_var_collector_t *collect, term_t t) {
326   collect->budget = UINT32_MAX;
327   return bool_vars_of_term(collect, t);
328 }
329 
330 
331 
332 /*
333  * CONDITIONAL DEFINITIONS
334  */
335 
336 /*
337  * Create a conditional definition descriptor:
338  * - t = term
339  * - v = value
340  * - vset = set of variables
341  * - n = number of conditions
342  * - a[0 ... n-1] = conditions
343  */
new_cond_def(term_t t,term_t v,harray_t * vset,uint32_t n,term_t * a)344 static cond_def_t *new_cond_def(term_t t, term_t v, harray_t *vset, uint32_t n, term_t *a) {
345   cond_def_t *tmp;
346   uint32_t i;
347 
348   assert(n <= MAX_COND_DEF_CONJUNCTS);
349   tmp = (cond_def_t *) safe_malloc(sizeof(cond_def_t) + n * sizeof(term_t));
350   tmp->term = t;
351   tmp->value = v;
352   tmp->vset = vset;
353   tmp->nconds = n;
354   for (i=0; i<n; i++) {
355     tmp->cond[i] = a[i];
356   }
357   return tmp;
358 }
359 
360 
361 
362 /*
363  * Initialize a collector
364  * - ctx = relevant context
365  */
init_cond_def_collector(cond_def_collector_t * c,context_t * ctx)366 void init_cond_def_collector(cond_def_collector_t *c, context_t *ctx) {
367   uint32_t i;
368 
369   c->ctx = ctx;
370   c->terms = ctx->terms;
371   init_pvector(&c->cdefs, 0);
372   init_int_array_hset(&c->store, 0);
373   init_bool_var_collector(&c->collect, ctx, &c->store);
374   init_simple_cache(&c->cache, 0);
375   init_ivector(&c->assumptions, 10);
376   init_ivector(&c->aux, 10);
377 
378   for (i=0; i<6; i++) {
379     q_init(c->coeff + i);
380   }
381   q_init(&c->base);
382   q_init(&c->q_aux);
383 }
384 
385 
386 /*
387  * Delete: free all memory
388  */
delete_cond_def_collector(cond_def_collector_t * c)389 void delete_cond_def_collector(cond_def_collector_t *c) {
390   uint32_t i, n;
391 
392   n = c->cdefs.size;
393   for (i=0; i<n; i++) {
394     safe_free(c->cdefs.data[i]);
395   }
396   delete_pvector(&c->cdefs);
397   delete_bool_var_collector(&c->collect);
398   delete_simple_cache(&c->cache);
399   delete_int_array_hset(&c->store);
400   delete_ivector(&c->assumptions);
401   delete_ivector(&c->aux);
402 
403   for (i=0; i<6; i++) {
404     q_clear(c->coeff + i);
405   }
406   q_clear(&c->base);
407   q_clear(&c->q_aux);
408 }
409 
410 
411 /*
412  * Add a conditional definition to c
413  */
add_cond_def(cond_def_collector_t * c,cond_def_t * def)414 static inline void add_cond_def(cond_def_collector_t *c, cond_def_t *def) {
415   assert(def != NULL);
416   pvector_push(&c->cdefs, def);
417 }
418 
419 
420 #if TRACE
421 
422 /*
423  * For testing: print def
424  */
print_cond_def(cond_def_collector_t * c,cond_def_t * def)425 static void print_cond_def(cond_def_collector_t *c, cond_def_t *def) {
426   yices_pp_t pp;
427   pp_area_t area;
428   uint32_t i, n;
429 
430   area.width = 400;
431   area.height = 300;
432   area.offset = 0;
433   area.stretch = false;
434   area.truncate = true;
435   init_default_yices_pp(&pp, stdout, &area);
436 
437   pp_open_block(&pp, PP_OPEN);
438   pp_open_block(&pp, PP_OPEN_IMPLIES);
439   n = def->nconds;
440   if (n > 1) pp_open_block(&pp, PP_OPEN_AND);
441   for (i=0; i<n; i++) {
442     pp_term_full(&pp, c->terms, def->cond[i]);
443   }
444   if (n > 1) pp_close_block(&pp, true); // close and
445   pp_open_block(&pp, PP_OPEN_EQ);
446   pp_term_full(&pp, c->terms, def->term);
447   pp_term_full(&pp, c->terms, def->value);
448   pp_close_block(&pp, true); // close eq
449   pp_close_block(&pp, true); // close implies
450   pp_close_block(&pp, false);
451 
452   delete_yices_pp(&pp, true);
453 }
454 
455 
456 /*
457  * For testing: print the variables in s
458  */
print_vset(cond_def_collector_t * c,harray_t * s)459 static void print_vset(cond_def_collector_t *c, harray_t *s) {
460   uint32_t i, n;
461 
462   n = s->nelems;
463   for (i=0; i<n; i++) {
464     if (i > 0) printf(" ");
465     print_term_full(stdout, c->terms, s->data[i]);
466   }
467 }
468 
469 
470 
471 #if 0
472 /*
473  * For testing: print a truth table
474  * - ttbl = 64bit encoding for the table
475  * - x[0 ... n-1] = Boolean variables in increasing order
476  */
477 static void print_truth_tbl(cond_def_collector_t *c, uint64_t ttbl, term_t *x, uint32_t n) {
478   uint32_t i, k, max_k;
479   uint64_t mask, bit;
480 
481   assert(array_is_sorted(x, n) && n <= 6);
482 
483   for (i=0; i<n; i++) {
484     assert(is_boolean_term(c->terms, x[i]) &&
485 	   is_pos_term(x[i]) &&
486 	   term_kind(c->terms, x[i]) == UNINTERPRETED_TERM);
487 
488     printf("  %6s", term_name(c->terms, x[i]));
489   }
490   printf("\n");
491 
492   max_k = (1 << n); // 2^n
493   assert(max_k <= 64);
494   mask = 1;  // select bit 0 of ttbl
495 
496   for (k=0; k<max_k; k++) {
497     for (i=0; i<n; i++) {
498       bit = (k & (1 << i));
499       assert(bit == 0 || bit == (1 << i));
500       if (bit == 0) {
501 	printf("  %6s", "0");
502       } else {
503 	printf("  %6s", "1");
504       }
505     }
506     bit = (ttbl & mask);
507     assert(bit == 0 || bit == mask);
508     if (bit == 0) {
509       printf("  |    0\n");
510     } else {
511       printf("  |    1\n");
512     }
513     mask <<= 1;
514   }
515 
516   printf("\n");
517 }
518 #endif
519 
520 /*
521  * For testing: print a definition table
522  * - table = 64bit encoding for the table
523  * - x[0 ... n-1] = Boolean variables in increasing order
524  */
print_definition_table(cond_def_collector_t * c,term_t * table,term_t * x,uint32_t n)525 static void print_definition_table(cond_def_collector_t *c, term_t *table, term_t *x, uint32_t n) {
526   uint32_t i, k, max_k;
527   uint64_t bit;
528 
529   assert(array_is_sorted(x, n) && n <= 6);
530 
531   for (i=0; i<n; i++) {
532     assert(is_boolean_term(c->terms, x[i]) &&
533 	   is_pos_term(x[i]) &&
534 	   term_kind(c->terms, x[i]) == UNINTERPRETED_TERM);
535 
536     printf("  %6s", term_name(c->terms, x[i]));
537   }
538   printf("\n");
539 
540   max_k = (1 << n); // 2^n
541   assert(max_k <= 64);
542 
543   for (k=0; k<max_k; k++) {
544     for (i=0; i<n; i++) {
545       bit = (k & (1 << i));
546       assert(bit == 0 || bit == (1 << i));
547       if (bit == 0) {
548 	printf("  %6s", "0");
549       } else {
550 	printf("  %6s", "1");
551       }
552     }
553     printf("   |   ");
554     if (table[k] == NULL_TERM) {
555       printf("unknown");
556     } else if (table[k] == -2) {
557       printf("conflict");
558     } else {
559       print_term_full(stdout, c->terms, table[k]);
560     }
561     printf("\n");
562   }
563 
564   printf("\n");
565 }
566 
567 
print_candidate(cond_def_collector_t * c,harray_t * s)568 static void print_candidate(cond_def_collector_t *c, harray_t *s) {
569   uint32_t i, n;
570   rational_t *q;
571 
572   n = s->nelems;
573   assert(n <= 6);
574 
575   q_print(stdout, &c->base);
576   for (i=0; i<n; i++) {
577     q = c->coeff + i;
578     printf(" + (");
579     q_print(stdout, q);
580     printf(" %s)", term_name(c->terms, s->data[i]));
581   }
582   printf("\n");
583 }
584 
585 #endif
586 
587 
588 /*
589  * CONVERSION OF ASSERTIONS TO CONDITIONAL DEFINITIONS
590  */
591 
592 /*
593  * Add t as an assumption: follow the internalization table
594  */
push_assumption(cond_def_collector_t * c,term_t t)595 static void push_assumption(cond_def_collector_t *c, term_t t) {
596   context_t *ctx;
597 
598   ctx = c->ctx;
599   t = intern_tbl_get_root(&ctx->intern, t);
600   if (term_is_true(ctx, t)) {
601     t = true_term;
602   } else if (term_is_false(ctx, t)) {
603     t = false_term;
604   }
605   ivector_push(&c->assumptions, t);
606 }
607 
608 
609 /*
610  * Compute the set of variables occurring in a[0 ... n-1]
611  * - a[0 ... n-1] must all be pure Boolean terms
612  */
bool_vars_of_array(cond_def_collector_t * c,uint32_t n,term_t * a)613 static harray_t *bool_vars_of_array(cond_def_collector_t *c, uint32_t n, term_t *a) {
614   ivector_t *v;
615   harray_t *s;
616   uint32_t i;
617 
618   if (n == 0) {
619     s = empty_set(&c->store);
620   } else if (n == 1) {
621     s = get_bool_vars_of_term(&c->collect, a[0]);
622   } else {
623     v = &c->aux;
624     assert(v->size == 0);
625     for (i=0; i<n; i++) {
626       s = get_bool_vars_of_term(&c->collect, a[i]);
627       add_vars_to_vector(v, s);
628     }
629     assert(vector_is_sorted(v));
630     s = int_array_hset_get(&c->store, v->size, v->data);
631     ivector_reset(v);
632   }
633 
634   return s;
635 }
636 
637 
638 /*
639  * Attempts to convert a formula of the form (assumptions => f) to
640  * conditional definitions.
641  * - the assumptions are stored in c->assumption vector
642  * - f = term to explore
643  */
644 static void cond_def_explore(cond_def_collector_t *c, term_t f);
645 
646 
647 /*
648  * Explore (or t1 ... tn)
649  * - if polarity is true, this is processed as (or t1 ... tn)
650  * - if polarity is false, this is processed (and (not t1) ... (not t_n))
651  */
cond_def_explore_or(cond_def_collector_t * c,composite_term_t * or,bool polarity)652 static void cond_def_explore_or(cond_def_collector_t *c, composite_term_t *or, bool polarity) {
653   uint32_t i, n, num_assumptions;
654   term_t t, u;
655 
656   n = or->arity;
657   if (polarity) {
658     num_assumptions = c->assumptions.size;
659 
660     /*
661      * Check whether all t_i's but one are pure Boolean.
662      */
663     u = NULL_TERM;
664     for (i=0; i<n; i++) {
665       t = or->arg[i];
666       if (bool_term_is_pure(&c->collect, t)) {
667 	// add (not t) as an assumption
668 	push_assumption(c, opposite_term(t));
669       } else {
670 	if (u != NULL_TERM) {
671 	  // we can't convert the or to a conditional definition
672 	  goto abort;
673 	}
674 	u = t;
675       }
676     }
677 
678     /*
679      * u is the unique sub-term that's not purely Boolean
680      * the other subterms are in the assumption vector
681      * we recursively process u.
682      */
683     if (u != NULL_TERM) {
684       cond_def_explore(c, u);
685     }
686 
687   abort:
688     // restore the assumption stack
689     ivector_shrink(&c->assumptions, num_assumptions);
690 
691 
692   } else {
693     /*
694      * Assumptions => (and (not t1) ... (not t_n))
695      */
696     for (i=0; i<n; i++) {
697       cond_def_explore(c, opposite_term(or->arg[i]));
698     }
699   }
700 }
701 
702 
703 /*
704  * Explore (ite c t1 2)
705  * - if polarity is true, this is processed as (c => t1) AND (not(c) => t2)
706  * - otherwise, it's processed as (c => not(t1)) AND (not c => not(t2))
707  */
cond_def_explore_ite(cond_def_collector_t * c,composite_term_t * ite,bool polarity)708 static void cond_def_explore_ite(cond_def_collector_t *c, composite_term_t *ite, bool polarity) {
709   term_t cond;
710 
711   assert(ite->arity == 3);
712   cond = ite->arg[0];
713   if (bool_term_is_pure(&c->collect, cond)) {
714     push_assumption(c, cond);
715     cond_def_explore(c, signed_term(ite->arg[1], polarity));
716     ivector_pop(&c->assumptions);
717 
718     push_assumption(c, opposite_term(cond));
719     cond_def_explore(c, signed_term(ite->arg[2], polarity));
720     ivector_pop(&c->assumptions);
721   }
722 }
723 
724 
cond_def_explore(cond_def_collector_t * c,term_t f)725 static void cond_def_explore(cond_def_collector_t *c, term_t f) {
726   term_table_t *terms;
727   cond_def_t *def;
728   harray_t *set;
729   term_t x, a;
730 
731   terms = c->terms;
732   switch (term_kind(terms, f)) {
733   case OR_TERM:
734     cond_def_explore_or(c, or_term_desc(terms, f), is_pos_term(f));
735     break;
736 
737   case ITE_TERM:
738   case ITE_SPECIAL:
739     cond_def_explore_ite(c, ite_term_desc(terms, f), is_pos_term(f));
740     break;
741 
742   default:
743     //    if (is_term_eq_const(terms, f, &x, &a)) {
744     if (is_unint_eq_const(terms, f, &x, &a)) {
745       if (c->assumptions.size <= MAX_COND_DEF_CONJUNCTS) {
746 	set = bool_vars_of_array(c, c->assumptions.size, c->assumptions.data);
747 	/*
748 	 * If set is empty, we ignore this definition: either the assumptions
749 	 * are all true or all false. In either case, normal internalization
750 	 * will process (x == a) or ignore it.
751 	 */
752 	if (set->nelems > 0) {
753 	  def = new_cond_def(x, a, set, c->assumptions.size, c->assumptions.data);
754 	  add_cond_def(c, def);
755 	}
756       }
757     }
758     break;
759   }
760 }
761 
762 
763 /*
764  * Attempt to convert f to a conjunction of conditional definitions
765  * - id = index to identify f
766  * - add the definitions to c->cdefs
767  */
extract_conditional_definitions(cond_def_collector_t * c,term_t f)768 void extract_conditional_definitions(cond_def_collector_t *c, term_t f) {
769   ivector_reset(&c->assumptions);
770   cond_def_explore(c, f);
771 }
772 
773 
774 /*
775  * TRUTH TABLES
776  */
777 
778 /*
779  * Given a term t that's a Boolean combination of n variables x[0] ... x[n-1],
780  * we can encode the truth table for t as a bit-vector of 2^n elements.
781  * We limit this to n <= 6, then we can represent the truth table as an unsigned
782  * 64 bit integer.
783  *
784  * For example, if n=3 the truth table for t will look like
785  *
786  *     x[2]   x[1]   x[0]   |  t
787  *   ------------------------------
788  *       0      0      0    |  t_0
789  *       0      0      1    |  t_1
790  *       0      1      0    |  t_2
791  *       0      1      1    |  t_3
792  *       1      0      0    |  t_4
793  *       1      0      1    |  t_5
794  *       1      1      0    |  t_6
795  *       1      1      1    |  t_7
796  *
797  * The truth table for t is then 8 word [t_7 t_6 ... t_0] (from high-order
798  * to low-order). We extend it to 64 bit by repeating this pattern 8 times.
799  *
800  * All functions below compute the truth-table for a term t, assuming a fixed
801  * set of Boolean variables x[0 ... n-1] (with n <= 6). The variables are
802  * sorted in increasing order and are all distinct.
803  */
804 
805 
806 /*
807  * Constant arrays: truth tables for variables x[0 ... 5]
808  */
809 static const uint64_t truth_tbl_var[6] = {
810   0xAAAAAAAAAAAAAAAAULL,  // 1010 1010 1010 1010 1010 1010 1010 1010 ...
811   0xCCCCCCCCCCCCCCCCULL,  // 1100 1100 1100 1100 1100 1100 1100 1100 ...
812   0xF0F0F0F0F0F0F0F0ULL,  // 1111 0000 1111 0000 1111 0000 1111 0000 ...
813   0xFF00FF00FF00FF00ULL,  // 1111 1111 0000 0000 1111 1111 0000 0000 ...
814   0xFFFF0000FFFF0000ULL,  // 1111 1111 1111 1111 0000 0000 0000 0000 ..
815   0xFFFFFFFF00000000ULL,
816 };
817 
818 
819 /*
820  * Main procedure: recursively compute the truth table of t
821  * - t must be a pure Boolean term
822  * - the variables of t must be included in { x[0] ... x[n-1] }
823  * - n must be no more than 6
824  */
825 static uint64_t truth_tbl_of_term(cond_def_collector_t *c, term_t t, term_t *x, uint32_t n);
826 
827 /*
828  * Truth table for a variable t
829  * - t must be present in x[0 ... n-1]
830  */
truth_tbl_of_var(term_t t,term_t * x,uint32_t n)831 static uint64_t truth_tbl_of_var(term_t t, term_t *x, uint32_t n) {
832   uint32_t i;
833 
834   assert(is_pos_term(t) && array_is_sorted(x, n) && n <= 6);
835 
836   for (i=0; i<n; i++) {
837     if (t == x[i]) break;
838   }
839   assert(i < n);
840 
841   return truth_tbl_var[i];
842 }
843 
844 
845 /*
846  * Store truth table of idx in c->cache
847  */
cache_truth_tbl(cond_def_collector_t * c,int32_t idx,uint64_t ttbl)848 static void cache_truth_tbl(cond_def_collector_t *c, int32_t idx, uint64_t ttbl) {
849   assert(good_term_idx(c->terms, idx));
850   simple_cache_store_u64(&c->cache, idx, 0x1a, ttbl); // tag = 0x1a (could be anything)
851 }
852 
853 /*
854  * Recursive computation for composite terms:
855  * - idx is a valid term index in the term table
856  * - we use c->cache to avoid blowing up
857  */
truth_tbl_of_ite(cond_def_collector_t * c,int32_t idx,term_t * x,uint32_t n)858 static uint64_t truth_tbl_of_ite(cond_def_collector_t *c, int32_t idx, term_t *x, uint32_t n) {
859   simple_cache_entry_t *e;
860   composite_term_t *ite;
861   uint64_t tc, ta, tb, r;
862 
863   assert(kind_for_idx(c->terms, idx) == ITE_TERM ||
864 	 kind_for_idx(c->terms, idx) == ITE_SPECIAL);
865 
866   e = simple_cache_find(&c->cache, idx);
867   if (e != NULL) {
868     assert(e->key == idx && e->tag == 0x1a);
869     return e->val.u64;
870   }
871 
872   ite = composite_for_idx(c->terms, idx);
873   assert(ite->arity == 3);
874 
875   tc = truth_tbl_of_term(c, ite->arg[0], x, n); // condition
876   ta = truth_tbl_of_term(c, ite->arg[1], x, n); // then part
877   tb = truth_tbl_of_term(c, ite->arg[2], x, n); // else part
878   r = (tc & ta) | (~tc & tb);
879 
880   cache_truth_tbl(c, idx, r);
881 
882   return r;
883 }
884 
truth_tbl_of_or(cond_def_collector_t * c,int32_t idx,term_t * x,uint32_t n)885 static uint64_t truth_tbl_of_or(cond_def_collector_t *c, int32_t idx, term_t *x, uint32_t n) {
886   simple_cache_entry_t *e;
887   composite_term_t *or;
888   uint64_t r;
889   uint32_t i, m;
890 
891   assert(kind_for_idx(c->terms, idx) == OR_TERM);
892 
893   e = simple_cache_find(&c->cache, idx);
894   if (e != NULL) {
895     assert(e->key == idx && e->tag == 0x1a);
896     return e->val.u64;
897   }
898 
899   r = 0;
900   or = composite_for_idx(c->terms, idx);
901   m = or->arity;
902   for (i=0; i<m; i++) {
903     r |= truth_tbl_of_term(c, or->arg[i], x, n);
904   }
905 
906   cache_truth_tbl(c, idx, r);
907 
908   return r;
909 }
910 
truth_tbl_of_xor(cond_def_collector_t * c,int32_t idx,term_t * x,uint32_t n)911 static uint64_t truth_tbl_of_xor(cond_def_collector_t *c, int32_t idx, term_t *x, uint32_t n) {
912   simple_cache_entry_t *e;
913   composite_term_t *xor;
914   uint64_t r;
915   uint32_t i, m;
916 
917   assert(kind_for_idx(c->terms, idx) == XOR_TERM);
918 
919   e = simple_cache_find(&c->cache, idx);
920   if (e != NULL) {
921     assert(e->key == idx && e->tag == 0x1a);
922     return e->val.u64;
923   }
924 
925   r = 0;
926   xor = composite_for_idx(c->terms, idx);
927   m = xor->arity;
928   for (i=0; i<m; i++) {
929     r ^= truth_tbl_of_term(c, xor->arg[i], x, n);
930   }
931 
932   cache_truth_tbl(c, idx, r);
933 
934   return r;
935 }
936 
truth_tbl_of_iff(cond_def_collector_t * c,int32_t idx,term_t * x,uint32_t n)937 static uint64_t truth_tbl_of_iff(cond_def_collector_t *c, int32_t idx, term_t *x, uint32_t n) {
938   simple_cache_entry_t *e;
939   composite_term_t *iff;
940   uint64_t ta, tb, r;
941 
942   assert(kind_for_idx(c->terms, idx) == EQ_TERM);
943 
944   e = simple_cache_find(&c->cache, idx);
945   if (e != NULL) {
946     assert(e->key == idx && e->tag == 0x1a);
947     return e->val.u64;
948   }
949 
950   iff = composite_for_idx(c->terms, idx);
951   assert(iff->arity == 2);
952 
953   ta = truth_tbl_of_term(c, iff->arg[0], x, n);
954   tb = truth_tbl_of_term(c, iff->arg[1], x, n);
955   r = ~(ta ^ tb); // not xor
956 
957   cache_truth_tbl(c, idx, r);
958 
959   return r;
960 }
961 
truth_tbl_of_term(cond_def_collector_t * c,term_t t,term_t * x,uint32_t n)962 static uint64_t truth_tbl_of_term(cond_def_collector_t *c, term_t t, term_t *x, uint32_t n) {
963   context_t *ctx;
964   term_table_t *terms;
965   uint64_t ttbl;
966   term_t r;
967   int32_t i;
968 
969   assert(is_boolean_term(c->terms, t));
970 
971   ctx = c->ctx;
972   r = intern_tbl_get_root(&ctx->intern, t);
973   if (term_is_true(ctx, r)) {
974     return 0xFFFFFFFFFFFFFFFFULL; // all true
975   }
976 
977   if (term_is_false(ctx, r)) {
978     return 0x0000000000000000ULL; // all false
979   }
980 
981   i = index_of(r);
982   terms = c->terms;
983 
984   assert(good_term_idx(c->terms, i));
985 
986   switch (kind_for_idx(terms, i)) {
987   case UNINTERPRETED_TERM:
988     ttbl = truth_tbl_of_var(pos_occ(i), x, n);
989     break;
990 
991   case ITE_TERM:
992   case ITE_SPECIAL:
993     ttbl = truth_tbl_of_ite(c, i, x, n);
994     break;
995 
996   case OR_TERM:
997     ttbl = truth_tbl_of_or(c, i, x, n);
998     break;
999 
1000   case XOR_TERM:
1001     ttbl = truth_tbl_of_xor(c, i, x, n);
1002     break;
1003 
1004   case EQ_TERM:
1005     // this must be an equality between Boolean terms
1006     ttbl = truth_tbl_of_iff(c, i, x, n);
1007     break;
1008 
1009   default:
1010     // this should not happen. t is a pure Boolean term
1011     assert(false);
1012     ttbl = 0; // prevent a GCC warning
1013     break;
1014   }
1015 
1016   /*
1017    * ttbl is the truth table for i.
1018    * if  r is not(i), we flip all bits
1019    */
1020   if (is_neg_term(r)) {
1021     ttbl = ~ttbl;
1022   }
1023 
1024   return ttbl;
1025 }
1026 
1027 
1028 /*
1029  * Truth table for the conjunction (a[0] /\ ... /\ a[m-1])
1030  */
truth_tbl_of_array(cond_def_collector_t * c,uint32_t m,term_t * a,term_t * x,uint32_t n)1031 static uint64_t truth_tbl_of_array(cond_def_collector_t *c, uint32_t m, term_t *a, term_t *x, uint32_t n) {
1032   uint64_t r;
1033   uint32_t i;
1034 
1035   r = 0xFFFFFFFFFFFFFFFFULL;
1036   for (i=0; i<m; i++) {
1037     r &= truth_tbl_of_term(c, a[i], x, n);
1038   }
1039 
1040   return r;
1041 }
1042 
1043 
1044 /*
1045  * Test row k of the truth table ttbl
1046  * - k must be between 0 and 63
1047  */
truth_tbl_test_row(uint64_t ttbl,uint32_t k)1048 static bool truth_tbl_test_row(uint64_t ttbl, uint32_t k) {
1049   uint64_t mask;
1050 
1051   assert(k < 64);
1052   mask = ((uint64_t) 1) << k;
1053   return (ttbl & mask) != 0;
1054 }
1055 
1056 
1057 /*
1058  * ANALYSIS OF CONDITIONAL DEFINITIONS
1059  */
1060 
1061 /*
1062  * Check whether t < u
1063  * - both must be arithmetic constants (rationals)
1064  */
arith_lt(term_table_t * tbl,term_t t,term_t u)1065 static bool arith_lt(term_table_t *tbl, term_t t, term_t u) {
1066   return q_lt(rational_term_desc(tbl, t), rational_term_desc(tbl, u));
1067 }
1068 
1069 /*
1070  * Copy the value of term t into q
1071  * - t must be an arithmetic constant
1072  */
copy_rational_term(term_table_t * terms,rational_t * q,term_t t)1073 static void copy_rational_term(term_table_t *terms, rational_t *q, term_t t) {
1074   q_set(q, rational_term_desc(terms, t));
1075 }
1076 
1077 /*
1078  * Check whether t's value equals q
1079  */
rational_eq_term(term_table_t * terms,rational_t * q,term_t t)1080 static bool rational_eq_term(term_table_t *terms, rational_t *q, term_t t) {
1081   return q_eq(q, rational_term_desc(terms, t));
1082 }
1083 
1084 
1085 /*
1086  * Add aux atom t <= u in the context.
1087  * - both t and u must be arithmetic terms
1088  */
add_le_atom(context_t * ctx,term_t t,term_t u)1089 static void add_le_atom(context_t *ctx, term_t t, term_t u) {
1090   rba_buffer_t *b;
1091   term_t a;
1092 
1093   assert(is_pos_term(t) && is_arithmetic_term(ctx->terms, t));
1094   assert(is_pos_term(u) && is_arithmetic_term(ctx->terms, u));
1095 
1096   b = context_get_arith_buffer(ctx);
1097   assert(b != NULL && rba_buffer_is_zero(b));
1098   rba_buffer_add_term(b, ctx->terms, t);
1099   rba_buffer_sub_term(b, ctx->terms, u);   // b is t - u
1100   a = mk_direct_arith_leq0(ctx->terms, b, true); // a is (t - u <= 0)
1101 
1102   add_aux_atom(ctx, a);
1103 
1104 #if TRACE
1105   printf("Adding atom: ");
1106   pretty_print_term_full(stdout, NULL, ctx->terms, a);
1107 #endif
1108 
1109   trace_puts(ctx->trace, 5, "Adding atom\n");
1110   trace_pp_term(ctx->trace, 5, ctx->terms, a);
1111 }
1112 
1113 
1114 /*
1115  * Table[0 ... k_max-1] contains a set of constants that are
1116  * all the possible values of term x.
1117  * - x is an arithmetic term
1118  * - find minimal and maximal element in table then assert
1119  *   min <= x <= max
1120  * - skip any table[i] that's not a valid term
1121  */
assert_arith_bounds_from_table(cond_def_collector_t * c,term_t x,uint32_t k_max,term_t * table)1122 static void assert_arith_bounds_from_table(cond_def_collector_t *c, term_t x, uint32_t k_max, term_t *table) {
1123   term_table_t *terms;
1124   term_t min, max, t;
1125   uint32_t i;
1126 
1127   min = NULL_TERM;
1128   max = NULL_TERM;
1129   terms = c->terms;
1130 
1131   assert(is_arithmetic_term(terms, x));
1132 
1133   for (i=0; i<k_max; i++) {
1134     t = table[i];
1135     if (t >= 0) {
1136       assert(term_kind(terms, t) == ARITH_CONSTANT);
1137       if (min < 0) {
1138 	assert(max < 0);
1139 	min = t;
1140 	max = t;
1141       } else {
1142 	if (arith_lt(terms, t, min)) {
1143 	  min = t;
1144 	}
1145 	if (arith_lt(terms, max, t)) {
1146 	  max = t;
1147 	}
1148       }
1149     }
1150   }
1151 
1152   if (min >= 0) {
1153     assert(term_kind(terms, min) == ARITH_CONSTANT &&
1154 	   term_kind(terms, max) == ARITH_CONSTANT &&
1155 	   q_le(rational_term_desc(terms, min), rational_term_desc(terms, max)));
1156 
1157     add_le_atom(c->ctx, min, x);
1158     add_le_atom(c->ctx, x, max);
1159   }
1160 }
1161 
1162 /*
1163  * Store table[0] in c->base
1164  * Then the coefficients for each variables in c->coeff[0 ... n-1]
1165  */
build_candidate(cond_def_collector_t * c,uint32_t n,term_t * table)1166 static void build_candidate(cond_def_collector_t *c, uint32_t n, term_t *table) {
1167   uint32_t i, k;
1168 
1169   assert(n <= 6);
1170 
1171   copy_rational_term(c->terms, &c->base, table[0]);
1172 
1173   k = 1;
1174   for (i=0; i<n; i++) {
1175     copy_rational_term(c->terms, c->coeff + i, table[k]);
1176     q_sub(c->coeff + i, &c->base);   // coeff[i] := table[2^i] - table[0]
1177     k <<= 1;
1178   }
1179 }
1180 
1181 
1182 /*
1183  * The candidate linear expression is
1184  * b + c[0] x[0] + ... + c[n-1] x[n-1]
1185  * where b = c->base, c[i] = c->coeff[i] and x[i] = Boolean variable.
1186  *
1187  * This function evaluate the expression for the Boolean assignment defined by index m:
1188  * - bit i of m = value of x[i]
1189  * The result is stored in c->q_aux
1190  */
eval_candidate(cond_def_collector_t * c,uint32_t n,uint32_t m)1191 static void eval_candidate(cond_def_collector_t *c, uint32_t n, uint32_t m) {
1192   rational_t *q;
1193   uint32_t i, k;
1194 
1195   assert(n <= 6);
1196 
1197   q = &c->q_aux;
1198   q_set(q, &c->base);
1199 
1200   k = 1;
1201   for (i=0; i<n; i++) {
1202     // k is 2^i, k&m is bit i of m
1203     if ((k & m) != 0) {
1204       q_add(q, c->coeff + i);
1205     }
1206     k <<= 1;
1207   }
1208 }
1209 
1210 
1211 /*
1212  * Check that the candidate expression agrees with the full table
1213  */
candidate_is_good(cond_def_collector_t * c,uint32_t n,uint32_t k_max,term_t * table)1214 static bool candidate_is_good(cond_def_collector_t *c, uint32_t n, uint32_t k_max, term_t *table) {
1215   uint32_t m;
1216 
1217   assert(n <= 6 && k_max == (1 << n));
1218 
1219   for (m=0; m<k_max; m++) {
1220     eval_candidate(c, n, m);
1221     if (! rational_eq_term(c->terms, &c->q_aux, table[m])) {
1222       return false;
1223     }
1224   }
1225 
1226   return true;
1227 }
1228 
1229 /*
1230  * Build the term q * x where x is Boolean variable
1231  * - this builds (if x q 0)
1232  */
make_pseudo_product(term_table_t * terms,rational_t * q,term_t x)1233 static term_t make_pseudo_product(term_table_t *terms, rational_t *q, term_t x) {
1234   term_t a;
1235   type_t tau;
1236 
1237   assert(is_boolean_term(terms, x));
1238 
1239   a = arith_constant(terms, q);
1240   tau = term_type(terms, a);
1241 
1242   return ite_term(terms, tau, x, a, zero_term);
1243 }
1244 
1245 
1246 // variant: make (if x 1 0)
make_zero_one(term_table_t * terms,term_t x)1247 static term_t make_zero_one(term_table_t *terms, term_t x) {
1248   rational_t q;
1249   term_t t;
1250 
1251   q_init(&q);
1252   q_set_one(&q);
1253   t = make_pseudo_product(terms, &q, x);
1254   q_clear(&q);
1255 
1256   return t;
1257 }
1258 
1259 /*
1260  * Build the linear equality x - s == 0 (as a term)
1261  * - s = variables
1262  */
make_linear_equality(cond_def_collector_t * c,term_t x,harray_t * s)1263 static term_t make_linear_equality(cond_def_collector_t *c, term_t x, harray_t *s) {
1264   rba_buffer_t *b;
1265   uint32_t i, n;
1266   term_t t;
1267 
1268   b = context_get_arith_buffer(c->ctx);
1269   assert(b != NULL && rba_buffer_is_zero(b));
1270 
1271   rba_buffer_add_const(b, &c->base);
1272 
1273   n = s->nelems;
1274   assert(n <= 6);
1275   for (i=0; i<n; i++) {
1276 #if 0
1277     t = make_pseudo_product(c->terms, c->coeff + i, s->data[i]);
1278     rba_buffer_add_term(b, c->terms, t);
1279 #else
1280     t = make_zero_one(c->terms, s->data[i]);
1281     rba_buffer_add_const_times_term(b, c->terms, c->coeff + i, t);
1282 #endif
1283   }
1284 
1285   rba_buffer_sub_term(b, c->terms, x);
1286 
1287   return mk_direct_arith_eq0(c->terms, b, false);
1288 }
1289 
1290 
1291 /*
1292  * Attempt to convert table into a linear combination of 0/1 variables
1293  */
try_linear_table(cond_def_collector_t * c,term_t x,harray_t * s,uint32_t k_max,term_t * table)1294 static void try_linear_table(cond_def_collector_t *c, term_t x, harray_t *s, uint32_t k_max, term_t *table) {
1295   uint32_t n;
1296   term_t eq;
1297 
1298   n = s->nelems;
1299   assert(k_max == (1 << n));
1300 
1301   build_candidate(c, n, table);
1302   if (candidate_is_good(c, n, k_max, table)) {
1303 #if TRACE
1304     printf("Candidate linear expression: ");
1305     print_candidate(c, s);
1306 #endif
1307     eq = make_linear_equality(c, x, s);
1308     add_arith_aux_eq(c->ctx, eq);
1309 #if TRACE
1310     printf("As term: ");
1311     print_term_full(stdout, c->terms, eq);
1312     printf("\n");
1313 #endif
1314   }
1315 }
1316 
1317 
1318 /*
1319  * Examine the table of values for a term x
1320  * - s = variable set = set of Boolean variables with at most six elements
1321  *   s = { b_0, ..., b_n } where n<=5
1322  * - table = array of k_max values where k_max = 2^|s|
1323  * - every integer in 0 ... k_max-1 encodes a Boolean assignment
1324  *   to the variables of s:
1325  *     bit 0 of i is the value of b_0
1326  *     bit 1 of i is the value of b_1
1327  *     etc.
1328  * - using this encoding,  table[i] = value assigned to x
1329  *   for the Boolean assignment i
1330  *
1331  * - if table[i] = NULL_TERM, then the value is not defined
1332  * - if table[i] = -2 then assignment i is not allowed
1333  * - otherwise table[i] is a constant term
1334  */
analyze_map_table(cond_def_collector_t * c,term_t x,harray_t * s,uint32_t k_max,term_t * table)1335 static void analyze_map_table(cond_def_collector_t *c, term_t x, harray_t *s, uint32_t k_max, term_t *table) {
1336   uint32_t i, nconflicts;
1337 
1338   assert(s->nelems <= 6 && k_max <= 64 && (k_max == (1 << s->nelems)));
1339 
1340   // if any row in table is NULL_TERM we don't do anything
1341   nconflicts = 0;
1342   for (i=0; i<k_max; i++) {
1343     if (table[i] == NULL_TERM) return;
1344     if (table[i] == -2) {
1345       nconflicts ++;
1346     }
1347   }
1348 
1349   /*
1350    * table[0 ... k_max-1] contains the set of possible
1351    * values of x
1352    */
1353   if (is_arithmetic_term(c->terms, x)) {
1354     assert_arith_bounds_from_table(c, x, k_max, table);
1355     if (nconflicts == 0 && s->nelems >= 2 && s->nelems <= 4) {
1356       try_linear_table(c, x, s, k_max, table);
1357     }
1358   }
1359 }
1360 
1361 
1362 /*
1363  * Compute the union of all vsets in a[0] ... a[n-1]
1364  * - n must be positive
1365  * - return NULL if the union has more than 6 elements
1366  */
merge_vsets(cond_def_collector_t * c,cond_def_t ** a,uint32_t n)1367 static harray_t *merge_vsets(cond_def_collector_t *c, cond_def_t **a, uint32_t n) {
1368   harray_t *s, *r;
1369   ivector_t *v;
1370   uint32_t i;
1371 
1372   assert(n > 0);
1373 
1374   r = NULL;
1375   s = a[0]->vset;
1376   if (s->nelems <= 6) {
1377     // it's common for all sets to be equal.
1378     for (i=1; i<n; i++) {
1379       if (s != a[i]->vset) break;
1380     }
1381 
1382     if (i == n) {
1383       // a[0 ... n-1] all have the set same vset
1384       r = s;
1385     } else {
1386       assert(i < n);
1387 
1388       // merge s with a[i] ... a[n-1];
1389       v = &c->aux;
1390       assert(v->size == 0);
1391       add_vars_to_vector(v, s);
1392       do {
1393 	add_vars_to_vector(v, a[i]->vset);
1394 	i ++;
1395       } while (v->size <= 6 && i < n);
1396 
1397       if (v->size <= 6) {
1398 	r = vector_to_set(&c->store, v);
1399       }
1400       ivector_reset(v);
1401     }
1402   }
1403 
1404   return r;
1405 }
1406 
1407 
1408 /*
1409  * Process all conditional definitions for the same term x
1410  * - the definitions are stored in a[0 ... n-1]
1411  * - first, we build the set of variables that occur in a[0 ... n-1]
1412  * - if this set S has six variables or less, we build a table that defines x.
1413  * - each truth assignment to variables of S is encoded as an integer
1414  *   between 0 and 2^|S|-1.
1415  * - table[k] = value of x for truth assignment k
1416  */
analyze_term_cond_def(cond_def_collector_t * c,term_t x,cond_def_t ** a,uint32_t n)1417 static void analyze_term_cond_def(cond_def_collector_t *c, term_t x, cond_def_t **a, uint32_t n) {
1418   term_t table[64];
1419   cond_def_t *d;
1420   harray_t *s;
1421   uint64_t ttbl;
1422   uint32_t i, k, max_k;
1423 
1424 #if TRACE
1425   printf("\nDefinitions for term ");
1426   print_term_name(stdout, c->terms, x);
1427   printf("\n");
1428   for (i=0; i<n; i++) {
1429     d = a[i];
1430     assert(d->term == x);
1431     print_cond_def(c, d);
1432   }
1433 #endif
1434 
1435   s = merge_vsets(c, a, n);
1436   if (s != NULL) {
1437     // s has six vars or less
1438     max_k = (1 << s->nelems);
1439     assert(max_k <= 64);
1440 
1441     for (k=0; k<max_k; k++) {
1442       table[k] = NULL_TERM;
1443     }
1444 
1445     reset_simple_cache(&c->cache);
1446 
1447     for (i=0; i<n; i++) {
1448       d = a[i];
1449       /*
1450        * d is (cond => x = d->value)
1451        * we build ttbl = truth table of cond
1452        * if ttbl[k] is true, then table[k] := d->value
1453        */
1454       ttbl = truth_tbl_of_array(c, d->nconds, d->cond, s->data, s->nelems);
1455       for (k=0; k<max_k; k++) {
1456 	if (truth_tbl_test_row(ttbl, k)) {
1457 	  /*
1458 	   * table[k] must be equal to d->value
1459 	   * if table[k] is already set to something else, we mark the conflict
1460 	   * by setting table[k] to -2.
1461 	   */
1462 	  if (table[k] == NULL_TERM) {
1463 	    table[k] = d->value;
1464 	  } else if (table[k] != d->value) {
1465 	    assert(table[k] == -2 || disequal_terms(c->terms, d->value, table[k], true));
1466 	    table[k] = -2;
1467 	  }
1468 	}
1469       }
1470     }
1471 
1472 #if TRACE
1473     printf("Var set: ");
1474     print_vset(c, s);
1475     printf("\n");
1476     printf("Table:\n");
1477     print_definition_table(c, table, s->data, s->nelems);
1478 #endif
1479 
1480     /*
1481      * Learn what we can from the table
1482      */
1483     analyze_map_table(c, x, s, max_k, table);
1484   }
1485 
1486 
1487 }
1488 
1489 /*
1490  * Sort the conditional definitions:
1491  * - we want all definitions with the same variable to be adjacent in c->cdefs
1492  */
1493 // comparison function: return true if d1 < d2 in this ordering
cdef_lt(void * data,void * d1,void * d2)1494 static bool cdef_lt(void *data, void *d1, void *d2) {
1495   return ((cond_def_t *) d1)->term  < ((cond_def_t *) d2)-> term;
1496 }
1497 
1498 /*
1499  * Process all conditional definitions in c->cdefs
1500  */
analyze_conditional_definitions(cond_def_collector_t * c)1501 void analyze_conditional_definitions(cond_def_collector_t *c) {
1502   uint32_t i, j, n;
1503   cond_def_t **a;
1504   term_t x;
1505 
1506   n = c->cdefs.size;
1507   if (n > 0) {
1508     ptr_array_sort2(c->cdefs.data, n, NULL, cdef_lt);
1509 
1510     a = (cond_def_t **) c->cdefs.data;
1511     i = 0;
1512     j = 0;
1513     while (i < n) {
1514       assert(i == j);
1515 
1516       /*
1517        * find segment: [i ... j-1]: that contains all defs with the
1518        * same variable x
1519        */
1520       x = a[i]->term;
1521       do { j ++; } while (j < n && a[j]->term == x);
1522       assert(i < j);
1523       analyze_term_cond_def(c, x, a + i, j - i);
1524       i = j;
1525     }
1526   }
1527 }
1528