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