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  * DPLL(T) CORE
21  */
22 
23 #include <assert.h>
24 #include <stddef.h>
25 #include <float.h>
26 
27 #include "solvers/cdcl/smt_core.h"
28 #include "utils/gcd.h"
29 #include "utils/int_array_sort.h"
30 #include "utils/int_hash_sets.h"
31 #include "utils/int_queues.h"
32 #include "utils/memalloc.h"
33 
34 
35 #define TRACE 0
36 #define DEBUG 0
37 
38 #if DEBUG || TRACE
39 
40 #include <stdio.h>
41 #include <inttypes.h>
42 
43 extern void print_literal(FILE *f, literal_t l);
44 extern void print_bval(FILE *f, bval_t b);
45 extern void print_bvar(FILE *f, bvar_t x);
46 
47 #endif
48 
49 
50 #if DEBUG
51 
52 // All debugging functions are defined at the end of this file
53 static void check_heap_content(smt_core_t *s);
54 static void check_heap(smt_core_t *s);
55 static void check_propagation(smt_core_t *s);
56 static void check_marks(smt_core_t *s);
57 static void check_theory_conflict(smt_core_t *s, literal_t *a);
58 static void check_theory_explanation(smt_core_t *s, literal_t l);
59 static void check_watched_literals(smt_core_t *s, uint32_t n, literal_t *a);
60 static void check_lemma(smt_core_t *s, uint32_t n, literal_t *a);
61 
62 #endif
63 
64 
65 
66 
67 /**********
68  *  PRNG  *
69  *********/
70 
71 /*
72  * PARAMETERS FOR THE PSEUDO RANDOM NUMBER GENERATOR
73  *
74  * We  use the same linear congruence as in prng.h,
75  * but we use a local implementation so that different
76  * solvers can use different seeds.
77  */
78 
79 #define CORE_PRNG_MULTIPLIER 1664525
80 #define CORE_PRNG_CONSTANT   1013904223
81 #define CORE_PRNG_SEED       0xabcdef98
82 
83 
84 /*
85  * Return a 32bit unsigned int
86  */
random_uint32(smt_core_t * s)87 static inline uint32_t random_uint32(smt_core_t *s) {
88   uint32_t x;
89 
90   x = s->prng;
91   s->prng = x * ((uint32_t) CORE_PRNG_MULTIPLIER) + ((uint32_t) CORE_PRNG_CONSTANT);
92   return x;
93 }
94 
95 
96 /*
97  * Return a 32bit integer between 0 and n-1
98  */
random_uint(smt_core_t * s,uint32_t n)99 static inline uint32_t random_uint(smt_core_t *s, uint32_t n) {
100   return (random_uint32(s) >> 8) % n;
101 }
102 
103 
104 
105 
106 /********************************
107  * CLAUSES AND LEARNED CLAUSES  *
108  *******************************/
109 
110 /*
111  * Get first watched literal of cl
112  */
get_first_watch(clause_t * cl)113 static inline literal_t get_first_watch(clause_t *cl) {
114   return cl->cl[0];
115 }
116 
117 /*
118  * Get second watched literal of cl
119  */
get_second_watch(clause_t * cl)120 static inline literal_t get_second_watch(clause_t *cl) {
121   return cl->cl[1];
122 }
123 
124 /*
125  * Get watched literal of index (1 - i) in cl.
126  * - i = 0 or 1
127  */
get_other_watch(clause_t * cl,uint32_t i)128 static inline literal_t get_other_watch(clause_t *cl, uint32_t i) {
129   // flip low-order bit of i
130   return cl->cl[1 - i];
131 }
132 
133 /*
134  * Get pointer to learned_clause in which clause cl is embedded.
135  */
learned(const clause_t * cl)136 static inline learned_clause_t *learned(const clause_t *cl) {
137   return (learned_clause_t *)(((char *)cl) - offsetof(learned_clause_t, clause));
138 }
139 
140 /*
141  * Activity of a learned clause
142  */
get_activity(const clause_t * cl)143 static inline float get_activity(const clause_t *cl) {
144   return learned(cl)->activity;
145 }
146 
147 /*
148  * Increase the activity of a learned clause by delta
149  */
increase_activity(clause_t * cl,float delta)150 static inline void increase_activity(clause_t *cl, float delta) {
151   learned(cl)->activity += delta;
152 }
153 
154 /*
155  * Multiply activity by scale
156  */
multiply_activity(clause_t * cl,float scale)157 static inline void multiply_activity(clause_t *cl, float scale) {
158   learned(cl)->activity *= scale;
159 }
160 
161 /*
162  * Mark a clause cl for removal
163  */
mark_for_removal(clause_t * cl)164 static inline void mark_for_removal(clause_t *cl) {
165   cl->cl[0] = - cl->cl[0];
166   cl->cl[1] = - cl->cl[1];
167 }
168 
is_clause_to_be_removed(clause_t * cl)169 static inline bool is_clause_to_be_removed(clause_t *cl) {
170   return cl->cl[0] < 0;
171 }
172 
173 /*
174  * Restore a removed clause: flip the signs back
175  */
restore_removed_clause(clause_t * cl)176 static inline void restore_removed_clause(clause_t *cl) {
177   cl->cl[0] = - cl->cl[0];
178   cl->cl[1] = - cl->cl[1];
179 }
180 
181 
182 /*
183  * Clause length
184  */
clause_length(clause_t * cl)185 static uint32_t clause_length(clause_t *cl) {
186   literal_t *a;
187 
188   a = cl->cl + 2;
189   while (*a >= 0) {
190     a ++;
191   }
192 
193   return a - cl->cl;
194 }
195 
196 /*
197  * Allocate and initialize a new clause (not a learned clause)
198  * \param len = number of literals
199  * \param lit = array of len literals
200  * The watched pointers are not initialized
201  */
new_clause(uint32_t len,literal_t * lit)202 static clause_t *new_clause(uint32_t len, literal_t *lit) {
203   clause_t *result;
204   uint32_t i;
205 
206   result = (clause_t *) safe_malloc(sizeof(clause_t) + sizeof(literal_t) +
207                                     len * sizeof(literal_t));
208 
209   for (i=0; i<len; i++) {
210     result->cl[i] = lit[i];
211   }
212   result->cl[i] = end_clause; // end marker: not a learned clause
213 
214   return result;
215 }
216 
217 /*
218  * Delete clause cl
219  * cl must be a non-learned clause, allocated via the previous function.
220  */
delete_clause(clause_t * cl)221 static inline void delete_clause(clause_t *cl) {
222   safe_free(cl);
223 }
224 
225 /*
226  * Allocate and initialize a new learned clause
227  * \param len = number of literals
228  * \param lit = array of len literals
229  * The watched pointers are not initialized.
230  * The activity is initialized to 0.0
231  */
new_learned_clause(uint32_t len,literal_t * lit)232 static clause_t *new_learned_clause(uint32_t len, literal_t *lit) {
233   learned_clause_t *tmp;
234   clause_t *result;
235   uint32_t i;
236 
237   tmp = (learned_clause_t *) safe_malloc(sizeof(learned_clause_t) + sizeof(literal_t) +
238                                          len * sizeof(literal_t));
239   tmp->activity = 0.0;
240   result = &(tmp->clause);
241 
242   for (i=0; i<len; i++) {
243     result->cl[i] = lit[i];
244   }
245   result->cl[i] = end_learned; // end marker: learned clause
246 
247   return result;
248 }
249 
250 /*
251  * Delete learned clause cl
252  * cl must have been allocated via the new_learned_clause function
253  */
delete_learned_clause(clause_t * cl)254 static inline void delete_learned_clause(clause_t *cl) {
255   safe_free(learned(cl));
256 }
257 
258 
259 
260 /********************
261  *  CLAUSE VECTORS  *
262  *******************/
263 
264 /*
265  * Create a clause vector of capacity n.
266  */
new_clause_vector(uint32_t n)267 static clause_t **new_clause_vector(uint32_t n) {
268   clause_vector_t *tmp;
269 
270   tmp = (clause_vector_t *) safe_malloc(sizeof(clause_vector_t) + n * sizeof(clause_t *));
271   tmp->capacity = n;
272   tmp->size = 0;
273 
274   return tmp->data;
275 }
276 
277 /*
278  * Clean up: free memory used by v
279  */
delete_clause_vector(clause_t ** v)280 static void delete_clause_vector(clause_t **v) {
281   safe_free(cv_header(v));
282 }
283 
284 /*
285  * Add clause cl at the end of vector *v. Assumes *v has been initialized.
286  */
add_clause_to_vector(clause_t *** v,clause_t * cl)287 static void add_clause_to_vector(clause_t ***v, clause_t *cl) {
288   clause_vector_t *vector;
289   clause_t **d;
290   uint32_t i, n;
291 
292   d = *v;
293   vector = cv_header(d);
294   i = vector->size;
295   if (i == vector->capacity) {
296     n = i + 1;
297     n += (n >> 1); // n = new capacity
298     if (n > MAX_CLAUSE_VECTOR_SIZE) {
299       out_of_memory();
300     }
301     vector = (clause_vector_t *)
302       safe_realloc(vector, sizeof(clause_vector_t) + n * sizeof(clause_t *));
303     vector->capacity = n;
304     d = vector->data;
305     *v = d;
306   }
307   d[i] = cl;
308   vector->size = i+1;
309 }
310 
311 
312 /*
313  * Reset clause vector v: set its size to 0
314  */
reset_clause_vector(clause_t ** v)315 static inline void reset_clause_vector(clause_t **v) {
316   set_cv_size(v, 0);
317 }
318 
319 
320 
321 
322 /**********************
323  *  LITERAL VECTORS   *
324  *********************/
325 
326 /*
327  * When used to store binary clauses literal vectors are initially
328  * NULL.  Memory is allocated on the first addition and literal
329  * vectors are terminated by -1.
330  *
331  * For a vector v of size i, the literals are stored
332  * in v[0],...,v[i-1], and v[i] = -1
333  */
334 
335 /*
336  * Add literal l at the end of vector *v
337  * - allocate a fresh vector if *v == NULL
338  * - resize *v if *v is full.
339  * - add -1 terminator after l.
340  */
add_literal_to_vector(literal_t ** v,literal_t l)341 static void add_literal_to_vector(literal_t **v, literal_t l) {
342   literal_vector_t *vector;
343   literal_t *d;
344   uint32_t i, n;
345 
346   d = *v;
347   if (d == NULL) {
348     i = 0;
349     n = DEF_LITERAL_VECTOR_SIZE;
350     vector = (literal_vector_t *)
351       safe_malloc(sizeof(literal_vector_t) + n * sizeof(literal_t));
352     vector->capacity = n;
353     d = vector->data;
354     *v = d;
355   } else {
356     vector = lv_header(d);
357     i = vector->size;
358     n = vector->capacity;
359     if (i >= n - 1) {
360       n ++;
361       n += n>>1; // new cap = 50% more than old capacity
362       if (n > MAX_LITERAL_VECTOR_SIZE) {
363         out_of_memory();
364       }
365       vector = (literal_vector_t *)
366         safe_realloc(vector, sizeof(literal_vector_t) + n * sizeof(literal_t));
367       vector->capacity = n;
368       d = vector->data;
369       *v = d;
370     }
371   }
372 
373   assert(i + 1 < vector->capacity);
374 
375   d[i] = l;
376   d[i+1] = null_literal;
377   vector->size = i+1;
378 }
379 
380 
381 /*
382  * Delete literal vector v
383  */
delete_literal_vector(literal_t * v)384 static void delete_literal_vector(literal_t *v) {
385   if (v != NULL) {
386     safe_free(lv_header(v));
387   }
388 }
389 
390 
391 /*
392  * Remove the last literal from vector v
393  */
literal_vector_pop(literal_t * v)394 static  void literal_vector_pop(literal_t *v) {
395   uint32_t i;
396 
397   i = get_lv_size(v);
398   assert(i > 0);
399   i --;
400   v[i] = null_literal;
401   set_lv_size(v,  i);
402 }
403 
404 
405 /*
406  * Last element of vector v (used in assert)
407  */
408 #ifndef NDEBUG
last_lv_elem(literal_t * v)409 static inline literal_t last_lv_elem(literal_t *v) {
410   assert(v != NULL && get_lv_size(v) > 0);
411   return v[get_lv_size(v) - 1];
412 }
413 #endif
414 
415 
416 /***********
417  *  STACK  *
418  **********/
419 
420 /*
421  * Initialize stack s for nvar
422  */
init_stack(prop_stack_t * s,uint32_t nvar)423 static void init_stack(prop_stack_t *s, uint32_t nvar) {
424   s->lit = (literal_t *) safe_malloc(nvar * sizeof(literal_t));
425   s->level_index = (uint32_t *) safe_malloc(DEFAULT_NLEVELS * sizeof(uint32_t));
426   s->level_index[0] = 0;
427   s->top = 0;
428   s->prop_ptr = 0;
429   s->theory_ptr = 0;
430   s->nlevels = DEFAULT_NLEVELS;
431 }
432 
433 /*
434  * Extend the size: nvar = new size
435  */
extend_stack(prop_stack_t * s,uint32_t nvar)436 static void extend_stack(prop_stack_t *s, uint32_t nvar) {
437   s->lit = (literal_t *) safe_realloc(s->lit, nvar * sizeof(literal_t));
438 }
439 
440 /*
441  * Extend the level_index array by 50%
442  */
increase_stack_levels(prop_stack_t * s)443 static void increase_stack_levels(prop_stack_t *s) {
444   uint32_t n;
445 
446   n = s->nlevels;
447   n += n>>1;
448   s->level_index = (uint32_t *) safe_realloc(s->level_index, n * sizeof(uint32_t));
449   s->nlevels = n;
450 }
451 
452 /*
453  * Reset the stack (empty it)
454  */
reset_stack(prop_stack_t * s)455 static void reset_stack(prop_stack_t *s) {
456   s->top = 0;
457   s->prop_ptr = 0;
458   s->theory_ptr = 0;
459   s->level_index[0] = 0;
460 }
461 
462 
463 /*
464  * Free memory used by stack s
465  */
delete_stack(prop_stack_t * s)466 static void delete_stack(prop_stack_t *s) {
467   free(s->lit);
468   free(s->level_index);
469 }
470 
471 /*
472  * Push literal l on top of stack s
473  */
push_literal(prop_stack_t * s,literal_t l)474 static void push_literal(prop_stack_t *s, literal_t l) {
475   uint32_t i;
476   i = s->top;
477   s->lit[i] = l;
478   s->top = i + 1;
479 }
480 
481 
482 
483 
484 /**********
485  *  HEAP  *
486  *********/
487 
488 /*
489  * Initialize heap for n variables
490  * - heap is initially empty: heap_last = 0
491  * - heap[0] = -1 is a marker, with activity[-1] higher
492  *   than any variable activity.
493  * - we also use -2 as a marker with negative activity
494  * - activity increment and threshold are set to their
495  *   default initial value.
496  */
init_heap(var_heap_t * heap,uint32_t n)497 static void init_heap(var_heap_t *heap, uint32_t n) {
498   uint32_t i;
499   double *tmp;
500 
501   heap->size = n;
502   tmp = (double *) safe_malloc((n+2) * sizeof(double));
503   heap->activity = tmp + 2;
504   heap->heap_index = (int32_t *) safe_malloc(n * sizeof(int32_t));
505   heap->heap = (bvar_t *) safe_malloc((n+1) * sizeof(bvar_t));
506 
507   for (i=0; i<n; i++) {
508     heap->heap_index[i] = -1;
509     heap->activity[i] = 0.0;
510   }
511 
512   heap->activity[-2] = -1.0;
513   heap->activity[-1] = DBL_MAX;
514   heap->heap[0] = -1;
515   heap->heap_last = 0;
516 
517   heap->act_increment = INIT_VAR_ACTIVITY_INCREMENT;
518   heap->inv_act_decay = 1/VAR_DECAY_FACTOR;
519 }
520 
521 /*
522  * Extend the heap for n variables
523  */
extend_heap(var_heap_t * heap,uint32_t n)524 static void extend_heap(var_heap_t *heap, uint32_t n) {
525   uint32_t old_size, i;
526   double *tmp;
527 
528   old_size = heap->size;
529   assert(old_size < n);
530   heap->size = n;
531   tmp = heap->activity - 2;
532   tmp = (double *) safe_realloc(tmp, (n+2) * sizeof(double));
533   heap->activity = tmp + 2;
534   heap->heap_index = (int32_t *) safe_realloc(heap->heap_index, n * sizeof(int32_t));
535   heap->heap = (int32_t *) safe_realloc(heap->heap, (n+1) * sizeof(int32_t));
536 
537   for (i=old_size; i<n; i++) {
538     heap->heap_index[i] = -1;
539     heap->activity[i] = 0.0;
540   }
541 }
542 
543 /*
544  * Free the heap
545  */
delete_heap(var_heap_t * heap)546 static void delete_heap(var_heap_t *heap) {
547   safe_free(heap->activity - 2);
548   safe_free(heap->heap_index);
549   safe_free(heap->heap);
550 }
551 
552 
553 /*
554  * Reset: remove all variables from the heap and set their activities to 0
555  */
reset_heap(var_heap_t * heap)556 static void reset_heap(var_heap_t *heap) {
557   uint32_t i, n;
558 
559   n = heap->size;
560   for (i=0; i<n; i++) {
561     heap->heap_index[i] = -1;
562     heap->activity[i] = 0.0;
563   }
564   heap->heap_last = 0;
565 
566   // reset activity parameters: this makes a difference (2010/08/10)
567   heap->act_increment = INIT_VAR_ACTIVITY_INCREMENT;
568   heap->inv_act_decay = 1/VAR_DECAY_FACTOR;
569 }
570 
571 
572 /*
573  * EXPERIMENT: TEST TWO HEAP ORDERINGS
574  * - if BREAK_TIES is set, then ties are broken by ranking
575  *   the variable with smallest index higher than the other.
576  *   (seems to work better on bitvector benchmarks)
577  * - otherwise, we don't attempt to break ties.
578  *
579  * NOTE: if BREAK_TIES is set, then rescale_var_activities
580  * may not preserve the intended heap ordering. We ignore this
581  * issue for now, it should not matter much anyway??
582  */
583 
584 #define BREAK_TIES 1
585 
586 /*
587  * Comparison: return true if x precedes y in the heap ordering (strict ordering)
588  * - ax = activity of x
589  * - ay = activity of y
590  */
heap_cmp(bvar_t x,bvar_t y,double ax,double ay)591 static inline bool heap_cmp(bvar_t x, bvar_t y, double ax, double ay) {
592 #if BREAK_TIES
593   return (ax > ay) || (ax == ay && x < y);
594 #else
595   return ax > ay;
596 #endif
597 }
598 
599 // variant: act = activity array
heap_precedes(double * act,bvar_t x,bvar_t y)600 static inline bool heap_precedes(double *act, bvar_t x, bvar_t y) {
601   return heap_cmp(x, y, act[x], act[y]);
602 }
603 
604 
605 
606 /*
607  * Move x up in the heap.
608  * i = current position of x in the heap (or heap_last if x is being inserted)
609  */
update_up(var_heap_t * heap,bvar_t x,uint32_t i)610 static void update_up(var_heap_t *heap, bvar_t x, uint32_t i) {
611   double ax, *act;
612   int32_t *index;
613   bvar_t *h, y;
614   uint32_t j;
615 
616   h = heap->heap;
617   index = heap->heap_index;
618   act = heap->activity;
619 
620   ax = act[x];
621 
622   j = i >> 1;    // parent of i
623   y = h[j];      // variable at position j in the heap
624 
625   // The loop terminates since act[h[0]] = DBL_MAX and h[0] = -1
626   while (heap_cmp(x, y, ax, act[y])) {
627     // move y down, into position i
628     h[i] = y;
629     index[y] = i;
630 
631     // move i and j up
632     i = j;
633     j >>= 1;
634     y = h[j];
635   }
636 
637   // i is the new position for variable x
638   h[i] = x;
639   index[x] = i;
640 }
641 
642 
643 /*
644  * Remove element at index i in the heap.
645  * Replace it by the current last element.
646  */
update_down(var_heap_t * heap,uint32_t i)647 static void update_down(var_heap_t *heap, uint32_t i) {
648   double *act;
649   int32_t *index;
650   bvar_t *h;
651   double ax, ay, az;
652   bvar_t x, y, z;
653   uint32_t j, last;
654 
655   last = heap->heap_last;
656   heap->heap_last = last - 1;
657   if (last == i) return;  // last element was removed
658 
659   h = heap->heap;
660   index = heap->heap_index;
661   act = heap->activity;
662 
663   assert(i < last && act[h[i]] >= act[h[last]]);
664 
665   z = h[last]; // last element
666   az = act[z]; // activity of last heap element.
667 
668   // set end marker: act[-2] is less than any variable activity
669   h[last] = -2;
670 
671   j = 2 * i;   // left child of i
672 
673   while (j < last) {
674     /*
675      * find child of i with highest activity.
676      * Since we've set h[last] = -2, we don't need to check for j+1 < last
677      */
678     x = h[j];
679     ax = act[x];
680     y = h[j+1];
681     ay = act[y];
682     if (heap_cmp(y, x, ay, ax)) {
683       j ++;
684       x = y;
685       ax = ay;
686     }
687 
688     // x = child of node i of highest activity
689     // j = position of x in the heap (j = 2i or j = 2i+1)
690     if (heap_cmp(z, x, az, ax)) break;
691 
692     // move x up, into heap[i]
693     h[i] = x;
694     index[x] = i;
695 
696     // go down one step.
697     i = j;
698     j <<= 1;
699   }
700 
701   h[i] = z;
702   index[z] = i;
703 }
704 
705 
706 /*
707  * Insert x into the heap, using its current activity.
708  * No effect if x is already in the heap.
709  * - x must be between 0 and nvars - 1
710  */
heap_insert(var_heap_t * heap,bvar_t x)711 static void heap_insert(var_heap_t *heap, bvar_t x) {
712   if (heap->heap_index[x] < 0) {
713     // x not in the heap
714     heap->heap_last ++;
715     update_up(heap, x, heap->heap_last);
716   }
717 }
718 
719 /*
720  * Remove x from the heap
721  */
heap_remove(var_heap_t * heap,bvar_t x)722 static void heap_remove(var_heap_t *heap, bvar_t x) {
723   int32_t i, j;
724   bvar_t y;
725 
726   i = heap->heap_index[x];
727   if (i < 0) return; // x is not in the heap
728 
729   heap->heap_index[x] = -1;
730 
731   j = heap->heap_last;
732   y = heap->heap[j]; // last variable
733 
734   if (i == j) {
735     // x was the last element
736     assert(x == y);
737     heap->heap_last --;
738   } else if (heap_precedes(heap->activity, x, y)) {
739     // in update down, h[i] is replaced by last element (i.e. y)
740     update_down(heap, i);
741   } else {
742     // replace x by y and move y up the heap
743     heap->heap[i] = y;
744     heap->heap_last --;
745     update_up(heap, y, i);
746   }
747 }
748 
749 
750 /*
751  * Check whether the heap is empty
752  */
heap_is_empty(var_heap_t * heap)753 static inline bool heap_is_empty(var_heap_t *heap) {
754   return heap->heap_last == 0;
755 }
756 
757 
758 /*
759  * Get and remove the top element
760  * - the heap must not be empty
761  */
heap_get_top(var_heap_t * heap)762 static bvar_t heap_get_top(var_heap_t *heap) {
763   bvar_t top;
764 
765   assert(heap->heap_last > 0);
766 
767   // remove top element
768   top = heap->heap[1];
769   heap->heap_index[top] = -1;
770 
771   // repair the heap
772   update_down(heap, 1);
773 
774   return top;
775 }
776 
777 
778 /*
779  * Rescale variable activities: divide by VAR_ACTIVITY_THRESHOLD
780  * \param heap = pointer to a heap structure
781  * \param n = number of variables
782  */
rescale_var_activities(var_heap_t * heap,uint32_t n)783 static void rescale_var_activities(var_heap_t *heap, uint32_t n) {
784   uint32_t i;
785   double *act;
786 
787   heap->act_increment *= INV_VAR_ACTIVITY_THRESHOLD;
788   act = heap->activity;
789   for (i=0; i<n; i++) {
790     act[i] *= INV_VAR_ACTIVITY_THRESHOLD;
791   }
792 }
793 
794 
795 
796 /*****************
797  *  TRAIL STACK  *
798  ****************/
799 
800 /*
801  * Initialize a trail stack. Size = 0
802  */
init_trail_stack(trail_stack_t * stack)803 static void init_trail_stack(trail_stack_t *stack) {
804   stack->size = 0;
805   stack->top = 0;
806   stack->data = NULL;
807 }
808 
809 /*
810  * Save level:
811  * - v = number of variables
812  * - u = number of unit clauses
813  * - b = number of binary clauses
814  * - p = number of (non-unit and non-binary) problem clauses
815  * - b_ptr = boolean propagation pointer
816  * - t_ptr = theory propagation pointer
817  */
trail_stack_save(trail_stack_t * stack,uint32_t v,uint32_t u,uint32_t b,uint32_t p,uint32_t b_ptr,uint32_t t_ptr)818 static void trail_stack_save(trail_stack_t *stack, uint32_t v, uint32_t u, uint32_t b, uint32_t p,
819                              uint32_t b_ptr, uint32_t t_ptr) {
820   uint32_t i, n;
821 
822   i = stack->top;
823   n = stack->size;
824   if (i == n) {
825     if (n == 0) {
826       n = DEFAULT_DPLL_TRAIL_SIZE;
827     } else {
828       n += n;
829       if (n >= MAX_DPLL_TRAIL_SIZE) {
830         out_of_memory();
831       }
832     }
833     stack->data = (trail_t *) safe_realloc(stack->data, n * sizeof(trail_t));
834     stack->size = n;
835   }
836   stack->data[i].nvars = v;
837   stack->data[i].nunits = u;
838   stack->data[i].nbins = b;
839   stack->data[i].nclauses = p;
840   stack->data[i].prop_ptr = b_ptr;
841   stack->data[i].theory_ptr = t_ptr;
842 
843   stack->top = i + 1;
844 }
845 
846 
847 /*
848  * Get top record
849  */
trail_stack_top(trail_stack_t * stack)850 static inline trail_t *trail_stack_top(trail_stack_t *stack) {
851   assert(stack->top > 0);
852   return stack->data + (stack->top - 1);
853 }
854 
855 /*
856  * Remove top record
857  */
trail_stack_pop(trail_stack_t * stack)858 static inline void trail_stack_pop(trail_stack_t *stack) {
859   assert(stack->top > 0);
860   stack->top --;
861 }
862 
863 
864 /*
865  * Empty the stack
866  */
reset_trail_stack(trail_stack_t * stack)867 static inline void reset_trail_stack(trail_stack_t *stack) {
868   stack->top = 0;
869 }
870 
871 
872 /*
873  * Delete
874  */
delete_trail_stack(trail_stack_t * stack)875 static inline void delete_trail_stack(trail_stack_t *stack) {
876   safe_free(stack->data);
877   stack->data = NULL;
878 }
879 
880 
881 
882 /******************
883  *   ATOM TABLE   *
884  *****************/
885 
886 /*
887  * Initialization: the table is initially empty.
888  */
init_atom_table(atom_table_t * tbl)889 static void init_atom_table(atom_table_t *tbl) {
890   tbl->has_atom = NULL;
891   tbl->atom = NULL;
892   tbl->size = 0;
893   tbl->natoms = 0;
894 }
895 
896 
897 /*
898  * Make room for more atoms: n = new size
899  */
resize_atom_table(atom_table_t * tbl,uint32_t n)900 static void resize_atom_table(atom_table_t *tbl, uint32_t n) {
901   uint32_t k;
902 
903   // round up to a multiple of 8
904   n = (n + 7) & ~7;
905   k = tbl->size;
906 
907   if (n > k) {
908     assert(n <= MAX_ATOM_TABLE_SIZE);
909 
910     tbl->has_atom = extend_bitvector(tbl->has_atom, n);
911     tbl->atom = (void **) safe_realloc(tbl->atom, n * sizeof(void *));
912     tbl->size = n;
913 
914     // clear new bitvector elements
915     clear_bitvector(tbl->has_atom + (k>>3), n - k);
916   }
917 }
918 
919 
920 /*
921  * Deletion
922  */
delete_atom_table(atom_table_t * tbl)923 static void delete_atom_table(atom_table_t *tbl) {
924   delete_bitvector(tbl->has_atom);
925   safe_free(tbl->atom);
926   tbl->has_atom = NULL;
927   tbl->atom = NULL;
928 }
929 
930 
931 /*
932  * Reset the table: empty it
933  */
reset_atom_table(atom_table_t * tbl)934 static void reset_atom_table(atom_table_t *tbl) {
935   tbl->natoms = 0;
936   clear_bitvector(tbl->has_atom, tbl->size);
937 }
938 
939 
940 
941 
942 /*
943  * Attach atom atm to variable v:
944  * - v must not have an atom attached already and there must be enough
945  * room in tbl for variable v (i.e., tbl must be resized before this
946  * function is called).
947  */
add_atom(atom_table_t * tbl,bvar_t v,void * atm)948 static void add_atom(atom_table_t *tbl, bvar_t v, void *atm) {
949   assert(v < tbl->size && !tst_bit(tbl->has_atom, v));
950   set_bit(tbl->has_atom, v);
951   tbl->atom[v] = atm;
952   tbl->natoms ++;
953 }
954 
955 
956 /*
957  * Remove the atom attached to v
958  */
remove_atom(atom_table_t * tbl,bvar_t v)959 static void remove_atom(atom_table_t *tbl, bvar_t v) {
960   assert(v < tbl->size && tst_bit(tbl->has_atom, v));
961   clr_bit(tbl->has_atom, v);
962   tbl->atom[v] = NULL;
963   tbl->natoms --;
964 }
965 
966 
967 
968 
969 /*****************
970  *  LEMMA QUEUE  *
971  ****************/
972 
973 /*
974  * Initialize queue: nothing is allocated yet
975  */
init_lemma_queue(lemma_queue_t * queue)976 static void init_lemma_queue(lemma_queue_t *queue) {
977   queue->capacity = 0;
978   queue->nblocks = 0;
979   queue->free_block = 0;
980   queue->block = NULL;
981 }
982 
983 /*
984  * Delete all allocated blocks and the array queue->block
985  */
delete_lemma_queue(lemma_queue_t * queue)986 static void delete_lemma_queue(lemma_queue_t *queue) {
987   uint32_t i;
988 
989   for (i=0; i<queue->nblocks; i++) {
990     safe_free(queue->block[i]);
991   }
992   safe_free(queue->block);
993   queue->block = NULL;
994 }
995 
996 
997 /*
998  * Increase capacity: increase the size of the block array
999  */
increase_lemma_queue_capacity(lemma_queue_t * queue)1000 static void increase_lemma_queue_capacity(lemma_queue_t *queue) {
1001   uint32_t  n;
1002 
1003   n = 2 * queue->capacity; // new capacity
1004   if (n == 0) {
1005     n = DEF_LEMMA_BLOCKS;
1006   }
1007 
1008   if (n >= MAX_LEMMA_BLOCKS) {
1009     out_of_memory();
1010   }
1011 
1012   queue->block = (lemma_block_t **) safe_realloc(queue->block, n * sizeof(lemma_block_t *));
1013   queue->capacity = n;
1014 }
1015 
1016 
1017 /*
1018  * Allocate a block of the given size
1019  */
new_lemma_block(uint32_t size)1020 static lemma_block_t *new_lemma_block(uint32_t size) {
1021   lemma_block_t *tmp;
1022 
1023   if (size >= MAX_LEMMA_BLOCK_SIZE) {
1024     out_of_memory();
1025   }
1026 
1027   tmp = (lemma_block_t *) safe_malloc(sizeof(lemma_block_t) + size * sizeof(literal_t));
1028   tmp->size = size;
1029   tmp->ptr = 0;
1030 
1031   return tmp;
1032 }
1033 
1034 
1035 /*
1036  * Find a block b that has space for n literals (i.e., b->size - b->ptr >= n)
1037  * - use the top_block if that works, otherwise use the next block
1038  * - allocate blocks if necessary
1039  */
find_block_for_lemma(lemma_queue_t * queue,uint32_t n)1040 static lemma_block_t *find_block_for_lemma(lemma_queue_t *queue, uint32_t n) {
1041   uint32_t i, j;
1042   lemma_block_t *tmp;
1043 
1044   /*
1045    * invariants:
1046    * 0 <= free_block <= nblocks <= capacity
1047    * block has size = capacity
1048    * if 0 <= i < free_block-1 then block[i] is full
1049    * if free_block > 0, then block[free_block-1] is not empty and not full
1050    * if free_block <= i < nblocks then block[i] is allocated and empty
1051    * if nblocks <= i < capacity then block[i] is not allocated
1052    */
1053   i = queue->free_block;
1054   if (i > 0) {
1055     // try the current block
1056     tmp = queue->block[i-1];
1057     assert(tmp != NULL && tmp->ptr > 0);
1058     if (tmp->size - tmp->ptr >= n) return tmp;
1059   }
1060 
1061   // current block does not exist or it's full.
1062   // search for a large enough block among block[free_blocks ... nblocks-1]
1063   for (j=i; j<queue->nblocks; j++) {
1064     tmp = queue->block[j];
1065     assert(tmp != NULL && tmp->ptr == 0);
1066     if (tmp->size >= n) {
1067       // swap block[i] and block[j]
1068       queue->block[j] = queue->block[i];
1069       queue->block[i] = tmp;
1070       queue->free_block ++;
1071       return tmp;
1072     }
1073   }
1074 
1075   // we need to allocate a new block, large enough for n literals
1076   if (n < DEF_LEMMA_BLOCK_SIZE) {
1077     n = DEF_LEMMA_BLOCK_SIZE;
1078   }
1079   tmp = new_lemma_block(n);
1080 
1081   // make room in queue->block if necessary
1082   j = queue->nblocks;
1083   if (j >= queue->capacity) {
1084     increase_lemma_queue_capacity(queue);
1085     assert(queue->nblocks < queue->capacity);
1086   }
1087 
1088   queue->block[j] = queue->block[i];
1089   queue->block[i] = tmp;
1090   queue->free_block ++;
1091   queue->nblocks ++;
1092 
1093   return tmp;
1094 }
1095 
1096 
1097 /*
1098  * Push literal array a[0] ... a[n-1] as a lemma
1099  */
push_lemma(lemma_queue_t * queue,uint32_t n,literal_t * a)1100 static void push_lemma(lemma_queue_t *queue, uint32_t n, literal_t *a) {
1101   lemma_block_t *blk;
1102   uint32_t i;
1103   literal_t *b;
1104 
1105   blk = find_block_for_lemma(queue, n+1);
1106   assert(queue->free_block > 0 && blk == queue->block[queue->free_block-1]
1107          && blk->ptr + n < blk->size);
1108 
1109   b = blk->data + blk->ptr;
1110   for (i=0; i<n; i++) {
1111     b[i] = a[i];
1112   }
1113   b[i] = null_literal; // end-marker;
1114   i++;
1115   blk->ptr += i;
1116 }
1117 
1118 
1119 
1120 
1121 
1122 /*
1123  * Empty the queue
1124  */
reset_lemma_queue(lemma_queue_t * queue)1125 static void reset_lemma_queue(lemma_queue_t *queue) {
1126   uint32_t i;
1127 
1128   if (queue->nblocks > LEMMA_BLOCKS_TO_KEEP) {
1129     // keep 4 blocks, delete the others to save memory
1130     for (i=0; i<LEMMA_BLOCKS_TO_KEEP; i++) {
1131       queue->block[i]->ptr = 0;
1132     }
1133     while (i < queue->nblocks) {
1134       safe_free(queue->block[i]);
1135       queue->block[i] = NULL;
1136       i ++;
1137     }
1138     queue->nblocks = LEMMA_BLOCKS_TO_KEEP;
1139 
1140   } else {
1141     // keep all the allocated blocks
1142     for (i=0; i<queue->nblocks; i++) {
1143       queue->block[i]->ptr = 0;
1144     }
1145   }
1146   queue->free_block = 0;
1147 }
1148 
1149 
1150 /*
1151  * Check whether the queue is empty
1152  */
empty_lemma_queue(lemma_queue_t * queue)1153 static inline bool empty_lemma_queue(lemma_queue_t *queue) {
1154   return queue->free_block == 0;
1155 }
1156 
1157 
1158 
1159 
1160 
1161 /************************
1162  *   CHECKPOINT STACK   *
1163  ***********************/
1164 
1165 /*
1166  * Initialization: nothing is allocated
1167  */
init_checkpoint_stack(checkpoint_stack_t * stack)1168 static void init_checkpoint_stack(checkpoint_stack_t *stack) {
1169   stack->size = 0;
1170   stack->top = 0;
1171   stack->data = NULL;
1172 }
1173 
1174 /*
1175  * Delete
1176  */
delete_checkpoint_stack(checkpoint_stack_t * stack)1177 static void delete_checkpoint_stack(checkpoint_stack_t *stack) {
1178   safe_free(stack->data);
1179   stack->data = NULL;
1180 }
1181 
1182 
1183 /*
1184  * Increase the size
1185  */
extend_checkpoint_stack(checkpoint_stack_t * stack)1186 static void extend_checkpoint_stack(checkpoint_stack_t *stack) {
1187   uint32_t n;
1188 
1189   n = stack->size;
1190   n += n>>1;     // make it 50% larger
1191   if (n == 0) {
1192     // first allocation
1193     n = DEF_CHECKPOINT_STACK_SIZE;
1194   }
1195 
1196   if (n >= MAX_CHECKPOINT_STACK_SIZE) {
1197     out_of_memory();
1198   }
1199 
1200   stack->data = (checkpoint_t *) safe_realloc(stack->data, n * sizeof(checkpoint_t));
1201   stack->size = n;
1202 }
1203 
1204 
1205 /*
1206  * Check whether the stack is empty
1207  */
empty_checkpoint_stack(checkpoint_stack_t * stack)1208 static inline bool empty_checkpoint_stack(checkpoint_stack_t *stack) {
1209   return stack->top == 0;
1210 }
1211 
non_empty_checkpoint_stack(checkpoint_stack_t * stack)1212 static inline bool non_empty_checkpoint_stack(checkpoint_stack_t *stack) {
1213   return stack->top > 0;
1214 }
1215 
1216 
1217 /*
1218  * Get the top checkpoint
1219  */
top_checkpoint(checkpoint_stack_t * stack)1220 static inline checkpoint_t *top_checkpoint(checkpoint_stack_t *stack) {
1221   assert(non_empty_checkpoint_stack(stack));
1222   return stack->data + (stack->top - 1);
1223 }
1224 
1225 /*
1226  * Remove the top checkpoint
1227  */
pop_checkpoint(checkpoint_stack_t * stack)1228 static inline void pop_checkpoint(checkpoint_stack_t *stack) {
1229   assert(non_empty_checkpoint_stack(stack));
1230   stack->top --;
1231 }
1232 
1233 /*
1234  * Push a checkpoint
1235  * - d = decision level,
1236  * - n = number of terms
1237  */
push_checkpoint(checkpoint_stack_t * stack,uint32_t d,uint32_t n)1238 static void push_checkpoint(checkpoint_stack_t *stack, uint32_t d, uint32_t n) {
1239   uint32_t i;
1240 
1241   i = stack->top;
1242   if (i >= stack->size) {
1243     extend_checkpoint_stack(stack);
1244     assert(i < stack->size);
1245   }
1246   stack->data[i].dlevel = d;
1247   stack->data[i].nvars = n;
1248   stack->top = i+1;
1249 }
1250 
1251 
1252 /*
1253  * Reset: empty the stack
1254  */
reset_checkpoint_stack(checkpoint_stack_t * stack)1255 static inline void reset_checkpoint_stack(checkpoint_stack_t *stack) {
1256   stack->top = 0;
1257 }
1258 
1259 
1260 
1261 
1262 
1263 
1264 /************************
1265  *  STATISTICS RECORD   *
1266  ***********************/
1267 
1268 
1269 /*
1270  * Initialize a statistics record
1271  */
init_statistics(dpll_stats_t * stat)1272 static void init_statistics(dpll_stats_t *stat) {
1273   stat->restarts = 0;
1274   stat->simplify_calls = 0;
1275   stat->reduce_calls = 0;
1276   stat->remove_calls = 0;
1277   stat->decisions = 0;
1278   stat->random_decisions = 0;
1279   stat->propagations = 0;
1280   stat->conflicts = 0;
1281   stat->th_props = 0;
1282   stat->th_prop_lemmas = 0;
1283   stat->th_conflicts = 0;
1284   stat->th_conflict_lemmas = 0;
1285   stat->prob_literals = 0;
1286   stat->learned_literals = 0;
1287   stat->prob_clauses_deleted = 0;
1288   stat->learned_clauses_deleted = 0;
1289   stat->bin_clauses_deleted = 0;
1290   stat->literals_before_simpl = 0;
1291   stat->subsumed_literals = 0;
1292 }
1293 
1294 
1295 /*
1296  * Reset = same thing as init
1297  */
reset_statistics(dpll_stats_t * stats)1298 static inline void reset_statistics(dpll_stats_t *stats) {
1299   init_statistics(stats);
1300 }
1301 
1302 
1303 
1304 /**********************************
1305  *  EXPERIMENTAL: EQUALITY TABLE  *
1306  *********************************/
1307 
1308 #if 0
1309 
1310 /*
1311  * Allocate and initialize the etable
1312  */
1313 void smt_core_make_etable(smt_core_t *s) {
1314   booleq_table_t *tmp;
1315 
1316   assert(s->etable == NULL);
1317   tmp = (booleq_table_t *) safe_malloc(sizeof(booleq_table_t));
1318   init_booleq_table(tmp);
1319   s->etable = tmp;
1320 }
1321 
1322 
1323 /*
1324  * Record l = (xor a b)
1325  */
1326 void smt_core_record_xor_def(smt_core_t *s, literal_t l, literal_t a, literal_t b) {
1327   assert(s->etable != NULL);
1328   booleq_table_record_xor(s->etable, l, a, b);
1329 
1330   print_literal(stdout, l);
1331   printf(" := (xor ");
1332   print_literal(stdout, a);
1333   printf(" ");
1334   print_literal(stdout, b);
1335   printf(")\n");
1336 }
1337 
1338 
1339 /*
1340  * Delete the table if any
1341  */
1342 static void delete_etable(smt_core_t *s) {
1343   if (s->etable != NULL) {
1344     delete_booleq_table(s->etable);
1345     safe_free(s->etable);
1346     s->etable = NULL;
1347   }
1348 }
1349 
1350 
1351 /*
1352  * Reset it
1353  */
1354 static void reset_etable(smt_core_t *s) {
1355   if (s->etable != NULL) {
1356     reset_booleq_table(s->etable);
1357   }
1358 }
1359 
1360 
1361 /*
1362  * Display details about a learned clause if it contains
1363  * at least two xor or equality atoms
1364  */
1365 static void test_eq_clause(smt_core_t *s, const char *msg, uint32_t n, literal_t *a) {
1366   uint32_t i, neq;
1367   literal_t u, v;
1368 
1369   assert(s->etable != NULL);
1370 
1371   neq = 0;
1372   for (i=0; i<n; i++) {
1373     if (literal_is_eq(s->etable, a[i])) {
1374       neq ++;
1375     }
1376   }
1377 
1378   if (neq >= 0) {
1379     printf("\n--- Learned clause %"PRIu64" %s ---\n", s->stats.conflicts, msg);
1380     printf("{");
1381     for (i=0; i<n; i++) {
1382       printf(" ");
1383       print_literal(stdout, a[i]);
1384     }
1385     printf(" }\n");
1386 
1387     for (i=0; i<n; i++) {
1388       if (get_booleq(s->etable, not(a[i]), &u, &v)) {
1389 	print_literal(stdout, not(a[i]));
1390 	printf(" := (eq ");
1391 	print_literal(stdout, u);
1392 	printf(" ");
1393 	print_literal(stdout, v);
1394 	printf(")\n");
1395       }
1396     }
1397     printf("\n");
1398   }
1399 }
1400 
1401 
1402 /*
1403  * Same thing for the conflict clause
1404  */
1405 static void test_eq_conflict(smt_core_t *s) {
1406   literal_t *c;
1407   literal_t u, v;
1408 
1409   assert(s->etable != NULL);
1410 
1411   if (! s->theory_conflict) {
1412     c = s->conflict;
1413     printf("\n--- Conflict %"PRIu64" ---\n", s->stats.conflicts);
1414     printf("{");
1415     while (*c >= 0) {
1416       printf(" ");
1417       print_literal(stdout, *c);
1418       c ++;
1419     }
1420     printf(" }\n");
1421 
1422     c = s->conflict;
1423     while (*c >= 0) {
1424       if (get_booleq(s->etable, not(*c), &u, &v)) {
1425 	print_literal(stdout, not(*c));
1426 	printf(" := (eq ");
1427 	print_literal(stdout, u);
1428 	printf(" ");
1429 	print_literal(stdout, v);
1430 	printf(")\n");
1431       }
1432       c ++;
1433     }
1434   }
1435 }
1436 
1437 #endif
1438 
1439 
1440 /************************
1441  *  GENERAL OPERATIONS  *
1442  ***********************/
1443 
1444 /*
1445  * Initialize an smt core
1446  * - n = initial vsize = size of the variable-indexed arrays
1447  * - th = theory solver
1448  * - ctrl = descriptor of control functions for th
1449  * - smt = descriptor of the SMT functions for th
1450  * - mode = to select optional features
1451  * This creates the predefined "constant" variable and the true/false literals
1452  *
1453  * The clause and variable activity increments, and the randomness
1454  * parameters are set to their default values
1455  */
init_smt_core(smt_core_t * s,uint32_t n,void * th,th_ctrl_interface_t * ctrl,th_smt_interface_t * smt,smt_mode_t mode)1456 void init_smt_core(smt_core_t *s, uint32_t n, void *th,
1457                    th_ctrl_interface_t *ctrl, th_smt_interface_t *smt,
1458                    smt_mode_t mode) {
1459   uint32_t lsize;
1460 
1461   s->th_solver = th;
1462   s->th_ctrl = *ctrl; // make a full copy
1463   s->th_smt = *smt;   // ditto
1464   s->bool_only = false;
1465 
1466   s->status = STATUS_IDLE;
1467 
1468   switch (mode) {
1469   case SMT_MODE_BASIC:
1470     s->option_flag = 0;
1471     break;
1472 
1473   case SMT_MODE_PUSHPOP:
1474     s->option_flag = PUSH_POP_MASK;
1475     break;
1476 
1477   default:
1478     s->option_flag = PUSH_POP_MASK|CLEAN_INTERRUPT_MASK;
1479     break;
1480   }
1481 
1482   // ensure there's room for the constants
1483   if (n == 0) n = 1;
1484   lsize = 2 * n;
1485 
1486   if (n >= MAX_VARIABLES) {
1487     out_of_memory();
1488   }
1489 
1490   // counters
1491   s->nvars = 1;
1492   s->nlits = 2;
1493   s->vsize = n;
1494   s->lsize = lsize;
1495 
1496   s->nb_clauses = 0;
1497   s->nb_prob_clauses = 0;
1498   s->nb_bin_clauses = 0;
1499   s->nb_unit_clauses = 0;
1500 
1501   s->simplify_bottom = 0;
1502   s->simplify_props = 0;
1503   s->simplify_threshold = 0;
1504 
1505   s->aux_literals = 0;
1506   s->aux_clauses = 0;
1507 
1508   s->decision_level = 0;
1509   s->base_level = 0;
1510 
1511   // heuristic parameters
1512   s->cla_inc = INIT_CLAUSE_ACTIVITY_INCREMENT;
1513   s->inv_cla_decay = 1/CLAUSE_DECAY_FACTOR;
1514   s->prng = CORE_PRNG_SEED;
1515   s->scaled_random = (uint32_t) (VAR_RANDOM_FACTOR * VAR_RANDOM_SCALE);
1516 
1517   // theory caching: disabled initially
1518   s->th_cache_enabled = false;
1519   s->th_cache_cl_size = 0;
1520 
1521   // conflict data: no need to initialize conflict_buffer
1522   s->inconsistent = false;
1523   s->theory_conflict = false;
1524   s->conflict = NULL;
1525   s->false_clause = NULL;
1526 
1527   // auxiliary buffers
1528   init_ivector(&s->buffer, DEF_LBUFFER_SIZE);
1529   init_ivector(&s->buffer2, DEF_LBUFFER_SIZE);
1530   init_ivector(&s->explanation, DEF_LBUFFER_SIZE);
1531 
1532   // assumptions
1533   s->has_assumptions = false;
1534   s->num_assumptions = 0;
1535   s->assumption_index = 0;
1536   s->assumptions = NULL;
1537   s->bad_assumption = null_literal;
1538 
1539   // clause database: all empty
1540   s->problem_clauses = new_clause_vector(DEF_CLAUSE_VECTOR_SIZE);
1541   s->learned_clauses = new_clause_vector(DEF_CLAUSE_VECTOR_SIZE);
1542   init_ivector(&s->binary_clauses, 0);
1543 
1544 
1545   /*
1546    * Variable-indexed arrays
1547    *
1548    * level and value are indexed from -1 to n-1
1549    * level[-1] = UINT32_MAX (never assigned, marker variable)
1550    * value[-1] = VAL_UNDEF_FALSE (not assigned)
1551    */
1552   s->value = (uint8_t *) safe_malloc((n + 1) * sizeof(uint8_t)) + 1;
1553   s->antecedent = (antecedent_t *) safe_malloc(n * sizeof(antecedent_t));
1554   s->level = (uint32_t *) safe_malloc((n + 1) * sizeof(uint32_t)) + 1;
1555   s->mark = allocate_bitvector(n);
1556   s->level[-1] = UINT32_MAX;
1557   s->value[-1] = VAL_UNDEF_FALSE;
1558 
1559   /*
1560    * Literal-indexed arrays
1561    */
1562   s->bin = (literal_t **) safe_malloc(lsize * sizeof(literal_t *));
1563   s->watch = (link_t *) safe_malloc(lsize * sizeof(link_t));
1564 
1565   /*
1566    * Initialize data structures for true_literal and false_literal
1567    */
1568   assert(const_bvar == 0 && true_literal == 0 && false_literal == 1 && s->nvars > 0);
1569   s->level[const_bvar] = 0;
1570   s->value[const_bvar] = VAL_TRUE;
1571   set_bit(s->mark, const_bvar);
1572   assert(literal_value(s, true_literal) == VAL_TRUE &&
1573 	 literal_value(s, false_literal) == VAL_FALSE);
1574 
1575   s->bin[true_literal] = NULL;
1576   s->bin[false_literal] = NULL;
1577   s->watch[true_literal] = NULL_LINK;
1578   s->watch[false_literal] = NULL_LINK;
1579 
1580   init_stack(&s->stack, n);
1581   init_heap(&s->heap, n);
1582   init_lemma_queue(&s->lemmas);
1583   init_statistics(&s->stats);
1584   init_atom_table(&s->atoms);
1585   init_gate_table(&s->gates);
1586   init_trail_stack(&s->trail_stack);
1587   init_checkpoint_stack(&s->checkpoints);
1588   s->cp_flag = false;
1589 
1590   s->etable = NULL;
1591   s->trace = NULL;
1592 
1593   s->interrupt_push = false;
1594 }
1595 
1596 
1597 
1598 /*
1599  * Replace the theory solver and interface descriptors
1600  * - this can used provided no atom/clause has been added yet
1601  */
smt_core_reset_thsolver(smt_core_t * s,void * th,th_ctrl_interface_t * ctrl,th_smt_interface_t * smt)1602 void smt_core_reset_thsolver(smt_core_t *s, void *th, th_ctrl_interface_t *ctrl,
1603 			     th_smt_interface_t *smt) {
1604   s->th_solver = th;
1605   s->th_ctrl = *ctrl; // make a full copy
1606   s->th_smt = *smt;   // ditto
1607 }
1608 
1609 
1610 /*
1611  * Delete: free all allocated memory
1612  */
delete_smt_core(smt_core_t * s)1613 void delete_smt_core(smt_core_t *s) {
1614   uint32_t i, n;
1615   clause_t **cl;
1616 
1617   delete_ivector(&s->buffer);
1618   delete_ivector(&s->buffer2);
1619   delete_ivector(&s->explanation);
1620 
1621   // Delete all the clauses
1622   cl = s->problem_clauses;
1623   n = get_cv_size(cl);
1624   for (i=0; i<n; i++) {
1625     delete_clause(cl[i]);
1626   }
1627   delete_clause_vector(cl);
1628 
1629   cl = s->learned_clauses;
1630   n = get_cv_size(cl);
1631   for (i=0; i<n; i++) {
1632     delete_learned_clause(cl[i]);
1633   }
1634   delete_clause_vector(cl);
1635 
1636   delete_ivector(&s->binary_clauses);
1637 
1638   // var-indexed arrays
1639   safe_free(s->value - 1);
1640   safe_free(s->antecedent);
1641   safe_free(s->level - 1);
1642   delete_bitvector(s->mark);
1643 
1644   // literal-indexed arrays
1645   n = s->nlits;
1646   for (i=0; i<n; i++) {
1647     delete_literal_vector(s->bin[i]);
1648   }
1649   safe_free(s->bin);
1650   safe_free(s->watch);
1651 
1652   delete_stack(&s->stack);
1653   delete_heap(&s->heap);
1654   delete_lemma_queue(&s->lemmas);
1655   delete_atom_table(&s->atoms);
1656   delete_gate_table(&s->gates);
1657   delete_trail_stack(&s->trail_stack);
1658   delete_checkpoint_stack(&s->checkpoints);
1659 
1660   // EXPERIMENTAL
1661   //  delete_etable(s);
1662 }
1663 
1664 
1665 /*
1666  * Reset: remove all variables, atoms, and clauses
1667  * - also calls reset on the attached theory solver
1668  * - we don't call atom_deleted for the solver.
1669  */
reset_smt_core(smt_core_t * s)1670 void reset_smt_core(smt_core_t *s) {
1671   uint32_t i, n;
1672   clause_t **cl;
1673 
1674   s->status = STATUS_IDLE;
1675 
1676   // reset buffers
1677   ivector_reset(&s->buffer);
1678   ivector_reset(&s->buffer2);
1679   ivector_reset(&s->explanation);
1680 
1681   // assumptions
1682   s->has_assumptions = false;
1683   s->num_assumptions = 0;
1684   s->assumption_index = 0;
1685   s->assumptions = NULL;
1686   s->bad_assumption = null_literal;
1687 
1688   // delete the clauses
1689   cl = s->problem_clauses;
1690   n = get_cv_size(cl);
1691   for (i=0; i<n; i++) {
1692     delete_clause(cl[i]);
1693   }
1694   reset_clause_vector(cl);
1695 
1696   cl = s->learned_clauses;
1697   n = get_cv_size(cl);
1698   for (i=0; i<n; i++) {
1699     delete_learned_clause(cl[i]);
1700   }
1701   reset_clause_vector(cl);
1702 
1703   ivector_reset(&s->binary_clauses);
1704 
1705   // delete binary-watched literal vectors
1706   n = s->nlits;
1707   for (i=0; i<n; i++) {
1708     delete_literal_vector(s->bin[i]);
1709   }
1710 
1711   reset_stack(&s->stack);
1712   reset_heap(&s->heap);
1713   reset_lemma_queue(&s->lemmas);
1714   reset_statistics(&s->stats);
1715   reset_atom_table(&s->atoms);
1716   reset_gate_table(&s->gates);
1717   reset_trail_stack(&s->trail_stack);
1718   reset_checkpoint_stack(&s->checkpoints);
1719   s->cp_flag = false;
1720 
1721   // reset all counters
1722   s->nvars = 1;
1723   s->nlits = 2;
1724   s->nb_clauses = 0;
1725   s->nb_prob_clauses = 0;  // fixed 2010/08/10 (was missing)
1726   s->nb_bin_clauses = 0;
1727   s->nb_unit_clauses = 0;
1728   s->simplify_bottom = 0;
1729   s->simplify_props = 0;
1730   s->simplify_threshold = 0;
1731   s->decision_level = 0;
1732   s->base_level = 0;
1733 
1734   // heuristic parameters: it makes a difference to reset cla_inc
1735   s->cla_inc = INIT_CLAUSE_ACTIVITY_INCREMENT;
1736   s->inv_cla_decay = 1/CLAUSE_DECAY_FACTOR;
1737   s->prng = CORE_PRNG_SEED;
1738   s->scaled_random = (uint32_t) (VAR_RANDOM_FACTOR * VAR_RANDOM_SCALE);
1739 
1740   // reset conflict data
1741   s->inconsistent = false;
1742   s->theory_conflict = false;
1743   s->conflict = NULL;
1744   s->false_clause = NULL;
1745 
1746   // reset the theory solver
1747   s->th_ctrl.reset(s->th_solver);
1748 
1749   // EXPERIMENTAL
1750   //  reset_etable(s);
1751 
1752   s->interrupt_push = false;
1753 }
1754 
1755 
1756 
1757 /*
1758  * Extend solver: make room for more variables
1759  * - n = new vsize
1760  */
extend_smt_core(smt_core_t * s,uint32_t n)1761 static void extend_smt_core(smt_core_t *s, uint32_t n) {
1762   uint32_t lsize;
1763 
1764   assert(n >= s->vsize);
1765 
1766   if (n >= MAX_VARIABLES) {
1767     out_of_memory();
1768   }
1769 
1770   lsize = 2 * n;
1771   s->vsize = n;
1772   s->lsize = lsize;
1773 
1774   s->value = (uint8_t *) safe_realloc(s->value - 1, (n + 1) * sizeof(uint8_t)) + 1;
1775   s->antecedent = (antecedent_t *) safe_realloc(s->antecedent, n * sizeof(antecedent_t));
1776   s->level = (uint32_t *) safe_realloc(s->level - 1, (n + 1) * sizeof(uint32_t)) + 1;
1777   s->mark = extend_bitvector(s->mark, n);
1778 
1779   s->bin = (literal_t **) safe_realloc(s->bin, lsize * sizeof(literal_t *));
1780   s->watch = (link_t *) safe_realloc(s->watch, lsize * sizeof(link_t));
1781 
1782   extend_heap(&s->heap, n);
1783   extend_stack(&s->stack, n);
1784 }
1785 
1786 
1787 
1788 /*
1789  * Change the heuristic parameters:
1790  * - must not be called when search is under way
1791  * - factor must be between 0 and 1.0
1792  */
set_var_decay_factor(smt_core_t * s,double factor)1793 void set_var_decay_factor(smt_core_t *s, double factor) {
1794   assert(s->status != STATUS_SEARCHING && 0.0 < factor && factor < 1.0);
1795   s->heap.inv_act_decay = 1/factor;
1796 }
1797 
set_clause_decay_factor(smt_core_t * s,float factor)1798 void set_clause_decay_factor(smt_core_t *s, float factor) {
1799   assert(s->status != STATUS_SEARCHING && 0.0F < factor && factor < 1.0F);
1800   s->inv_cla_decay = 1/factor;
1801 }
1802 
set_randomness(smt_core_t * s,float random_factor)1803 void set_randomness(smt_core_t *s, float random_factor) {
1804   assert(s->status != STATUS_SEARCHING && 0.0F <= random_factor && random_factor < 1.0F);
1805   s->scaled_random = (uint32_t)(random_factor * VAR_RANDOM_SCALE);
1806 }
1807 
1808 
1809 /*
1810  * Set the internal seed
1811  */
set_random_seed(smt_core_t * s,uint32_t x)1812 void set_random_seed(smt_core_t *s, uint32_t x) {
1813   s->prng = x;
1814 }
1815 
1816 
1817 /*
1818  * Set the trace file
1819  */
smt_core_set_trace(smt_core_t * s,tracer_t * tracer)1820 void smt_core_set_trace(smt_core_t *s, tracer_t *tracer) {
1821   assert(s->trace == NULL);
1822   s->trace = tracer;
1823 }
1824 
1825 
avg_learned_clause_size(smt_core_t * core)1826 extern double avg_learned_clause_size(smt_core_t *core) {
1827   uint32_t num_clauses;
1828   double r;
1829 
1830   r = 0.0;
1831   num_clauses = num_learned_clauses(core);
1832   if (num_clauses > 0) {
1833     r = ((double) num_learned_literals(core)) /num_clauses;
1834   }
1835   return r;
1836 }
1837 
1838 
1839 
1840 /**************************
1841  *  VARIABLE ALLOCATION   *
1842  *************************/
1843 
1844 /*
1845  * Initialize all arrays for a new variable x
1846  * - antecedent[x] = NULL
1847  * - level[x] = UINT32_MAX
1848  * - mark[x] = 0
1849  * - value[x] = VAL_UNDEF_FALSE (negative polarity preferred)
1850  * - activity[x] = 0 (in heap)
1851  *
1852  * For l=pos_lit(x) and neg_lit(x):
1853  * - bin[l] = NULL
1854  * - watch[l] = NULL
1855  */
init_variable(smt_core_t * s,bvar_t x)1856 static void init_variable(smt_core_t *s, bvar_t x) {
1857   literal_t l0, l1;
1858 
1859   clr_bit(s->mark, x);
1860   s->value[x] = VAL_UNDEF_FALSE;
1861   s->antecedent[x] = mk_literal_antecedent(null_literal);
1862   s->level[x] = UINT32_MAX;
1863 
1864   // HACK for testing initial order
1865   //  assert(s->heap.heap_index[x] < 0);
1866   //  s->heap.activity[x] = (10000.0/(x+1));
1867   // end of HACK
1868   assert(s->heap.heap_index[x] < 0);
1869   s->heap.activity[x] = 0.0;
1870 
1871 #if 0
1872   printf("bvar %"PRId32": activity = %f\n", x, s->heap.activity[x]);
1873 #endif
1874   heap_insert(&s->heap, x);
1875 
1876   l0 = pos_lit(x);
1877   l1 = neg_lit(x);
1878   s->bin[l0] = NULL;
1879   s->bin[l1] = NULL;
1880   s->watch[l0] = NULL_LINK;
1881   s->watch[l1] = NULL_LINK;
1882 }
1883 
1884 /*
1885  * Create a fresh variable and return its index
1886  * - the index is x = s->nvars
1887  */
create_boolean_variable(smt_core_t * s)1888 bvar_t create_boolean_variable(smt_core_t *s) {
1889   uint32_t new_size, i;
1890 
1891   i = s->nvars;
1892   if (i >= s->vsize) {
1893     new_size = s->vsize + 1;
1894     new_size += new_size >> 1;
1895     extend_smt_core(s, new_size);
1896     assert(i < s->vsize);
1897   }
1898 
1899   init_variable(s, i);
1900   s->nvars ++;
1901   s->nlits += 2;
1902 
1903   return i;
1904 }
1905 
1906 /*
1907  * Add n fresh boolean variables: indices are allocated starting
1908  * from s->nvars (i.e., if s->nvars == v before the call, the
1909  * new variables have indices v, v+1, ... v+n-1).
1910  */
add_boolean_variables(smt_core_t * s,uint32_t n)1911 void add_boolean_variables(smt_core_t *s, uint32_t n) {
1912   uint32_t nv, new_size, i;
1913 
1914   nv = s->nvars;
1915   if (nv + n > s->vsize) {
1916     new_size = s->vsize + 1;
1917     new_size += new_size >> 1;
1918     if (new_size < nv + n) {
1919       new_size = nv + n;
1920     }
1921     extend_smt_core(s, new_size);
1922     assert(nv + n <= s->vsize);
1923   }
1924 
1925   for (i=nv; i<nv+n; i++) {
1926     init_variable(s, i);
1927   }
1928 
1929   s->nvars += n;
1930   s->nlits += 2 * n;
1931 }
1932 
1933 
1934 
1935 /*
1936  * Attach atom a to boolean variable x
1937  * - x must not have an atom attached already
1938  */
attach_atom_to_bvar(smt_core_t * s,bvar_t x,void * atom)1939 void attach_atom_to_bvar(smt_core_t *s, bvar_t x, void *atom) {
1940   atom_table_t *tbl;
1941 
1942   tbl = &s->atoms;
1943   if (tbl->size <= x) {
1944     // make atom table as large as s->vsize
1945     resize_atom_table(tbl, s->vsize);
1946   }
1947   add_atom(tbl, x, atom);
1948 }
1949 
1950 
1951 /*
1952  * Check whether x has an atom attached
1953  */
bvar_has_atom(smt_core_t * s,bvar_t x)1954 bool bvar_has_atom(smt_core_t *s, bvar_t x) {
1955   atom_table_t *tbl;
1956 
1957   assert(0 <= x && x < s->nvars);
1958   tbl = &s->atoms;
1959   return x < tbl->size && tst_bit(tbl->has_atom, x);
1960 }
1961 
1962 
1963 /*
1964  * Return the atom attached to x (NULL if there's none)
1965  */
bvar_atom(smt_core_t * s,bvar_t x)1966 void *bvar_atom(smt_core_t *s, bvar_t x) {
1967   atom_table_t *tbl;
1968 
1969   assert(0 <= x && x < s->nvars);
1970   tbl = &s->atoms;
1971   if (x < tbl->size && tst_bit(tbl->has_atom, x)) {
1972     return tbl->atom[x];
1973   } else {
1974     return NULL;
1975   }
1976 }
1977 
1978 
1979 /*
1980  * Remove atom attached to x
1981  */
remove_bvar_atom(smt_core_t * s,bvar_t x)1982 void remove_bvar_atom(smt_core_t *s, bvar_t x) {
1983   atom_table_t *tbl;
1984 
1985   assert(0 <= x && x < s->nvars);
1986   tbl = &s->atoms;
1987   if (x < tbl->size && tst_bit(tbl->has_atom, x)) {
1988     remove_atom(tbl, x);
1989   }
1990 }
1991 
1992 
1993 /*
1994  * Set the initial activity of variable x
1995  */
set_bvar_activity(smt_core_t * s,bvar_t x,double a)1996 void set_bvar_activity(smt_core_t *s, bvar_t x, double a) {
1997   assert(0 <= x && x < s->nvars && a < DBL_MAX);
1998   heap_remove(&s->heap, x);
1999   s->heap.activity[x] = a;
2000   heap_insert(&s->heap, x);
2001 }
2002 
2003 
2004 
2005 
2006 
2007 /**************************
2008  *  VARIABLE ASSIGNMENTS  *
2009  *************************/
2010 
2011 /*
2012  * Assign literal l at the base level
2013  */
assign_literal(smt_core_t * s,literal_t l)2014 static void assign_literal(smt_core_t *s, literal_t l) {
2015   bvar_t v;
2016 
2017 #if TRACE
2018   printf("---> DPLL:   Assigning literal ");
2019   print_literal(stdout, l);
2020   printf(", decision level = %"PRIu32"\n", s->decision_level);
2021   fflush(stdout);
2022 #endif
2023   assert(0 <= l && l < s->nlits);
2024   assert(literal_is_unassigned(s, l));
2025   assert(s->decision_level == s->base_level);
2026 
2027   push_literal(&s->stack, l);
2028 
2029   v = var_of(l);
2030   s->value[v] = (VAL_TRUE ^ sign_of_lit(l));
2031   s->level[v] = s->base_level;
2032   s->antecedent[v] = mk_literal_antecedent(null_literal);
2033   set_bit(s->mark, v); // assigned at (or below) base_level
2034 
2035   assert(literal_value(s, l) == VAL_TRUE && literal_value(s, not(l)) == VAL_FALSE);
2036 }
2037 
2038 
2039 
2040 /*
2041  * Decide literal: increase decision level then
2042  * assign literal l to true and push it on the stack
2043  * - l must not be assigned
2044  */
decide_literal(smt_core_t * s,literal_t l)2045 void decide_literal(smt_core_t *s, literal_t l) {
2046   uint32_t k;
2047   bvar_t v;
2048 
2049   assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
2050   assert(literal_is_unassigned(s, l));
2051 
2052   // Increase decision level
2053   k = s->decision_level + 1;
2054   s->decision_level = k;
2055   if (s->stack.nlevels <= k) {
2056     increase_stack_levels(&s->stack);
2057   }
2058   s->stack.level_index[k] = s->stack.top;
2059 
2060   push_literal(&s->stack, l);
2061 
2062   v = var_of(l);
2063   s->value[v] = (VAL_TRUE ^ sign_of_lit(l));
2064   s->level[v] = k;
2065   s->antecedent[v] = mk_literal_antecedent(null_literal);
2066 
2067   assert(literal_value(s, l) == VAL_TRUE && literal_value(s, not(l)) == VAL_FALSE);
2068 
2069   // Notify the theory solver
2070   s->th_ctrl.increase_decision_level(s->th_solver);
2071 
2072   s->stats.decisions ++;
2073 
2074 #if TRACE
2075   printf("\n---> DPLL:   Decision: literal ");
2076   print_literal(stdout, l);
2077   printf(", decision level = %"PRIu32"\n", s->decision_level);
2078   fflush(stdout);
2079 #endif
2080 }
2081 
2082 
2083 /*
2084  * Assign literal l to true with the given antecedent
2085  * - s->mark[v] is set if decision level = base level
2086  */
implied_literal(smt_core_t * s,literal_t l,antecedent_t a)2087 static void implied_literal(smt_core_t *s, literal_t l, antecedent_t a) {
2088   bvar_t v;
2089 
2090   assert(literal_is_unassigned(s, l));
2091 
2092 #if TRACE
2093   printf("---> DPLL:   Implied literal ");
2094   print_literal(stdout, l);
2095   printf(", decision level = %"PRIu32"\n", s->decision_level);
2096   fflush(stdout);
2097 #endif
2098 
2099   s->stats.propagations ++;
2100 
2101   push_literal(&s->stack, l);
2102 
2103   v = var_of(l);
2104   s->value[v] = (VAL_TRUE ^ sign_of_lit(l));
2105   s->level[v] = s->decision_level;
2106   s->antecedent[v] = a;
2107   if (s->decision_level == s->base_level) {
2108     set_bit(s->mark, v);
2109     s->nb_unit_clauses ++;
2110   }
2111 
2112   assert(literal_value(s, l) == VAL_TRUE && literal_value(s, not(l)) == VAL_FALSE);
2113 }
2114 
2115 
propagate_literal(smt_core_t * s,literal_t l,void * expl)2116 void propagate_literal(smt_core_t *s, literal_t l, void *expl) {
2117   bvar_t v;
2118 
2119   assert(literal_is_unassigned(s, l));
2120   assert(bvar_has_atom(s, var_of(l)));
2121 
2122 #if TRACE
2123   printf("---> DPLL:   Theory prop ");
2124   print_literal(stdout, l);
2125   printf(", decision level = %"PRIu32"\n", s->decision_level);
2126   fflush(stdout);
2127 #endif
2128 
2129   s->stats.propagations ++;
2130   s->stats.th_props ++;
2131 
2132   push_literal(&s->stack, l);
2133 
2134   v = var_of(l);
2135   s->value[v] = (VAL_TRUE ^ sign_of_lit(l));
2136   s->level[v] = s->decision_level;
2137   s->antecedent[v] = mk_generic_antecedent(expl);
2138   if (s->decision_level == s->base_level) {
2139     set_bit(s->mark, v);
2140     s->nb_unit_clauses ++;
2141   }
2142 
2143   assert(literal_value(s, l) == VAL_TRUE && literal_value(s, not(l)) == VAL_FALSE);
2144 }
2145 
2146 
2147 
2148 
2149 /***************************
2150  *  HEURISTICS/ACTIVITIES  *
2151  **************************/
2152 
2153 /*
2154  * Select an unassigned literal: returns null_literal if all literals
2155  * are assigned. Use activity-based heuristic + randomization.
2156  */
select_unassigned_literal(smt_core_t * s)2157 literal_t select_unassigned_literal(smt_core_t *s) {
2158   uint32_t rnd;
2159   bvar_t x;
2160   uint8_t *v;
2161 
2162 #if DEBUG
2163   check_heap(s);
2164 #endif
2165 
2166   v = s->value;
2167 
2168   if (s->scaled_random > 0) {
2169     rnd = random_uint32(s) & VAR_RANDOM_MASK;
2170     if (rnd < s->scaled_random) {
2171       x = random_uint(s, s->nvars);
2172       assert(0 <= x && x < s->nvars);
2173       if (bval_is_undef(v[x])) {
2174 #if TRACE
2175 	printf("---> DPLL:   Random selection: variable ");
2176 	print_bvar(stdout, x);
2177 	printf("\n");
2178 	fflush(stdout);
2179 #endif
2180 	s->stats.random_decisions ++;
2181 	goto var_found;
2182       }
2183     }
2184   }
2185 
2186   /*
2187    * select unassigned variable x with highest activity
2188    */
2189   while (! heap_is_empty(&s->heap)) {
2190     x = heap_get_top(&s->heap);
2191     if (bval_is_undef(v[x])) {
2192       goto var_found;
2193     }
2194   }
2195 
2196   // empty heap
2197   return null_literal;
2198 
2199 
2200  var_found:
2201   // if polarity x == 1 use pos_lit(x) otherwise use neg_lit(x)
2202   return mk_signed_lit(x, v[x] & 1);
2203 }
2204 
2205 
2206 
2207 /*
2208  * Get the unassigned variable of highest activity
2209  * return null_bvar if all variables are assigned
2210  */
select_most_active_bvar(smt_core_t * s)2211 bvar_t select_most_active_bvar(smt_core_t *s) {
2212   bvar_t x;
2213   uint8_t *v;
2214 
2215   v = s->value;
2216   while (! heap_is_empty(&s->heap)) {
2217     x = heap_get_top(&s->heap);
2218     if (bval_is_undef(v[x])) {
2219       goto var_found;
2220     }
2221   }
2222 
2223   x = null_bvar;
2224 
2225  var_found:
2226   return x;
2227 }
2228 
2229 
2230 
2231 /*
2232  * Choose an unassigned variable randomly (uniformly)
2233  * return null_bvar if all variables are assigned
2234  */
select_random_bvar(smt_core_t * s)2235 bvar_t select_random_bvar(smt_core_t *s) {
2236   bvar_t x, y;
2237   uint8_t *v;
2238   uint32_t n, d;
2239 
2240   v = s->value;
2241   n = s->nvars;
2242   x = random_uint(s, n); // 0 ... n-1
2243   assert(0 <= x && x < n);
2244 
2245   if (bval_is_undef(v[x])) return x;
2246 
2247   if (all_variables_assigned(s)) return null_bvar;
2248 
2249   // d = random increment, must be prime with n.
2250   d = 1 + random_uint(s, n - 1); // 1 ... n-1
2251   while (gcd32(d, n) != 1) d--;
2252 
2253   // search in sequence x, x+d, x+2d, ... (modulo n)
2254   y = x;
2255   do {
2256     y += d;
2257     if (y > n) y -= n;
2258     assert(x != y); // don't loop
2259   } while (bval_is_def(v[y]));
2260 
2261   return y;
2262 }
2263 
2264 
2265 
2266 
2267 /*
2268  * Increase activity of variable x
2269  */
increase_bvar_activity(smt_core_t * s,bvar_t x)2270 static void increase_bvar_activity(smt_core_t *s, bvar_t x) {
2271   int32_t i;
2272   var_heap_t *heap;
2273 #if DEBUG
2274   bool rescaled = false;
2275 #endif
2276 
2277   heap = &s->heap;
2278   if ((heap->activity[x] += heap->act_increment) > VAR_ACTIVITY_THRESHOLD) {
2279     rescale_var_activities(heap, s->nvars);
2280 #if DEBUG
2281     rescaled = true;
2282 #endif
2283   }
2284 
2285   // move x up if it's in the heap
2286   i = heap->heap_index[x];
2287   if (i >= 0) {
2288     update_up(heap, x, i);
2289   }
2290 
2291 #if DEBUG
2292   if (rescaled) {
2293     check_heap(s);
2294   }
2295 #endif
2296 
2297 }
2298 
2299 
2300 
2301 /***********************
2302  *  CLAUSE ACTIVITIES  *
2303  **********************/
2304 
2305 /*
2306  * Rescale activity of all the learned clauses
2307  * (divide all by CLAUSE_ACTIVITY_THRESHOLD)
2308  */
rescale_clause_activities(smt_core_t * s)2309 static void rescale_clause_activities(smt_core_t *s) {
2310   uint32_t i, n;
2311   clause_t **v;
2312 
2313   s->cla_inc *= INV_CLAUSE_ACTIVITY_THRESHOLD;
2314   v = s->learned_clauses;
2315   n = get_cv_size(v);
2316   for (i=0; i<n; i++) {
2317     multiply_activity(v[i], INV_CLAUSE_ACTIVITY_THRESHOLD);
2318   }
2319 }
2320 
2321 
2322 /*
2323  * Increase activity of learned clause cl
2324  */
increase_clause_activity(smt_core_t * s,clause_t * cl)2325 static void increase_clause_activity(smt_core_t *s, clause_t *cl) {
2326   increase_activity(cl, s->cla_inc);
2327   if (get_activity(cl) > CLAUSE_ACTIVITY_THRESHOLD) {
2328     rescale_clause_activities(s);
2329   }
2330 }
2331 
2332 
2333 
2334 
2335 /*******************
2336  *  BACKTRACKING   *
2337  ******************/
2338 
2339 /*
2340  * Backtrack core to decision level back_level
2341  * - undo all literal assignments of level >= back_level + 1
2342  * - requires decision_level > back_level >= base_level
2343  * Also clear conflict data and sets cp_flag if deletion of atoms is enabled
2344  *
2345  * NOTE: this function does not force the theory solver to backtrack.
2346  */
backtrack(smt_core_t * s,uint32_t back_level)2347 static void backtrack(smt_core_t *s, uint32_t back_level) {
2348   uint32_t i, k;
2349   literal_t *u, l;
2350   bvar_t x;
2351 
2352 #if TRACE
2353   printf("---> DPLL:   Backtracking to level %"PRIu32"\n\n", back_level);
2354   fflush(stdout);
2355 #endif
2356 
2357   assert(s->base_level <= back_level && back_level < s->decision_level);
2358 
2359   u = s->stack.lit;
2360   k = s->stack.level_index[back_level + 1];
2361   i = s->stack.top;
2362   while (i > k) {
2363     i --;
2364     l = u[i];
2365 
2366     assert(literal_value(s, l) == VAL_TRUE);
2367     assert(s->level[var_of(l)] > back_level);
2368 
2369     // clear assignment of x, keep polarity bit
2370     x = var_of(l);
2371     s->value[x] &= 1;
2372     heap_insert(&s->heap, x);
2373 
2374     assert(literal_value(s, l) == VAL_UNDEF_TRUE);
2375   }
2376 
2377   s->stack.top = i;
2378   s->stack.prop_ptr = i;
2379   s->stack.theory_ptr = i;
2380   s->decision_level = back_level;
2381 
2382   // Update the cp_flag: the deletion of atoms is enabled if there's a checkpoint
2383   // and if the top checkpoint has level >= the new decision level
2384   s->cp_flag = non_empty_checkpoint_stack(&s->checkpoints) &&
2385     top_checkpoint(&s->checkpoints)->dlevel >= back_level;
2386 
2387   // adust the assumption index
2388   k = back_level - s->base_level;
2389   if (k < s->assumption_index) {
2390     s->assumption_index = k;
2391   }
2392 }
2393 
2394 
2395 
2396 /*
2397  * Cause both s and the theory solver to backtrack
2398  */
backtrack_to_level(smt_core_t * s,uint32_t back_level)2399 static void backtrack_to_level(smt_core_t *s, uint32_t back_level) {
2400   if (back_level < s->decision_level) {
2401     backtrack(s, back_level);
2402     s->th_ctrl.backtrack(s->th_solver, back_level);
2403   }
2404 }
2405 
backtrack_to_base_level(smt_core_t * s)2406 static void backtrack_to_base_level(smt_core_t *s) {
2407   backtrack_to_level(s, s->base_level);
2408 }
2409 
2410 
2411 /***************
2412  *  CONFLICTS  *
2413  **************/
2414 
2415 /*
2416  * Record a two-literal conflict: clause {l0, l1} is false
2417  */
record_binary_conflict(smt_core_t * s,literal_t l0,literal_t l1)2418 static void record_binary_conflict(smt_core_t *s, literal_t l0, literal_t l1) {
2419 #if TRACE
2420   printf("\n---> DPLL:   Binary conflict: {");
2421   print_literal(stdout, l0);
2422   printf(", ");
2423   print_literal(stdout, l1);
2424   printf("}\n");
2425   fflush(stdout);
2426 #endif
2427 
2428   assert(! s->theory_conflict);
2429 
2430   s->inconsistent = true;
2431   s->conflict_buffer[0] = l0;
2432   s->conflict_buffer[1] = l1;
2433   s->conflict_buffer[2] = end_clause;
2434   s->conflict = s->conflict_buffer;
2435 }
2436 
2437 
2438 /*
2439  * Record cl as a conflict clause
2440  */
record_clause_conflict(smt_core_t * s,clause_t * cl)2441 static void record_clause_conflict(smt_core_t *s, clause_t *cl) {
2442 #if TRACE
2443   uint32_t i;
2444   literal_t ll;
2445 
2446   printf("\n---> DPLL:   Conflict: {");
2447   print_literal(stdout, get_first_watch(cl));
2448   printf(", ");
2449   print_literal(stdout, get_second_watch(cl));
2450   i = 2;
2451   ll = cl->cl[i];
2452   while (ll >= 0) {
2453     printf(", ");
2454     print_literal(stdout, ll);
2455     i++;
2456     ll = cl->cl[i];
2457   }
2458   printf("}\n");
2459   fflush(stdout);
2460 #endif
2461 
2462   assert(! s->theory_conflict);
2463 
2464   s->inconsistent = true;
2465   s->false_clause = cl;
2466   s->conflict = cl->cl;
2467 }
2468 
2469 
2470 /*
2471  * Externally generated conflict (i.e., by a theory solver)
2472  * - a must be an array of literals terminated by null_literal
2473  * - all literals in a must be false in the current assignment
2474  */
record_theory_conflict(smt_core_t * s,literal_t * a)2475 void record_theory_conflict(smt_core_t *s, literal_t *a) {
2476 #if TRACE
2477   uint32_t i;
2478   literal_t l;
2479 
2480   printf("---> DPLL:   Theory conflict: {");
2481   i = 0;
2482   l = a[i];
2483   if (l >= 0) {
2484     print_literal(stdout, l);
2485     i ++;
2486     l = a[i];
2487     while (l >= 0) {
2488       printf(", ");
2489       print_literal(stdout, l);
2490       i++;
2491       l = a[i];
2492     }
2493   }
2494   printf("}\n");
2495 #endif
2496   fflush(stdout);
2497 
2498 #if DEBUG
2499   check_theory_conflict(s, a);
2500 #endif
2501 
2502   assert(! s->inconsistent && ! s->theory_conflict);
2503   s->stats.th_conflicts ++;
2504   s->inconsistent = true;
2505   s->theory_conflict = true;
2506   s->false_clause = NULL;
2507   s->conflict = a;
2508 }
2509 
2510 
2511 /*
2512  * Short cuts
2513  */
record_empty_theory_conflict(smt_core_t * s)2514 void record_empty_theory_conflict(smt_core_t *s) {
2515   s->conflict_buffer[0] = null_literal;
2516   record_theory_conflict(s, s->conflict_buffer);
2517 }
2518 
record_unit_theory_conflict(smt_core_t * s,literal_t l)2519 void record_unit_theory_conflict(smt_core_t *s, literal_t l) {
2520   s->conflict_buffer[0] = l;
2521   s->conflict_buffer[1] = null_literal;
2522   record_theory_conflict(s, s->conflict_buffer);
2523 }
2524 
record_binary_theory_conflict(smt_core_t * s,literal_t l1,literal_t l2)2525 void record_binary_theory_conflict(smt_core_t *s, literal_t l1, literal_t l2) {
2526   s->conflict_buffer[0] = l1;
2527   s->conflict_buffer[1] = l2;
2528   s->conflict_buffer[2] = null_literal;
2529   record_theory_conflict(s, s->conflict_buffer);
2530 }
2531 
record_ternary_theory_conflict(smt_core_t * s,literal_t l1,literal_t l2,literal_t l3)2532 void record_ternary_theory_conflict(smt_core_t *s, literal_t l1, literal_t l2, literal_t l3) {
2533   s->conflict_buffer[0] = l1;
2534   s->conflict_buffer[1] = l2;
2535   s->conflict_buffer[2] = l3;
2536   s->conflict_buffer[3] = null_literal;
2537   record_theory_conflict(s, s->conflict_buffer);
2538 }
2539 
2540 
2541 
2542 /*************************
2543  *  BOOLEAN PROPAGATION  *
2544  ************************/
2545 
2546 /*
2547  * Short cut: lit_val(v, l) is value of l
2548  * - v must be equal to solver->value
2549  */
lit_val(uint8_t * v,literal_t l)2550 static inline bval_t lit_val(uint8_t *v, literal_t l) {
2551   return v[var_of(l)] ^ sign_of_lit(l);
2552 }
2553 
2554 /*
2555  * Propagation via binary clauses:
2556  * - val = literal value array (must be s->value)
2557  * - l0 = literal (must be false in the current assignment)
2558  * - v = array of literals terminated by -1 (must be s->bin[l])
2559  * v must be != NULL
2560  *
2561  * Return true if there's no conflict, false otherwise.
2562  */
propagation_via_bin_vector(smt_core_t * s,uint8_t * val,literal_t l0,literal_t * v)2563 static bool propagation_via_bin_vector(smt_core_t *s, uint8_t *val, literal_t l0, literal_t *v) {
2564   literal_t l1;
2565   bval_t v1;
2566 
2567   assert(v != NULL);
2568   assert(s->value == val && s->bin[l0] == v && literal_value(s, l0) == VAL_FALSE);
2569 
2570   for (;;) {
2571     // Search for non-true literals in v
2572     // This terminates since val[end_marker] = VAL_UNDEF
2573     do {
2574       l1 = *v ++;
2575       v1 = lit_val(val, l1);
2576     } while (v1 == VAL_TRUE);
2577 
2578     if (l1 < 0) break; // end_marker
2579 
2580     if (bval_is_undef(v1)) {
2581       implied_literal(s, l1, mk_literal_antecedent(l0));
2582     } else {
2583       record_binary_conflict(s, l0, l1);
2584       return false;
2585     }
2586   }
2587 
2588   return true;
2589 }
2590 
2591 
2592 
2593 /*
2594  * Propagation via the watched lists of a literal l0.
2595  * - val = literal value array (must be s->value)
2596  *
2597  * Return true if there's no conflict, false otherwise
2598  */
propagation_via_watched_list(smt_core_t * s,uint8_t * val,literal_t l0)2599 static bool propagation_via_watched_list(smt_core_t *s, uint8_t *val, literal_t l0) {
2600   clause_t *cl;
2601   link_t *list;
2602   link_t link;
2603   bval_t v1;
2604   uint32_t k, i;
2605   literal_t l1, l, *b;
2606 
2607   assert(s->value == val);
2608 
2609   list = &s->watch[l0];
2610   link = *list;
2611   while (link != NULL_LINK) {
2612     cl = clause_of(link);
2613     i = idx_of(link);
2614     l1 = get_other_watch(cl, i);
2615     v1 = lit_val(val, l1);
2616 
2617     assert(next_of(link) == cl->link[i]);
2618     assert(cdr_ptr(link) == cl->link + i);
2619 
2620     if (v1 == VAL_TRUE) {
2621       /*
2622        * Skip clause cl: it's already true
2623        */
2624       *list = link;
2625       list = cl->link + i;
2626       link = cl->link[i];
2627 
2628     } else {
2629       /*
2630        * Search for a new watched literal in cl.
2631        * The loop terminates since cl->cl terminates with an end marked
2632        * and val[end_marker] == VAL_UNDEF.
2633        */
2634       k = 1;
2635       b = cl->cl;
2636       do {
2637         k ++;
2638         l = b[k];
2639       } while (lit_val(val, l) == VAL_FALSE);
2640 
2641       if (l >= 0) {
2642         /*
2643          * l occurs in b[k] = cl->cl[k] and is either TRUE or UNDEF
2644          * make l a new watched literal
2645          * - swap b[i] and b[k]
2646          * - insert cl into l's watched list (link[i])
2647          */
2648         b[k] = b[i];
2649         b[i] = l;
2650 
2651         // insert cl in watch[l] list and move to the next clause
2652         link = cl->link[i];
2653         s->watch[l] = cons(i, cl, s->watch[l]);
2654       } else {
2655         /*
2656          * All literals of cl, except possibly l1, are false
2657          */
2658 	if (bval_is_undef(v1)) {
2659           // l1 is implied
2660           implied_literal(s, l1, mk_clause_antecedent(cl, i^1));
2661 
2662           // move to the next clause
2663           *list = link;
2664           list = cl->link + i;
2665           link = cl->link[i];
2666 
2667         } else {
2668           // v1 == VAL_FALSE: conflict found
2669           record_clause_conflict(s, cl);
2670           *list = link;
2671           return false;
2672         }
2673       }
2674     }
2675   }
2676 
2677   *list = NULL_LINK;
2678 
2679   return true;
2680 }
2681 
2682 
2683 
2684 /*
2685  * Full boolean propagation: until either the propagation queue is empty,
2686  * or a conflict is found
2687  * - result = true if no conflict, false otherwise
2688  */
boolean_propagation(smt_core_t * s)2689 static bool boolean_propagation(smt_core_t *s) {
2690   uint8_t *val;
2691   literal_t l, *bin;
2692   uint32_t i;
2693 
2694   val = s->value;
2695 
2696   for (i = s->stack.prop_ptr; i < s->stack.top; i++) {
2697     l = not(s->stack.lit[i]);
2698 
2699     bin = s->bin[l];
2700     if (bin != NULL && ! propagation_via_bin_vector(s, val, l, bin)) {
2701       // conflict found
2702       return false;
2703     }
2704 
2705     if (! propagation_via_watched_list(s, val, l)) {
2706       return false;
2707     }
2708   }
2709 
2710   s->stack.prop_ptr = i;
2711 
2712 #if DEBUG
2713   check_propagation(s);
2714 #endif
2715 
2716   return true;
2717 }
2718 
2719 
2720 
2721 /**************************************
2722  *  PROPAGATION TO THE THEORY SOLVER  *
2723  *************************************/
2724 
2725 /*
2726  * Propagate all atom assignments to the theory solver
2727  * - return true if no conflict is found
2728  * - return false otherwise
2729  */
theory_propagation(smt_core_t * s)2730 static bool theory_propagation(smt_core_t *s) {
2731   uint32_t i, n;
2732   byte_t *has_atom;
2733   void **atom;
2734   literal_t *queue;
2735   literal_t l;
2736   bvar_t x;
2737 
2738   /*
2739    * IMPORTANT: make sure the theory_solver does not
2740    * create new atoms within the assert_atom function
2741    */
2742   n = s->atoms.size;
2743   has_atom = s->atoms.has_atom;
2744   atom = s->atoms.atom;
2745   queue = s->stack.lit;
2746 
2747   for (i = s->stack.theory_ptr; i < s->stack.top; i++) {
2748     l = queue[i];
2749     x = var_of(l);
2750     if (x < n && tst_bit(has_atom, x)) {
2751       if (! s->th_smt.assert_atom(s->th_solver, atom[x], l)) {
2752         // theory conflict reported
2753         //      assert(s->inconsistent && s->theory_conflict);
2754         /*
2755          * HACK: Changed this assert because the bvsolver adds the empty clause
2756          * rather than create a theory conflict.
2757          */
2758         assert(s->inconsistent);
2759         return false;
2760       }
2761     }
2762   }
2763 
2764   s->stack.theory_ptr = i;
2765 
2766   /*
2767    * If this function is called at base_level, then the theory solver
2768    * may add clauses (in its propagate function). In particular, the
2769    * theory solver may add the empty clause, which sets
2770    * s->inconsistent to true.  So we must check for s->inconsistent
2771    * here.
2772    */
2773   return s->th_ctrl.propagate(s->th_solver) && !s->inconsistent;
2774 }
2775 
2776 
2777 
2778 /************************
2779  *   FULL PROPAGATION   *
2780  ***********************/
2781 
2782 /*
2783  * Propagate all boolean assignments and all atoms,
2784  * repeat if the theory solver has implied some literals
2785  * - return false if a conflict is detected
2786  * - return true otherwise
2787  */
smt_propagation(smt_core_t * s)2788 static bool smt_propagation(smt_core_t *s) {
2789   bool code;
2790   uint32_t n;
2791 
2792   if (s->bool_only) {
2793     // purely boolean problem
2794     return boolean_propagation(s);
2795   }
2796 
2797   do {
2798     code = boolean_propagation(s);
2799     if (! code) break;
2800     n = s->stack.top;
2801     code = theory_propagation(s);
2802   } while (code && n < s->stack.top);
2803 
2804   return code;
2805 }
2806 
2807 
2808 
2809 
2810 /***********************************
2811  *  MARKS FOR CONFLICT RESOLUTION  *
2812  **********************************/
2813 
is_var_unmarked(smt_core_t * s,bvar_t x)2814 static inline bool is_var_unmarked(smt_core_t *s, bvar_t x) {
2815   return ! tst_bit(s->mark, x);
2816 }
2817 
2818 #if DEBUG || !defined(NDEBUG)
is_var_marked(smt_core_t * s,bvar_t x)2819 static inline bool is_var_marked(smt_core_t *s, bvar_t x) {
2820   return tst_bit(s->mark, x);
2821 }
2822 #endif
2823 
set_var_mark(smt_core_t * s,bvar_t x)2824 static inline void set_var_mark(smt_core_t *s, bvar_t x) {
2825   set_bit(s->mark, x);
2826 }
2827 
clr_var_mark(smt_core_t * s,bvar_t x)2828 static inline void clr_var_mark(smt_core_t *s, bvar_t x) {
2829   clr_bit(s->mark, x);
2830 }
2831 
2832 
is_lit_unmarked(smt_core_t * s,literal_t l)2833 static inline bool is_lit_unmarked(smt_core_t *s, literal_t l) {
2834   return ! tst_bit(s->mark, var_of(l));
2835 }
2836 
is_lit_marked(smt_core_t * s,literal_t l)2837 static inline bool is_lit_marked(smt_core_t *s, literal_t l) {
2838   return tst_bit(s->mark, var_of(l));
2839 }
2840 
set_lit_mark(smt_core_t * s,literal_t l)2841 static inline void set_lit_mark(smt_core_t *s, literal_t l) {
2842   set_bit(s->mark, var_of(l));
2843 }
2844 
clear_lit_mark(smt_core_t * s,literal_t l)2845 static inline void clear_lit_mark(smt_core_t *s, literal_t l) {
2846   clr_bit(s->mark, var_of(l));
2847 }
2848 
2849 
2850 /*
2851  * Decision level for assigned literal l
2852  */
d_level(smt_core_t * s,literal_t l)2853 static inline uint32_t d_level(smt_core_t *s, literal_t l) {
2854   return s->level[var_of(l)];
2855 }
2856 
2857 
2858 
2859 /*********************
2860  *  LEARNED CLAUSES  *
2861  ********************/
2862 
2863 /*
2864  * Auxiliary function: add { l1, l2} as a binary clause
2865  * - l1 and l2 must be distinct (and not complementary)
2866  * - we put the function here because it's used by add_learned_clause
2867  */
direct_binary_clause(smt_core_t * s,literal_t l1,literal_t l2)2868 static void direct_binary_clause(smt_core_t *s, literal_t l1, literal_t l2) {
2869 #if TRACE
2870   printf("---> DPLL:   Add binary clause: { ");
2871   print_literal(stdout, l1);
2872   printf(" ");
2873   print_literal(stdout, l2);
2874   printf(" }\n");
2875   fflush(stdout);
2876 #endif
2877 
2878   add_literal_to_vector(s->bin + l1, l2);
2879   add_literal_to_vector(s->bin + l2, l1);
2880   s->nb_bin_clauses ++;
2881 
2882   if (s->base_level > 0) {
2883     // make a copy for push/pop
2884     ivector_push(&s->binary_clauses, l1);
2885     ivector_push(&s->binary_clauses, l2);
2886   }
2887 }
2888 
2889 
2890 /*
2891  * Add an array of literals a as a new learned clause, after conflict resolution.
2892  * - n must be at least 1
2893  * - all literals must be assigned to false
2894  * - a[0] must be the implied literal: all other literals must have
2895  *   a lower assignment level than a[0].
2896  * - backtrack to the decision_level where a[0] is implied, then
2897  *   add a[0] to the propagation queue
2898  */
add_learned_clause(smt_core_t * s,uint32_t n,literal_t * a)2899 static void add_learned_clause(smt_core_t *s, uint32_t n, literal_t *a) {
2900   clause_t *cl;
2901   uint32_t i, j, k, q;
2902   literal_t l0, l1;
2903 
2904 #if TRACE
2905   printf("---> DPLL:   Learned clause: {");
2906   for (i=0; i<n; i++) {
2907     printf(" ");
2908     print_literal(stdout, a[i]);
2909   }
2910   printf(" }\n\n");
2911   fflush(stdout);
2912 #endif
2913 
2914   l0 = a[0];
2915 
2916   if (n == 1) {
2917 
2918     backtrack_to_base_level(s);
2919     if (literal_value(s, l0) == VAL_FALSE) {
2920       // conflict (the whole thing is unsat)
2921       s->inconsistent = true;
2922       s->conflict = s->conflict_buffer;
2923       s->conflict_buffer[0] = l0;
2924       s->conflict_buffer[1] = end_clause;
2925     } else {
2926 #if TRACE
2927       printf("---> DPLL:   Add learned unit clause: { ");
2928       print_literal(stdout, l0);
2929       printf(" }\n");
2930       fflush(stdout);
2931 #endif
2932       assign_literal(s, l0);
2933       s->nb_unit_clauses ++;
2934     }
2935 
2936   } else if (n == 2) {
2937 
2938     l1 = a[1];
2939     k = s->level[var_of(l1)];
2940     assert(k < s->level[var_of(l0)]);
2941 
2942     direct_binary_clause(s, l0, l1);
2943     backtrack_to_level(s, k);
2944     implied_literal(s, l0, mk_literal_antecedent(l1));
2945 
2946   } else {
2947 
2948     // EXPERIMENTAL
2949     //    if (s->etable != NULL) {
2950     //      test_eq_clause(s, "after simplification", n, a);
2951     //    }
2952 
2953     // find literal of second highest level in a[0 ... n-1]
2954     j = 1;
2955     k = s->level[var_of(a[1])];
2956     for (i=2; i<n; i++) {
2957       q = s->level[var_of(a[i])];
2958       if (q > k) {
2959         k = q;
2960         j = i;
2961       }
2962     }
2963 
2964     // swap a[1] and a[j]
2965     l1 = a[j]; a[j] = a[1]; a[1] = l1;
2966 
2967     // create the new clause with l0 and l1 as watched literals
2968     cl = new_learned_clause(n, a);
2969     add_clause_to_vector(&s->learned_clauses, cl);
2970     increase_clause_activity(s, cl);
2971 
2972     // add cl at the start of watch[l0] and watch[l1]
2973     s->watch[l0] = cons(0, cl, s->watch[l0]);
2974     s->watch[l1] = cons(1, cl, s->watch[l1]);
2975 
2976     s->nb_clauses ++;
2977     s->stats.learned_literals += n;
2978 
2979     // backtrack and assert l0
2980     assert(k < s->level[var_of(l0)]);
2981     backtrack_to_level(s, k);
2982 
2983     implied_literal(s, l0, mk_clause0_antecedent(cl));
2984   }
2985 }
2986 
2987 
2988 /*
2989  * Auxiliary function: attempt to add a[0] ... a[n-1] as a learned clause
2990  * - search for two literals of decision_level == s->decision level then
2991  *   use them as watched literals.
2992  * - if such literals can't be found don't do anything
2993  * Return true if the clause was added/false otherwise
2994  */
try_cache_theory_clause(smt_core_t * s,uint32_t n,literal_t * a)2995 static bool try_cache_theory_clause(smt_core_t *s, uint32_t n, literal_t *a) {
2996   clause_t *cl;
2997   uint32_t i, j, d;
2998   literal_t l, l0, l1;
2999 
3000   d = s->decision_level;
3001 
3002   if (n == 2) {
3003     // add as binary clause
3004     if (d_level(s, a[0]) == d && d_level(s, a[1]) == d) {
3005       direct_binary_clause(s, a[0], a[1]);
3006 
3007 #if TRACE
3008       printf("---> DPLL: cached theory clause: { ");
3009       print_literal(stdout, a[0]);
3010       printf(" ");
3011       print_literal(stdout, a[1]);
3012       printf(" }\n");
3013       fflush(stdout);
3014 #endif
3015       return true;
3016     }
3017 
3018     return false;
3019 
3020   } else if (n > 2) {
3021 
3022     i = 0;
3023     while (i<n) {
3024       l = a[i];
3025       if (d_level(s, l) == d) goto found0;
3026       i ++;
3027     }
3028     return false;
3029 
3030   found0:
3031     j = i;
3032     l0 = l;  // l0 == a[j] == first watched literal
3033     i ++;
3034     while (i<n) {
3035       l = a[i];
3036       if (d_level(s, l) == d) goto found1;
3037       i ++;
3038     }
3039     return false;
3040 
3041   found1:
3042     l1 = l; // l1 == a[i] == second watched literal
3043 
3044     assert(l0 != l1 && j < i && d_level(s, l0) == d && d_level(s, l1) == d);
3045 
3046     // swap a[0] and a[j] == l0, swap a[1] and a[i] == l1
3047     a[j] = a[0]; a[0] = l0;
3048     a[i] = a[1]; a[1] = l1;
3049 
3050 #if TRACE
3051     printf("---> DPLL: cached theory clause: {");
3052     for (i=0; i<n; i++) {
3053       printf(" ");
3054       print_literal(stdout, a[i]);
3055     }
3056     printf(" }\n");
3057     fflush(stdout);
3058 #endif
3059 
3060     // create the new clause with l0 and l1 as watched literals
3061     cl = new_learned_clause(n, a);
3062     add_clause_to_vector(&s->learned_clauses, cl);
3063     increase_clause_activity(s, cl);
3064 
3065     // insert cl at the head of watch[l0] and watch[l1]
3066     s->watch[l0] = cons(0, cl, s->watch[l0]);
3067     s->watch[l1] = cons(1, cl, s->watch[l1]);
3068 
3069     s->nb_clauses ++;
3070     s->stats.learned_literals += n;
3071     return true;
3072   }
3073 
3074   return false;
3075 }
3076 
3077 
3078 /*
3079  * Attempt to add a theory conflict as a learned clause
3080  * - a = array of literals
3081  * - n = size of the array
3082  * - all literals a[0] ... a[n-1] must be false
3083  * The clause is added if we can find two literals of level == s->decision_level.
3084  * Uses s->buffer2.
3085  */
try_cache_theory_conflict(smt_core_t * s,uint32_t n,literal_t * a)3086 static void try_cache_theory_conflict(smt_core_t *s, uint32_t n, literal_t *a) {
3087   ivector_t *v;
3088   uint32_t i;
3089   literal_t l;
3090 
3091   if (n < 2 || n > s->th_cache_cl_size) return;
3092 
3093   v = &s->buffer2;
3094   assert(v->size == 0);
3095 
3096   // remove literals false at the base level
3097   for (i=0; i<n; i++) {
3098     l = a[i];
3099     assert(literal_value(s, l) == VAL_FALSE && d_level(s, l) <= s->decision_level);
3100     if (d_level(s, l) > s->base_level) {
3101       ivector_push(v, l);
3102     }
3103   }
3104 
3105   // remove duplicate literals then try to add
3106   ivector_remove_duplicates(v);
3107   if (try_cache_theory_clause(s, v->size, v->data)) {
3108     s->stats.th_conflict_lemmas ++;
3109   }
3110 
3111   ivector_reset(v);
3112 }
3113 
3114 
3115 
3116 /*
3117  * Attempt to add a theory implication "(a[0] and ... and a[n-1]) implies l0"
3118  * as a learned clause.
3119  * - a[0] ... a[n-1] and l0 must all be true
3120  * - l0 must be assigned with level == current decision level
3121  * The clause is added if we can find another literal of that level among a[0 .. n-1].
3122  * Uses s->buffer2.
3123  */
try_cache_theory_implication(smt_core_t * s,uint32_t n,literal_t * a,literal_t l0)3124 static void try_cache_theory_implication(smt_core_t *s, uint32_t n, literal_t *a, literal_t l0) {
3125   ivector_t *v;
3126   uint32_t i;
3127   literal_t l;
3128 
3129   if (n == 0 || n >= s->th_cache_cl_size) return;
3130 
3131   v = &s->buffer2;
3132   assert(v->size == 0);
3133 
3134   assert(d_level(s, l0) == s->decision_level && literal_value(s, l0) == VAL_TRUE);
3135   ivector_push(v, l0);
3136 
3137   // turn the implication into a clause
3138   // ignore literals assigned at the base level
3139   for (i=0; i<n; i++) {
3140     l = a[i];
3141     assert(literal_value(s, l) == VAL_TRUE && d_level(s, l) <= s->decision_level);
3142     if (d_level(s, l) > s->base_level) {
3143       ivector_push(v, not(l));
3144     }
3145   }
3146 
3147   // now v->data contains l0 or (not a[0]) or ... or (not a[n-1])
3148   ivector_remove_duplicates(v);
3149   if (try_cache_theory_clause(s, v->size, v->data)) {
3150     s->stats.th_prop_lemmas ++;
3151   }
3152 
3153   ivector_reset(v);
3154 }
3155 
3156 
3157 
3158 /**************************************
3159  *  CONFLICT ANALYSIS AND RESOLUTION  *
3160  *************************************/
3161 
3162 /*
3163  * Turn a generic antecedent into a conjunction of literals:
3164  * - store the literals in s->explanation
3165  *
3166  * IMPORTANT: the theory solver must ensure causality. All literals in s->explanation
3167  * must be before l in the assignment/propagation stack.
3168  */
explain_antecedent(smt_core_t * s,literal_t l,antecedent_t a)3169 static void explain_antecedent(smt_core_t *s, literal_t l, antecedent_t a) {
3170   assert(literal_value(s, l) == VAL_TRUE && a == s->antecedent[var_of(l)] &&
3171          antecedent_tag(a) == generic_tag);
3172 
3173   ivector_reset(&s->explanation);
3174   s->th_smt.expand_explanation(s->th_solver, l, generic_antecedent(a), &s->explanation);
3175 
3176 #if DEBUG
3177   check_theory_explanation(s, l);
3178 #endif
3179 }
3180 
3181 
3182 /*
3183  * Auxiliary function to accelerate clause simplification (cf. Minisat).
3184  * This builds a hash of the decision levels in a literal array.
3185  * b = array of literals
3186  * n = number of literals
3187  */
signature(smt_core_t * s,literal_t * b,uint32_t n)3188 static uint32_t signature(smt_core_t *s, literal_t *b, uint32_t n) {
3189   uint32_t i, u;
3190 
3191   u = 0;
3192   for (i=0; i<n; i++) {
3193     u |= ((uint32_t) 1) << (d_level(s, b[i]) & 31);
3194   }
3195   return u;
3196 }
3197 
3198 /*
3199  * Check whether decision level for literal l matches the hash sgn
3200  */
check_level(smt_core_t * s,literal_t l,uint32_t sgn)3201 static inline bool check_level(smt_core_t *s, literal_t l, uint32_t sgn) {
3202   return (sgn & (((uint32_t) 1) << (d_level(s, l) & 31))) != 0;
3203 }
3204 
3205 
3206 /*
3207  * Analyze literal antecedents of not(l) to check whether l is subsumed.
3208  * - sgn = signature of the learned clause
3209  * level of l must match sgn (i.e., check_level(sol, l, sgn) is not 0).
3210  *
3211  * - returns false if l is not subsumed: either because not(l) has no antecedents
3212  *   or if an antecedent of not(l) has a decision level that does not match sgn.
3213  * - returns true otherwise.
3214  *
3215  * Unmarked antecedents are marked and pushed into sol->buffer2.
3216  */
analyze_antecedents(smt_core_t * s,literal_t l,uint32_t sgn)3217 static bool analyze_antecedents(smt_core_t *s, literal_t l, uint32_t sgn) {
3218   bvar_t x;
3219   antecedent_t a;
3220   literal_t l1;
3221   uint32_t i;
3222   ivector_t *b;
3223   literal_t *c;
3224 
3225   x = var_of(l);
3226   a = s->antecedent[x];
3227   if (a == mk_literal_antecedent(null_literal)) {
3228     return false;
3229   }
3230 
3231   b = &s->buffer2;
3232   switch (antecedent_tag(a)) {
3233   case clause0_tag:
3234   case clause1_tag:
3235     c = clause_antecedent(a)->cl;
3236     i = clause_index(a);
3237     assert(c[i] == not(l));
3238     // other watched literal
3239     l1 = c[i^1];
3240     if (is_lit_unmarked(s, l1)) {
3241       // l1 has the same decision level as l so there's no need to call check_level
3242       set_lit_mark(s, l1);
3243       ivector_push(b, l1);
3244     }
3245     // rest of the clause
3246     i = 2;
3247     l1 = c[i];
3248     while (l1 >= 0) {
3249       if (is_lit_unmarked(s, l1)) {
3250         if (check_level(s, l1, sgn)) {
3251           set_lit_mark(s, l1);
3252           ivector_push(b, l1);
3253         } else {
3254           return false;
3255         }
3256       }
3257       i ++;
3258       l1 = c[i];
3259     }
3260     break;
3261 
3262   case literal_tag:
3263     l1 = literal_antecedent(a);
3264     if (is_lit_unmarked(s, l1)) {
3265       set_lit_mark(s, l1);
3266       ivector_push(b, l1);
3267     }
3268     break;
3269 
3270   case generic_tag:
3271     /*
3272      * TODO: check whether skipping all theory-propagated literals
3273      * makes a difference here.
3274      */
3275     if (false) {
3276       explain_antecedent(s, not(l), a);
3277       c = s->explanation.data;
3278       // (and c[0] ... c[n-1]) implies (not l)
3279       for (i=0; i<s->explanation.size; i++) {
3280 	l1 = not(c[i]);
3281 	if (is_lit_unmarked(s, l1)) {
3282 	  if (check_level(s, l1, sgn)) {
3283 	    set_lit_mark(s, l1);
3284 	    ivector_push(b, l1);
3285 	  } else {
3286 	    return false;
3287 	  }
3288 	}
3289       }
3290     } else {
3291       return false;
3292     }
3293     break;
3294   }
3295 
3296   return true;
3297 }
3298 
3299 
3300 /*
3301  * Check whether literal l is subsumed by other marked literals
3302  * - sgn = signature of the learned clause (in which l occurs)
3303  * s->buffer2 is used as a queue
3304  */
subsumed(smt_core_t * s,literal_t l,uint32_t sgn)3305 static bool subsumed(smt_core_t *s, literal_t l, uint32_t sgn) {
3306   uint32_t i, n;
3307   ivector_t *b;
3308 
3309   b = &s->buffer2;
3310   n = b->size;
3311   i = n;
3312   while (analyze_antecedents(s, l, sgn)) {
3313     if (i < b->size) {
3314       l = b->data[i];
3315       i ++;
3316     } else {
3317       return true;
3318     }
3319   }
3320 
3321   // cleanup
3322   for (i=n; i<b->size; i++) {
3323     clear_lit_mark(s, b->data[i]);
3324   }
3325   b->size = n;
3326 
3327   return false;
3328 }
3329 
3330 
3331 /*
3332  * Simplification of a learned clause
3333  * - the clause is stored in s->buffer as an array of literals
3334  * - s->buffer[0] is the implied literal
3335  */
simplify_learned_clause(smt_core_t * s)3336 static void simplify_learned_clause(smt_core_t *s) {
3337   uint32_t hash;
3338   literal_t *b;
3339   literal_t l;
3340   uint32_t i, j, n;
3341 
3342   b = s->buffer.data;
3343   n = s->buffer.size;
3344   hash = signature(s, b+1, n-1); // skip b[0]. It cannot subsume anything.
3345 
3346   assert(s->buffer2.size == 0);
3347 
3348 #if TRACE
3349   printf("---> DPLL:   Learned clause: {");
3350   for (i=0; i<n; i++) {
3351     printf(" ");
3352     print_literal(stdout, b[i]);
3353   }
3354   printf(" }\n");
3355   fflush(stdout);
3356 #endif
3357 
3358   // remove the subsumed literals
3359   j = 1;
3360   for (i=1; i<n; i++) {
3361     l = b[i];
3362     if (subsumed(s, l, hash)) {
3363       // Hack: move l to buffer2 to clear its mark later
3364       ivector_push(&s->buffer2, l);
3365     } else {
3366       // keep l in buffer
3367       b[j] = l;
3368       j ++;
3369     }
3370   }
3371 
3372   s->stats.literals_before_simpl += n;
3373   s->stats.subsumed_literals += n - j;
3374   s->buffer.size = j;
3375 
3376   // remove the marks of literals in learned clause
3377   for (i=0; i<j; i++) {
3378     clear_lit_mark(s, b[i]);
3379   }
3380 
3381   // remove the marks of subsumed literals
3382   b = s->buffer2.data;
3383   n = s->buffer2.size;
3384   for (i=0; i<n; i++) {
3385     clear_lit_mark(s, b[i]);
3386   }
3387 
3388   ivector_reset(&s->buffer2);
3389 }
3390 
3391 
3392 
3393 
3394 /*
3395  * Compute the conflict level of a conflict a:
3396  * - a must be an array of literals terminated by null_literal/end_clause
3397  *   or by end_learned (i.e., by a negative number)
3398  * - if a is empty, the conflict level is set to s->base_level
3399  *   otherwise conflict level = max { d_level(l) | l in the clause }
3400  *
3401  * Also set s->th_conflict_size to the number of literals in the conflict clause.
3402  * This is used by the caching heuristics.
3403  *
3404  * Note: computing conflict level is necessary for theory conflicts.
3405  * For conflicts detected by boolean propagation, the conflict_level
3406  * is the same as the current decision_level
3407  */
get_conflict_level(smt_core_t * s,literal_t * a)3408 static uint32_t get_conflict_level(smt_core_t *s, literal_t *a) {
3409   uint32_t k, q, i;
3410   literal_t l;
3411 
3412   k = s->base_level;
3413   i = 0;
3414   for (;;) {
3415     l = a[i];
3416     if (l < 0) break;
3417     assert(literal_value(s, l) == VAL_FALSE);
3418     q = d_level(s, l);
3419     if (q > k) {
3420       k = q;
3421     }
3422     i ++;
3423   }
3424 
3425   s->th_conflict_size = i;
3426 
3427   return k;
3428 }
3429 
3430 
3431 
3432 
3433 /*
3434  * Search for first UIP and build the learned clause
3435  * d = solver state
3436  * - s->conflict stores a conflict clause (i.e., an array of literals
3437  *   terminated by -1 or -2 with all literals false).
3438  *
3439  * result:
3440  * - the learned clause is stored in s->buffer as an array of literals
3441  * - s->buffer.data[0] is the implied literal
3442  */
3443 
3444 #define process_literal(l)                    \
3445 do {                                          \
3446   x = var_of(l);                              \
3447   if (is_var_unmarked(s, x)) {                \
3448     set_var_mark(s, x);                       \
3449     increase_bvar_activity(s, x);             \
3450     if (s->level[x] < conflict_level) {       \
3451       ivector_push(buffer, l);                \
3452     } else {                                  \
3453       unresolved ++;                          \
3454     }                                         \
3455   }                                           \
3456 } while(0)
3457 
3458 
resolve_conflict(smt_core_t * s)3459 static void resolve_conflict(smt_core_t *s) {
3460   uint32_t i, j, conflict_level, unresolved;
3461   literal_t l, b;
3462   bvar_t x;
3463   literal_t *c,  *stack;
3464   antecedent_t a;
3465   clause_t *cl;
3466   ivector_t *buffer;
3467 
3468   assert(s->inconsistent);
3469   assert(s->theory_conflict || get_conflict_level(s, s->conflict) == s->decision_level);
3470   assert(s->base_level <= s->decision_level);
3471 
3472   s->stats.conflicts ++;
3473 
3474   c = s->conflict;
3475   conflict_level = s->decision_level;
3476 
3477   /*
3478    * adjust conflict_level and backtrack to that level if the conflict
3479    * was reported by the theory solver.
3480    */
3481   if (s->theory_conflict) {
3482     conflict_level = get_conflict_level(s, c);
3483     assert(s->base_level <= conflict_level && conflict_level <= s->decision_level);
3484     backtrack_to_level(s, conflict_level);
3485     assert(s->decision_level == conflict_level);
3486 
3487     // Cache as a clause
3488     if (s->th_cache_enabled) {
3489       try_cache_theory_conflict(s, s->th_conflict_size, c);
3490     }
3491   }
3492 
3493   if (conflict_level == s->base_level) {
3494     // can't be resolved: unsat problem
3495     return;
3496   }
3497 
3498 #if DEBUG
3499   check_marks(s);
3500 #endif
3501 
3502 
3503   /*
3504    * buffer stores the new clause (built by resolution)
3505    */
3506   buffer = &s->buffer;
3507   ivector_reset(buffer);
3508   unresolved = 0;
3509 
3510   // reserve space for the implied literal
3511   ivector_push(buffer, null_literal);
3512 
3513   /*
3514    * scan the conflict clause
3515    * - all literals of dl < conflict_level are added to buffer
3516    * - all literals are marked
3517    * - unresolved = number of literals in the conflict
3518    *   clause whose decision level is equal to conflict_level
3519    */
3520   l = *c;
3521   while (l >= 0) {
3522     process_literal(l);
3523     c ++;
3524     l = *c;
3525   }
3526 
3527   /*
3528    * If the conflict is a learned clause, increase its activity
3529    */
3530   if (l == end_learned) {
3531     increase_clause_activity(s, s->false_clause);
3532   }
3533 
3534   assert(unresolved > 0);
3535 
3536   /*
3537    * Scan the assignment stack from top to bottom and process the
3538    * antecedent of all marked literals:
3539    * - all the literals processed have decision_level == conflict_level
3540    * - the code works if unresolved == 1 (which may happen for theory conflicts)
3541    */
3542   stack = s->stack.lit;
3543   j = s->stack.top;
3544   for (;;) {
3545     j --;
3546     b = stack[j];
3547     assert(d_level(s, b) == conflict_level);
3548     if (is_lit_marked(s, b)) {
3549       if (unresolved == 1) {
3550         // not b is the implied literal; we're done.
3551         buffer->data[0] = not(b);
3552         break;
3553 
3554       } else {
3555         unresolved --;
3556         clear_lit_mark(s, b);
3557         a = s->antecedent[var_of(b)];
3558         /*
3559          * Process b's antecedent:
3560          */
3561         switch (antecedent_tag(a)) {
3562         case clause0_tag:
3563         case clause1_tag:
3564           cl = clause_antecedent(a);
3565           i = clause_index(a);
3566           c = cl->cl;
3567           assert(c[i] == b);
3568           // process other watched literal
3569           l = c[i^1];
3570           process_literal(l);
3571           // rest of the clause
3572           c += 2;
3573           l = *c;
3574           while (l >= 0) {
3575             process_literal(l);
3576             c ++;
3577             l = *c;
3578           }
3579           if (l == end_learned) {
3580             increase_clause_activity(s, cl);
3581           }
3582           break;
3583 
3584         case literal_tag:
3585           l = literal_antecedent(a);
3586           process_literal(l);
3587           break;
3588 
3589         case generic_tag:
3590           explain_antecedent(s, b, a);
3591           c = s->explanation.data;
3592           // explanation is c[0] ... c[n-1] where ((and c[0] ... c[n-1]) implies b)
3593           for (i=0; i<s->explanation.size; i++) {
3594             l = not(c[i]);
3595             assert(d_level(s, l) <= conflict_level);
3596             process_literal(l);
3597           }
3598           // cache the implication as a learned clause
3599           if (s->th_cache_enabled) {
3600             assert(i == s->explanation.size);
3601             try_cache_theory_implication(s, i, c, b);
3602           }
3603           break;
3604         }
3605       }
3606     }
3607   }
3608 
3609   // EXPERIMENTAL
3610   //  if (s->etable != NULL) {
3611   //    test_eq_conflict(s);
3612   //    test_eq_clause(s, "before simplification", s-> buffer.size, s->buffer.data);
3613   //  }
3614 
3615 
3616   /*
3617    * Simplify the learned clause and clear the marks
3618    */
3619   simplify_learned_clause(s);
3620 
3621 #if DEBUG
3622   check_marks(s);
3623 #endif
3624 
3625   /*
3626    * Clear the conflict flags
3627    */
3628   s->inconsistent = false;
3629   s->theory_conflict = false;
3630 
3631   /*
3632    * Add the learned clause: this causes backtracking
3633    * and assert the implied literal
3634    */
3635   add_learned_clause(s, s->buffer.size, s->buffer.data);
3636 }
3637 
3638 
3639 
3640 
3641 /*********************************
3642  *  ASSUMPTIONS AND UNSAT CORES  *
3643  ********************************/
3644 
3645 #ifndef NDEBUG
good_assumption_index(smt_core_t * s)3646 static bool good_assumption_index(smt_core_t *s) {
3647   uint32_t i;
3648   literal_t l;
3649 
3650   for (i=0; i<s->assumption_index; i++) {
3651     l = s->assumptions[i];
3652     if (literal_value(s, l) != VAL_TRUE) {
3653       return false;
3654     }
3655   }
3656   return true;
3657 }
3658 #endif
3659 
3660 
3661 /*
3662  * Get the next assumption for the current decision_level
3663  * - s->status mut be SEARCHING
3664  * - this scans the assumption array to search for an assumption
3665  *   that is not already true.
3666  * - returns an assumption l or null_literal if all assumptions
3667  *   are true (or if there are no assumptions)
3668  */
get_next_assumption(smt_core_t * s)3669 literal_t get_next_assumption(smt_core_t *s) {
3670   uint32_t i, n;
3671   literal_t l;
3672 
3673   assert(good_assumption_index(s));
3674 
3675   n = s->num_assumptions;
3676   for (i=s->assumption_index; i<n; i++) {
3677     l = s->assumptions[i];
3678     if (literal_value(s, l) != VAL_TRUE) {
3679       s->assumption_index = i+1;
3680       return l;
3681     }
3682   }
3683 
3684   s->assumption_index = n;
3685   return null_literal;
3686 }
3687 
3688 
3689 /*
3690  * Store l as a bad assumption:
3691  */
save_conflicting_assumption(smt_core_t * s,literal_t l)3692 void save_conflicting_assumption(smt_core_t *s, literal_t l) {
3693   assert(literal_value(s, l) == VAL_FALSE);
3694   s->bad_assumption = l;
3695   s->status = STATUS_UNSAT;
3696 }
3697 
3698 
3699 /*
3700  * UNSAT CORE CONSTRUCTION
3701  */
3702 
3703 /*
3704  * We use a queue + a hash set to mark all antecedent literals
3705  * already seen. The following functions add literals to the
3706  * queue and set if they have not been seen before and if they
3707  * are assigned at a decision level > base_level.
3708  *
3709  * We store var_of(l) rather than l in the set. This simplifies the
3710  * processing of clause antecedents:
3711  * - if l is implied by clause c then the clause looks like (l \/ c[0] ... \/ c[n-1])
3712  * - l is the only true literal in c.
3713  * - when we visit the clause, we call visit(not(l)), visit(not(c[0])), ..., visit(not c([n-1]))
3714  * - at this point l has been visited so var_of(l) is in the set.
3715  * - since var_of(l) = var_of(not(l)) is already in the set, we don't add not(l) to the queue.
3716  */
unsat_core_visit_literal(smt_core_t * s,int_hset_t * set,int_queue_t * queue,literal_t l)3717 static void unsat_core_visit_literal(smt_core_t *s, int_hset_t *set, int_queue_t *queue, literal_t l) {
3718   bvar_t x;
3719 
3720   x = var_of(l);
3721   if (s->level[x] > s->base_level && int_hset_add(set, x)) {
3722     assert(literal_value(s, l) == VAL_TRUE);
3723     int_queue_push(queue, l);
3724   }
3725 }
3726 
3727 /*
3728  * cl is (l \/ c[1] \/ .... \/ c[n]) where l is the implied literal
3729  * c[1] ... c[n] are all false in the current assignment
3730  * so the antecedents of l are (not c[0]) ... (not c[n])
3731  */
unsat_core_visit_clause(smt_core_t * s,int_hset_t * set,int_queue_t * queue,clause_t * cl)3732 static void unsat_core_visit_clause(smt_core_t *s, int_hset_t *set, int_queue_t *queue, clause_t *cl) {
3733   literal_t *c;
3734   literal_t l;
3735 
3736   c = cl->cl;
3737   l = *c;
3738   while (l >= 0) {
3739     unsat_core_visit_literal(s, set, queue, not(l));
3740     c ++;
3741     l = *c;
3742   }
3743 }
3744 
3745 /*
3746  * explanation is a vector of n literals c[0] ... c[n-1] such that
3747  * (and c[0] ... c[n-1]) implies  some other literal l.
3748  */
unsat_core_visit_explanation(smt_core_t * s,int_hset_t * set,int_queue_t * queue,ivector_t * explanation)3749 static void unsat_core_visit_explanation(smt_core_t *s, int_hset_t *set, int_queue_t *queue, ivector_t *explanation) {
3750   uint32_t i, n;
3751   literal_t l;
3752 
3753   n = explanation->size;
3754   for (i=0; i<n; i++) {
3755     l = explanation->data[i];
3756     unsat_core_visit_literal(s, set, queue, l);
3757   }
3758 }
3759 
3760 
3761 /*
3762  * Visit the antecedents of l
3763  */
unsat_core_visit_antecedents(smt_core_t * s,int_hset_t * set,int_queue_t * queue,literal_t l)3764 static void unsat_core_visit_antecedents(smt_core_t *s, int_hset_t *set, int_queue_t *queue, literal_t l) {
3765   antecedent_t a;
3766   literal_t q;
3767 
3768   a = s->antecedent[var_of(l)];
3769   switch (antecedent_tag(a)) {
3770   case clause0_tag:
3771   case clause1_tag:
3772     unsat_core_visit_clause(s, set, queue, clause_antecedent(a));
3773     break;
3774 
3775   case literal_tag:
3776     q = literal_antecedent(a);
3777     if (q != null_literal) {
3778       assert(literal_value(s, q) == VAL_FALSE);
3779       unsat_core_visit_literal(s, set, queue, not(q));
3780     }
3781     break;
3782 
3783   case generic_tag:
3784     // ask the theory solver for an explanation
3785     explain_antecedent(s, l, a);
3786     unsat_core_visit_explanation(s, set, queue, &s->explanation);
3787     break;
3788   }
3789 }
3790 
3791 
3792 /*
3793  * Visit all literals in queue and compute their antecedents.
3794  * Add any antecedent that's a decision literal to vector v.
3795  */
collect_decision_antecedents(smt_core_t * s,int_hset_t * set,int_queue_t * queue,ivector_t * v)3796 static void collect_decision_antecedents(smt_core_t *s, int_hset_t *set, int_queue_t *queue, ivector_t *v) {
3797   antecedent_t a;
3798   literal_t l;
3799 
3800   while (! int_queue_is_empty(queue)) {
3801     l = int_queue_pop(queue);
3802     assert(literal_value(s, l) == VAL_TRUE &&
3803 	   s->level[var_of(l)] > s->base_level);
3804 
3805     a = s->antecedent[var_of(l)];
3806     if (a == mk_literal_antecedent(null_literal)) {
3807       // l is a decision
3808       ivector_push(v, l);
3809     } else {
3810       unsat_core_visit_antecedents(s, set, queue, l);
3811     }
3812   }
3813 }
3814 
3815 
3816 /*
3817  * Compute an unsat core from the bad assumption:
3818  * - we collect all decision literals that are antecedents of the bad assumption
3819  * - if there is no bad assumption, we return an empty core
3820  */
build_unsat_core(smt_core_t * s,ivector_t * v)3821 void build_unsat_core(smt_core_t *s, ivector_t *v) {
3822   int_hset_t visited;
3823   int_queue_t queue;
3824   literal_t l;
3825 
3826   assert(s->status == STATUS_UNSAT);
3827   ivector_reset(v);
3828   l = s->bad_assumption;
3829   if (l != null_literal) {
3830     init_int_queue(&queue, 0);
3831     init_int_hset(&visited, 0);
3832 
3833     assert(literal_value(s, l) == VAL_FALSE);
3834 
3835     // collect all decision literals that imply not l
3836     unsat_core_visit_antecedents(s, &visited, &queue, not(l));
3837     collect_decision_antecedents(s, &visited, &queue, v);
3838     // the literals in v imply (not l)
3839     // the core is (v and l)
3840     ivector_push(v, l);
3841 
3842     delete_int_hset(&visited);
3843     delete_int_queue(&queue);
3844   }
3845 }
3846 
3847 
3848 
3849 
3850 /*************************************
3851  *  ADDITION OF LEMMAS AND CLAUSES   *
3852  ************************************/
3853 
3854 /*
3855  * Before addition, clauses are simplified with respect to the
3856  * base-level assignment:
3857  * - if a clause contains a literal true at the base level,
3858  *   or two complementary literals, then it's trivially true
3859  *   so it is ignored.
3860  * - otherwise all literals false at the base level are removed
3861  *   and duplicate literals are removed
3862  * - at this point, the clause contains no literals assigned
3863  *   at the base level.
3864  *
3865  * For a clause added during the search, we examine its truth value
3866  * at the current decision level.
3867  * - the clause if true if one of its literals is true
3868  * - the clause if false if all its literals are false
3869  * - the clause is undef if it has some undef literals and all other
3870  *   literals are false.
3871  * To find watched literals:
3872  * - for a false clause, take two literals of highest d_level
3873  * - for an undef clause, take two unassigned literals if that's possible,
3874  *   otherwise take the unassigned literal + a false literal of highest d_level
3875  * - for a true clause, let
3876  *       d = min { d_level(l) | l in clause and l is true }
3877  *   then the watched literals can be any literals of d_level >= d.
3878  *
3879  * We backtrack if the clause is false or if it contains a single
3880  * unassigned literal and all other literals are false.
3881  * - the backtrack level k is computed as follows:
3882  *   - for unit clauses, k = the base level
3883  *   - for a clause with a single undef literal.
3884  *       k = max { d_level(l) | l in clause and l is false }
3885  *   - for a false clause, sort literals in decreasing d_level order
3886  *       k = d_level of the second literal in this order
3887  * - after backtracking to level k: two cases are possible
3888  *   1) all literals are still false. We record the clause as a conflict.
3889  *      (this may overwrite an existing conflict but that's OK. We need
3890  *      to keep the conflict of lowest d_level anyway).
3891  *   2) one literal is unassigned, all other are false. We do a
3892  *      unit propagation step (to make the unassigned literal true).
3893  *
3894  * If several clauses are added in succession, then one may cause a conflict
3895  * at level k0 that gets cleared later by another clause that causes backtracking
3896  * to a lower level.
3897  */
3898 
3899 /*
3900  * Create a (simplified) problem clause
3901  * - a must not contain duplicate literals
3902  * - a must not be trivially true at the base level
3903  * - a[0] and a[1] must be valid watched literals
3904  * - return the new clause
3905  */
new_problem_clause(smt_core_t * s,uint32_t n,literal_t * a)3906 static clause_t *new_problem_clause(smt_core_t *s, uint32_t n, literal_t *a) {
3907   clause_t *cl;
3908   literal_t l;
3909 
3910 #if TRACE
3911   uint32_t i;
3912   printf("---> DPLL:   Add problem clause: {");
3913   for (i=0; i<n; i++) {
3914     printf(" ");
3915     print_literal(stdout, a[i]);
3916   }
3917   printf(" }\n");
3918   fflush(stdout);
3919 #endif
3920 
3921   cl = new_clause(n, a);
3922   add_clause_to_vector(&s->problem_clauses, cl);
3923 
3924   // add cl at the start of watch lists
3925   l = a[0];
3926   s->watch[l] = cons(0, cl, s->watch[l]);
3927 
3928   l = a[1];
3929   s->watch[l] = cons(1, cl, s->watch[l]);
3930 
3931   s->nb_prob_clauses ++;
3932   s->nb_clauses ++;
3933   s->stats.prob_literals += n;
3934 
3935   return cl;
3936 }
3937 
3938 
3939 /*
3940  * Add unit clause { l } after simplification
3941  * - l must not be assigned at the base level
3942  */
add_simplified_unit_clause(smt_core_t * s,literal_t l)3943 static void add_simplified_unit_clause(smt_core_t *s, literal_t l) {
3944 #if TRACE
3945   printf("---> DPLL:   Add unit clause: { ");
3946   print_literal(stdout, l);
3947   printf(" }\n");
3948   fflush(stdout);
3949 #endif
3950 
3951   if (s->inconsistent && s->decision_level > s->base_level) {
3952     s->inconsistent = false; // clear conflict
3953   }
3954   backtrack_to_base_level(s);
3955   assign_literal(s, l);
3956   s->nb_unit_clauses ++;
3957 }
3958 
3959 
3960 /*
3961  * Add binary clause { l0 l1 } after simplification
3962  * - l0 and l1 must not be assigned at the base level
3963  */
add_simplified_binary_clause(smt_core_t * s,literal_t l0,literal_t l1)3964 static void add_simplified_binary_clause(smt_core_t *s, literal_t l0, literal_t l1) {
3965   uint32_t k0, k1;
3966   bval_t v0, v1;
3967 
3968   direct_binary_clause(s, l0, l1); // add the clause
3969 
3970   if (s->base_level == s->decision_level) {
3971     assert(literal_is_unassigned(s, l0) && literal_is_unassigned(s, l1));
3972     return;
3973   }
3974 
3975   k0 = UINT32_MAX;
3976   k1 = UINT32_MAX;
3977   v0 = literal_value(s, l0);
3978   if (bval_is_def(v0)) k0 = s->level[var_of(l0)];
3979   v1 = literal_value(s, l1);
3980   if (bval_is_def(v1)) k1 = s->level[var_of(l1)];
3981 
3982   if (v0 == VAL_FALSE && k0 < k1) {
3983     // l1 implied at level k0
3984     if (k0 < s->decision_level) {
3985       backtrack_to_level(s, k0);
3986       s->inconsistent = false; // clear conflict if any
3987     }
3988     implied_literal(s, l1, mk_literal_antecedent(l0));
3989 
3990   } else if (v1 == VAL_FALSE && k1 < k0) {
3991     // l0 implied at level k1
3992     if (k1 < s->decision_level) {
3993       backtrack_to_level(s, k1);
3994       s->inconsistent = false; // clear conflict if any
3995     }
3996     implied_literal(s, l0, mk_literal_antecedent(l1));
3997 
3998   } else if (v0 == VAL_FALSE && v1 == VAL_FALSE) {
3999     assert(k0 == k1);
4000     // conflict at level k0
4001     backtrack_to_level(s, k0);
4002     record_binary_conflict(s, l0, l1);
4003   }
4004 }
4005 
4006 
4007 /*
4008  * For selecting watched literals, we pick two literals
4009  * that are minimal for a preference relation <
4010  *
4011  * To compare l and l', we look at
4012  *  (v  k)  where v  = value of l  and k  = level of l
4013  *  (v' k') where v' = value of l' and k' = level of l'
4014  *
4015  * Rules:
4016  *  (true, _) < (undef, _) < (false, _)
4017  *  k < k' implies (true, k) < (true, k')
4018  *  k' < k implies (false, k) < (false, k')
4019  *
4020  * Other choices are possible but we must ensure
4021  *   (undef, _) < (false, _)
4022  *   k' < k implies (false, k) < (false, k')
4023  *
4024  * Prefer returns true if (v1, k1) < (v2, k2)
4025  */
4026 
4027 /*
4028  * Priority table:
4029  * - prio[true] = 1
4030  * - prio[undef] = 0
4031  * - prio[false]  = -1
4032  *
4033  * If prio[v1] > prio[v2] then v1 is preferred
4034  * If prio[v1] = prio[v2]
4035  */
4036 static const int8_t prio[4] = {
4037   0, 0, -1, +1,
4038 };
4039 
prefer(bval_t v1,uint32_t k1,bval_t v2,uint32_t k2)4040 static bool prefer(bval_t v1, uint32_t k1, bval_t v2, uint32_t k2) {
4041   int8_t p1, p2;
4042   p1 = prio[v1];
4043   p2 = prio[v2];
4044   if (p1 == p2) {
4045     return (v1 == VAL_TRUE && k1 < k2) || (v1 == VAL_FALSE && k1 > k2);
4046   } else {
4047     return p1 > p2;
4048   }
4049 }
4050 
4051 
4052 /*
4053  * Add simplified clause { a[0] ... a[n-1] }
4054  * - a[0] ... a[n-1] are not assigned at the base level
4055  * - n >= 3
4056  */
add_simplified_clause(smt_core_t * s,uint32_t n,literal_t * a)4057 static void add_simplified_clause(smt_core_t *s, uint32_t n, literal_t *a) {
4058   uint32_t i, k0, k1, k;
4059   bval_t v0, v1, v;
4060   literal_t l;
4061   clause_t *cl;
4062 
4063   assert(n >= 3);
4064 
4065   if (s->base_level == s->decision_level) {
4066     new_problem_clause(s, n, a);
4067     return;
4068   }
4069 
4070   // find watched literals
4071   l = a[0];
4072   v0 = literal_value(s, l);
4073   k0 = s->level[var_of(l)];
4074 
4075   l = a[1];
4076   v1 = literal_value(s, l);
4077   k1 = s->level[var_of(l)];
4078   if (prefer(v1, k1, v0, k0)) {
4079     // swap a[0] and a[1]
4080     a[1] = a[0]; a[0] = l;
4081     v = v0; v0 = v1; v1 = v;
4082     k = k0; k0 = k1; k1 = k;
4083   }
4084 
4085   for (i=2; i<n; i++) {
4086     l = a[i];
4087     v = literal_value(s, l);
4088     k = s->level[var_of(l)];
4089     if (prefer(v, k, v0, k0)) {
4090       // circular rotation: a[i] --> a[0] --> a[1] --> a[i]
4091       a[i] = a[1]; a[1] = a[0]; a[0] = l;
4092       v1 = v0; k1 = k0;
4093       v0 = v; k0 = k;
4094     } else if (prefer(v, k, v1, k1)) {
4095       // swap a[i] and a[1]
4096       a[i] = a[1]; a[1] = l;
4097       v1 = v; k1 = k;
4098     }
4099   }
4100 
4101 #if DEBUG
4102   check_watched_literals(s, n, a);
4103 #endif
4104 
4105   cl = new_problem_clause(s, n, a);
4106 
4107   if (bval_is_undef(v0)) k0 = UINT32_MAX;
4108   if (bval_is_undef(v1)) k1 = UINT32_MAX;
4109 
4110   if (v0 == VAL_FALSE && k0 < k1) {
4111     // a[1] implied at level k0
4112     if (k0 < s->decision_level) {
4113       backtrack_to_level(s, k0);
4114       s->inconsistent = false; // clear conflict if any
4115     }
4116     implied_literal(s, a[1], mk_clause1_antecedent(cl));
4117 
4118   } else if (v1 == VAL_FALSE && k1 < k0) {
4119     // a[0] implied at level k1
4120     if (k1 < s->decision_level) {
4121       backtrack_to_level(s, k1);
4122       s->inconsistent = false; // clear conflict if any
4123     }
4124     implied_literal(s, a[0], mk_clause0_antecedent(cl));
4125 
4126   } else if (v0 == VAL_FALSE && v1 == VAL_FALSE) {
4127     assert(k0 == k1);
4128     backtrack_to_level(s, k0);
4129     record_clause_conflict(s, cl);
4130   }
4131 
4132 }
4133 
4134 
4135 
4136 
4137 /*
4138  * Simplify clause a[0... n-1]
4139  * - remove all literals false at base-level
4140  * - remove duplicate literals
4141  * - check whether the clause is true at base-level
4142  * Return code:
4143  * - true means the clause is not trivial
4144  *   n is updated and the simplified clause is stored in a[0 .. n-1].
4145  * - false means the clause contains complementary literals or
4146  *   a literal true at the base level
4147  */
preprocess_clause(smt_core_t * s,uint32_t * n,literal_t * a)4148 static bool preprocess_clause(smt_core_t *s, uint32_t *n, literal_t *a) {
4149   uint32_t i, j, m;
4150   literal_t l, l_aux;
4151 
4152   m = *n;
4153   if (m == 0) return true;
4154 
4155   // remove duplicates/check for complementary literals
4156   int_array_sort(a, m);
4157   l = a[0];
4158   j = 1;
4159   for (i=1; i<m; i++) {
4160     l_aux = a[i];
4161     if (l_aux != l) {
4162       if (l_aux == not(l)) return false; // true clause
4163       a[j++] = l_aux;
4164       l = l_aux;
4165     }
4166   }
4167   m = j;
4168 
4169   // remove false literals/check for true literals
4170   j = 0;
4171   for (i=0; i<m; i++) {
4172     l = a[i];
4173     switch (literal_base_value(s, l)) {
4174     case VAL_FALSE:
4175       break;
4176     case VAL_UNDEF_FALSE:
4177     case VAL_UNDEF_TRUE:
4178       a[j++] = l;
4179       break;
4180     case VAL_TRUE:
4181       return false; // true clause
4182     }
4183   }
4184 
4185   *n = j;
4186   return true;
4187 }
4188 
4189 
4190 
4191 
4192 
4193 /*
4194  * External API to add clauses:
4195  * - can be called if s->status is IDLE or SEARCHING
4196  * - if a clause is added on the fly, when decision_level > base_level,
4197  *   we copy it into the lemma queue for future processing.
4198  * The theory solver may call the clause-addition function within
4199  * its propagate or backtrack functions.
4200  */
4201 
4202 /*
4203  * Check for on-the-fly addition
4204  * (if compiled in DEBUG mode also abort
4205  *  if s->status is not IDLE or SEARCHING or INTERRUPTED).
4206  */
on_the_fly(smt_core_t * s)4207 static bool on_the_fly(smt_core_t *s) {
4208   assert((s->status == STATUS_IDLE && s->decision_level == s->base_level) ||
4209          (s->status == STATUS_SEARCHING && s->decision_level >= s->base_level) ||
4210          (s->status == STATUS_INTERRUPTED && s->decision_level >= s->base_level));
4211   return s->status != STATUS_IDLE;
4212 }
4213 
4214 /*
4215  * Record the empty clause as a conflict
4216  * - if resolve conflict is called after this, it will do the
4217  * right thing (namely, see that the conflict can't be resolved).
4218  */
record_empty_conflict(smt_core_t * s)4219 static void record_empty_conflict(smt_core_t *s) {
4220   assert(s->decision_level == s->base_level);
4221 
4222 #if TRACE
4223   printf("---> DPLL:   Add empty clause: {}\n");
4224   fflush(stdout);
4225 #endif
4226   s->inconsistent = true;
4227   s->conflict_buffer[0] = end_clause;
4228   s->conflict = s->conflict_buffer;
4229 }
4230 
4231 
4232 /*
4233  * Add the empty clause (we provide this for completeness)
4234  */
add_empty_clause(smt_core_t * s)4235 void add_empty_clause(smt_core_t *s) {
4236   if (on_the_fly(s)) {
4237     push_lemma(&s->lemmas, 0, NULL);
4238     return;
4239   }
4240   record_empty_conflict(s);
4241 }
4242 
4243 
4244 /*
4245  * Add a unit clause
4246  */
add_unit_clause(smt_core_t * s,literal_t l)4247 void add_unit_clause(smt_core_t *s, literal_t l) {
4248   if (on_the_fly(s) && s->decision_level > s->base_level) {
4249 #if DEBUG
4250     check_lemma(s, 1, &l);
4251 #endif
4252     push_lemma(&s->lemmas, 1, &l);
4253     return;
4254   }
4255 
4256 #if TRACE
4257   printf("---> DPLL:   Add unit clause: { ");
4258   print_literal(stdout, l);
4259   printf(" }\n");
4260   fflush(stdout);
4261 #endif
4262 
4263   assert(0 <= l && l < s->nlits);
4264 
4265   if (literal_value(s, l) == VAL_TRUE && s->level[var_of(l)] <= s->base_level) {
4266     return; // l is already true at the base level
4267   }
4268 
4269   if (literal_value(s, l) == VAL_FALSE) {
4270     // conflict (the whole thing is unsat)
4271     s->inconsistent = true;
4272     s->conflict = s->conflict_buffer;
4273     s->conflict_buffer[0] = l;
4274     s->conflict_buffer[1] = end_clause;
4275 
4276   } else {
4277     assign_literal(s, l);
4278     s->nb_unit_clauses ++;
4279   }
4280 }
4281 
4282 
4283 /*
4284  * Simplify then add clause a[0 ... n-1]
4285  * - this modifies array a
4286  */
add_clause_unsafe(smt_core_t * s,uint32_t n,literal_t * a)4287 void add_clause_unsafe(smt_core_t *s, uint32_t n, literal_t *a) {
4288   if (on_the_fly(s)) {
4289 #if DEBUG
4290     check_lemma(s, n, a);
4291 #endif
4292     push_lemma(&s->lemmas, n, a);
4293     return;
4294   }
4295 
4296   if (preprocess_clause(s, &n, a)) {
4297     if (n > 2) {
4298       //      add_simplified_clause(s, n, a);
4299       new_problem_clause(s, n, a);
4300     } else if (n == 2) {
4301       //      add_simplified_binary_clause(s, a[0], a[1]);
4302       direct_binary_clause(s, a[0], a[1]);
4303     } else if (n == 1) {
4304       add_simplified_unit_clause(s, a[0]);
4305     } else {
4306       record_empty_conflict(s);
4307     }
4308   }
4309 #if TRACE
4310   else {
4311     printf("---> DPLL:   Skipped true clause\n");
4312     fflush(stdout);
4313   }
4314 #endif
4315 }
4316 
4317 /*
4318  * Simplify then add clause a[0 ... n-1]
4319  * - makes a copy of a so it's safe to use
4320  */
add_clause(smt_core_t * s,uint32_t n,literal_t * a)4321 void add_clause(smt_core_t *s, uint32_t n, literal_t *a) {
4322   ivector_t *v;
4323 
4324   if (on_the_fly(s)) {
4325 #if DEBUG
4326     check_lemma(s, n, a);
4327 #endif
4328     push_lemma(&s->lemmas, n, a);
4329     return;
4330   }
4331 
4332   // use s->buffer2 as an auxiliary buffer to make a copy of a[0 .. n-1]
4333   v = &s->buffer2;
4334   assert(v->size == 0);
4335   ivector_copy(v, a, n);
4336   assert(v->size == n);
4337 
4338   // use the copy here
4339   a = v->data;
4340   if (preprocess_clause(s, &n, a)) {
4341     if (n > 2) {
4342       //      add_simplified_clause(s, n, a);
4343       new_problem_clause(s, n, a);
4344     } else if (n == 2) {
4345       //      add_simplified_binary_clause(s, a[0], a[1]);
4346       direct_binary_clause(s, a[0], a[1]);
4347     } else if (n == 1) {
4348       add_simplified_unit_clause(s, a[0]);
4349     } else {
4350       record_empty_conflict(s);
4351     }
4352   }
4353 #if TRACE
4354   else {
4355     printf("---> DPLL:   Skipped true clause\n");
4356     fflush(stdout);
4357   }
4358 #endif
4359 
4360   ivector_reset(v);
4361 }
4362 
4363 
4364 /*
4365  * Short cuts
4366  */
add_binary_clause(smt_core_t * s,literal_t l1,literal_t l2)4367 void add_binary_clause(smt_core_t *s, literal_t l1, literal_t l2) {
4368   literal_t a[2];
4369 
4370   a[0] = l1;
4371   a[1] = l2;
4372   add_clause_unsafe(s, 2, a);
4373 }
4374 
add_ternary_clause(smt_core_t * s,literal_t l1,literal_t l2,literal_t l3)4375 void add_ternary_clause(smt_core_t *s, literal_t l1, literal_t l2, literal_t l3) {
4376   literal_t a[3];
4377 
4378   a[0] = l1;
4379   a[1] = l2;
4380   a[2] = l3;
4381   add_clause_unsafe(s, 3, a);
4382 }
4383 
4384 
4385 
4386 
4387 
4388 /********************************
4389  *  DEAL WITH THE LEMMA QUEUE   *
4390  *******************************/
4391 
4392 /*
4393  * Find the length of a lemma a:
4394  * - a must be terminated by null_literal (or any negative end marker)
4395  */
lemma_length(literal_t * a)4396 static uint32_t lemma_length(literal_t *a) {
4397   uint32_t n;
4398 
4399   n = 0;
4400   while (*a >= 0) {
4401     a ++;
4402     n ++;
4403   }
4404   return n;
4405 }
4406 
4407 
4408 /*
4409  * Add lemma: similar to add_clause but does more work
4410  * - n = length of the lemma
4411  * - a = array of literals (lemma is a[0] ... a[n-1])
4412  */
add_lemma(smt_core_t * s,uint32_t n,literal_t * a)4413 static void add_lemma(smt_core_t *s, uint32_t n, literal_t *a) {
4414   if (preprocess_clause(s, &n, a)) {
4415     if (n > 2) {
4416       add_simplified_clause(s, n, a);
4417     } else if (n == 2) {
4418       add_simplified_binary_clause(s, a[0], a[1]);
4419     } else if (n == 1) {
4420       add_simplified_unit_clause(s, a[0]);
4421     } else {
4422       backtrack_to_base_level(s);
4423       record_empty_conflict(s);
4424     }
4425   }
4426 #if TRACE
4427   else {
4428     printf("---> DPLL:   Skipped true lemma\n");
4429     fflush(stdout);
4430   }
4431 #endif
4432 
4433 }
4434 
4435 
4436 /*
4437  * Add all queued lemmas to the database.
4438  * - this may cause backtracking
4439  * - a conflict clause may be recorded
4440  * If so, conflict resolution must be called outside this function
4441  */
add_all_lemmas(smt_core_t * s)4442 static void add_all_lemmas(smt_core_t *s) {
4443   lemma_block_t *tmp;
4444   literal_t *lemma;
4445   uint32_t i, j, n;
4446 
4447   for (i=0; i<s->lemmas.free_block; i++) {
4448     tmp = s->lemmas.block[i];
4449     lemma = tmp->data;
4450     j = 0;
4451     while (j < tmp->ptr) {
4452       /*
4453        * it's possible for new lemmas to be added within this loop
4454        * because clause addition may cause backtracking and
4455        * the theory solver is allowed to create lemmas within backtrack.
4456        */
4457       n = lemma_length(lemma);
4458       add_lemma(s, n, lemma);
4459       n ++; // skip the end marker
4460       j += n;
4461       lemma += n;
4462     }
4463   }
4464 
4465   // Empty the queue now:
4466   reset_lemma_queue(&s->lemmas);
4467 }
4468 
4469 
4470 
4471 
4472 
4473 /*********************************
4474  *  DELETION OF LEARNED CLAUSES  *
4475  ********************************/
4476 
4477 /*
4478  * Reorder an array  a[low ... high-1] of learned clauses so that
4479  * the clauses are divided in two half arrays:
4480  * - the clauses of highest activities are all stored in a[low...half - 1]
4481  * - the clauses of lowest activities are in a[half ... high-1],
4482  * where half = (low + high) / 2.
4483  */
quick_split(clause_t ** a,uint32_t low,uint32_t high)4484 static void quick_split(clause_t **a, uint32_t low, uint32_t high) {
4485   uint32_t i, j, half;
4486   float pivot;
4487   clause_t *aux;
4488 
4489   if (high <= low + 1) return;
4490 
4491   half = (low + high)/2;
4492 
4493   do {
4494     i = low;
4495     j = high;
4496     pivot = get_activity(a[i]);
4497 
4498     do { j --; } while (get_activity(a[j]) < pivot);
4499     do { i ++; } while (i <= j && get_activity(a[i]) > pivot);
4500 
4501     while (i < j) {
4502       // a[i].act <= pivot and a[j].act >= pivot: swap a[i] and a[j]
4503       aux = a[i];
4504       a[i] = a[j];
4505       a[j] = aux;
4506 
4507       do { j--; } while (get_activity(a[j]) < pivot);
4508       do { i++; } while (get_activity(a[i]) > pivot);
4509     }
4510 
4511     // a[j].act >= pivot, a[low].act = pivot: swap a[low] and a[i]
4512     aux = a[low];
4513     a[low] = a[j];
4514     a[j] = aux;
4515 
4516     /*
4517      * at this point:
4518      * - all clauses in a[low,.., j - 1] have activity >= pivot
4519      * - activity of a[j] == pivot
4520      * - all clauses in a[j+1,..., high-1] have activity <= pivot
4521      * reapply the procedure to whichever of the two subarrays
4522      * contains the half point
4523      */
4524     if (j < half) {
4525       low = j + 1;
4526     } else {
4527       high = j;
4528     }
4529   } while (j != half);
4530 }
4531 
4532 
4533 /*
4534  * Apply this to a vector v of learned_clauses
4535  */
reorder_clause_vector(clause_t ** v)4536 static void reorder_clause_vector(clause_t **v) {
4537   quick_split(v, 0, get_cv_size(v));
4538 }
4539 
4540 
4541 /*
4542  * Auxiliary function: follow clause list of l0
4543  * Remove all clauses marked for removal
4544  */
cleanup_watch_list(smt_core_t * s,literal_t l0)4545 static void cleanup_watch_list(smt_core_t *s, literal_t l0) {
4546   link_t lnk;
4547   clause_t *cl;
4548   link_t *list;
4549 
4550   list = s->watch + l0;
4551   for (lnk = *list; lnk != NULL_LINK; lnk = next_of(lnk)) {
4552     cl = clause_of(lnk);
4553     if (! is_clause_to_be_removed(cl)) {
4554       *list = lnk;
4555       list = cdr_ptr(lnk);
4556     }
4557   }
4558 
4559   *list = NULL_LINK; // end of list
4560 }
4561 
4562 
4563 /*
4564  * Update all watch lists: remove all clauses marked for deletion.
4565  */
cleanup_watch_lists(smt_core_t * s)4566 static void cleanup_watch_lists(smt_core_t *s) {
4567   uint32_t i, n;
4568 
4569   n = s->nlits;
4570   for (i=0; i<n; i ++) {
4571     cleanup_watch_list(s, i);
4572   }
4573 }
4574 
4575 
4576 /*
4577  * Check whether cl is an antecedent clause
4578  */
clause_is_locked(smt_core_t * s,clause_t * cl)4579 static bool clause_is_locked(smt_core_t *s, clause_t *cl) {
4580   bvar_t x0, x1;
4581 
4582   x0 = var_of(get_first_watch(cl));
4583   x1 = var_of(get_second_watch(cl));
4584 
4585   return (bval_is_def(s->value[x0]) && s->antecedent[x0] == mk_clause0_antecedent(cl))
4586     || (bval_is_def(s->value[x1]) && s->antecedent[x1] == mk_clause1_antecedent(cl));
4587 }
4588 
4589 
4590 /*
4591  * Delete all clauses that are marked for deletion
4592  */
delete_learned_clauses(smt_core_t * s)4593 static void delete_learned_clauses(smt_core_t *s) {
4594   uint32_t i, j, n;
4595   clause_t **v;
4596 
4597   v = s->learned_clauses;
4598   n = get_cv_size(v);
4599 
4600   // clean up all the watch-literal lists
4601   cleanup_watch_lists(s);
4602 
4603   // do the real deletion
4604   s->stats.learned_literals = 0;
4605 
4606   j = 0;
4607   for (i = 0; i<n; i++) {
4608     if (is_clause_to_be_removed(v[i])) {
4609       delete_learned_clause(v[i]);
4610     } else {
4611       s->stats.learned_literals += clause_length(v[i]);
4612       v[j] = v[i];
4613       j ++;
4614     }
4615   }
4616 
4617   // set new size of the learned clause vector
4618   set_cv_size(s->learned_clauses, j);
4619   s->nb_clauses -= (n - j);
4620 
4621   s->stats.learned_clauses_deleted += (n - j);
4622 }
4623 
4624 
4625 /*
4626  * Delete half the learned clauses, minus the locked ones (Minisat style).
4627  * This is expensive: the function scans and reconstructs the
4628  * watched lists.
4629  */
reduce_clause_database(smt_core_t * s)4630 void reduce_clause_database(smt_core_t *s) {
4631   uint32_t i, n;
4632   clause_t **v;
4633   float act_threshold;
4634 
4635   v = s->learned_clauses;
4636   n = get_cv_size(v);
4637   if (n == 0) return;
4638 
4639   // put the clauses with lowest activity in the upper
4640   // half of the learned clause vector.
4641   reorder_clause_vector(v);
4642 
4643   act_threshold = s->cla_inc/n;
4644 
4645   // prepare for deletion: all non-locked clauses, with activity less
4646   // than activity_threshold are marked for deletion.
4647   for (i=0; i<n/2; i++) {
4648     if (get_activity(v[i]) <= act_threshold && ! clause_is_locked(s, v[i])) {
4649       mark_for_removal(v[i]);
4650     }
4651   }
4652   for (i = n/2; i<n; i++) {
4653     if (! clause_is_locked(s, v[i])) {
4654       mark_for_removal(v[i]);
4655     }
4656   }
4657 
4658   delete_learned_clauses(s);
4659   s->stats.reduce_calls ++;
4660 }
4661 
4662 
4663 
4664 
4665 
4666 /*******************************************************
4667  *  ZCHAFF-STYLE CLAUSE DELETION (AS IN YICES 1.0.XX)  *
4668  ******************************************************/
4669 
4670 /*
4671  * Number of unassigned literals in clause cl
4672  */
unassigned_literals(smt_core_t * s,clause_t * cl)4673 static uint32_t unassigned_literals(smt_core_t *s, clause_t *cl) {
4674   uint32_t n;
4675   literal_t l, *a;
4676 
4677   n = 0;
4678   a = cl->cl;
4679   l = *a;
4680   while (l >= 0) {
4681     if (literal_is_unassigned(s,l)) n ++;
4682     a ++;
4683     l = *a;
4684   }
4685 
4686   return n;
4687 }
4688 
4689 
4690 /*
4691  * Delete irrelevant clauses (Zchaff-style)
4692  * - split the set of learned clauses into two parts: old-clauses and young-clauses
4693  * - if there are n learned clauses in total, then the n/young_ratio most recent are young,
4694  *   the rest are old. (young_ratio is 16)
4695  */
remove_irrelevant_learned_clauses(smt_core_t * s)4696 void remove_irrelevant_learned_clauses(smt_core_t *s) {
4697   clause_t **v;
4698   clause_t *cl;
4699   uint32_t i, n, p, relevance;
4700   float coeff;
4701 
4702   v = s->learned_clauses;
4703   n = get_cv_size(v);
4704   if (n == 0) return;
4705 
4706   p = n - n/TAIL_RATIO;
4707   coeff = (float) (HEAD_ACTIVITY - TAIL_ACTIVITY)/n;
4708 
4709   for (i=0; i<n; i++) {
4710     cl = v[i];
4711     if (! clause_is_locked(s, cl)) {
4712       relevance = i < p ? HEAD_RELEVANCE : TAIL_RELEVANCE;
4713       if (get_activity(cl) < HEAD_ACTIVITY - coeff * i &&
4714           unassigned_literals(s, cl) > relevance) {
4715         mark_for_removal(cl);
4716       }
4717     }
4718   }
4719 
4720   delete_learned_clauses(s);
4721   s->stats.remove_calls ++;
4722 }
4723 
4724 
4725 
4726 
4727 
4728 
4729 /***********************************************************
4730  *  SIMPLIFICATION: REMOVE CLAUSES TRUE AT THE BASE LEVEL  *
4731  **********************************************************/
4732 
4733 /*
4734  * Variant of literal_value: l can be negative
4735  */
unsafe_literal_value(smt_core_t * s,literal_t l)4736 static inline bval_t unsafe_literal_value(smt_core_t *s, literal_t l) {
4737   assert(end_learned <= l && l <= (int32_t) s->nlits);
4738   return lit_val(s->value, l);
4739 }
4740 
4741 
4742 /*
4743  * Variant of literal_is_unassigned (same reason)
4744  */
unsafe_literal_is_unassigned(smt_core_t * s,literal_t l)4745 static inline bval_t unsafe_literal_is_unassigned(smt_core_t *s, literal_t l) {
4746   assert(end_learned <= l && l <= (int32_t) s->nlits);
4747   return bval_is_undef(s->value[var_of(l)]);
4748 }
4749 
4750 
4751 /*
4752  * Simplify clause cl, given the current literal assignment
4753  * - mark cl for deletion if it's true
4754  * - otherwise remove the false literals
4755  * The watched literals are unchanged.
4756  *
4757  * Update the counters aux_clauses and aux_literals if the clause
4758  * is not marked for removal.
4759  *
4760  * This is sound only at level 0.
4761  */
simplify_clause(smt_core_t * s,clause_t * cl)4762 static void simplify_clause(smt_core_t *s, clause_t *cl) {
4763   uint32_t i, j;
4764   literal_t l;
4765 
4766   assert(s->base_level == 0 && s->decision_level ==0);
4767 
4768   i = 0;
4769   j = 0;
4770   do {
4771     l = cl->cl[i];
4772     i ++;
4773     switch (unsafe_literal_value(s, l)) {
4774     case VAL_FALSE:
4775       break;
4776 
4777     case VAL_UNDEF_FALSE:
4778     case VAL_UNDEF_TRUE:
4779       cl->cl[j] = l;
4780       j ++;
4781       break;
4782 
4783     case VAL_TRUE:
4784       mark_for_removal(cl);
4785       return;
4786     }
4787   } while (l >= 0);
4788 
4789   s->aux_literals += j - 1;
4790   s->aux_clauses ++;
4791   // could migrate cl to two-literal if j is 3??
4792 }
4793 
4794 
4795 /*
4796  * Check whether cl is true at the base level. If so mark it
4797  * for removal.
4798  */
mark_true_clause(smt_core_t * s,clause_t * cl)4799 static void mark_true_clause(smt_core_t *s, clause_t *cl) {
4800   uint32_t i;
4801   literal_t l;
4802 
4803   assert(s->base_level == s->decision_level);
4804 
4805   i = 0;
4806   do {
4807     l = cl->cl[i];
4808     i ++;
4809     if (unsafe_literal_value(s, l) == VAL_TRUE) {
4810       mark_for_removal(cl);
4811       return;
4812     }
4813   } while (l >= 0);
4814 
4815   s->aux_literals += (i - 1);
4816   s->aux_clauses ++;
4817 }
4818 
4819 
4820 /*
4821  * Simplify the set of clauses given the current assignment:
4822  * - remove all clauses that are true (from the watched literals)
4823  * - remove false literals from learned clauses
4824  */
simplify_clause_set(smt_core_t * s)4825 static void simplify_clause_set(smt_core_t *s) {
4826   uint32_t i, j, n;
4827   clause_t **v;
4828 
4829   assert(s->decision_level == s->base_level);
4830 
4831   if (s->base_level == 0) {
4832     /*
4833      * Apply thorough simplifications at level 0
4834      */
4835     // simplify problem clauses
4836     s->aux_literals = 0;
4837     s->aux_clauses = 0;
4838     v = s->problem_clauses;
4839     n = get_cv_size(v);
4840     for (i=0; i<n; i++) {
4841       if (! is_clause_to_be_removed(v[i]) &&
4842           ! clause_is_locked(s, v[i])) {
4843         simplify_clause(s, v[i]);
4844       }
4845     }
4846     s->stats.prob_literals = s->aux_literals;
4847     s->nb_prob_clauses = s->aux_clauses;
4848 
4849     // simplify learned clauses
4850     s->aux_literals = 0;
4851     s->aux_clauses = 0;
4852     v = s->learned_clauses;
4853     n = get_cv_size(v);
4854     for (i=0; i<n; i++) {
4855       assert(! is_clause_to_be_removed(v[i]));
4856       if (! clause_is_locked(s, v[i])) {
4857         simplify_clause(s, v[i]);
4858       }
4859     }
4860     s->stats.learned_literals = s->aux_literals;
4861 
4862   } else {
4863     /*
4864      * Mark the true clauses for removal
4865      */
4866     // mark the true problem clauses
4867     s->aux_literals = 0;
4868     s->aux_clauses = 0;
4869     v = s->problem_clauses;
4870     n = get_cv_size(v);
4871     for (i=0; i<n; i++) {
4872       if (! is_clause_to_be_removed(v[i]) &&
4873           ! clause_is_locked(s, v[i])) {
4874         mark_true_clause(s, v[i]);
4875       }
4876     }
4877     s->stats.prob_literals = s->aux_literals;
4878     s->nb_prob_clauses = s->aux_clauses;
4879 
4880     // mark the true learned clauses
4881     s->aux_literals = 0;
4882     v = s->learned_clauses;
4883     n = get_cv_size(v);
4884     for (i=0; i<n; i++) {
4885       assert(! is_clause_to_be_removed(v[i]));
4886       if (! clause_is_locked(s, v[i])) {
4887         mark_true_clause(s, v[i]);
4888       }
4889     }
4890     s->stats.learned_literals = s->aux_literals;
4891 
4892   }
4893 
4894   /*
4895    * cleanup the watched literal lists: all marked (i.e., true)
4896    * clauses are removed from the lists.
4897    */
4898   cleanup_watch_lists(s);
4899 
4900   /*
4901    * Remove the true simplified problem clauses for good
4902    * if we're at base_level 0
4903    */
4904   if (s->base_level == 0) {
4905     v = s->problem_clauses;
4906     n = get_cv_size(v);
4907     j = 0;
4908     for (i=0; i<n; i++) {
4909       if (is_clause_to_be_removed(v[i])) {
4910         delete_clause(v[i]);
4911       } else {
4912         v[j] = v[i];
4913         j ++;
4914       }
4915     }
4916     set_cv_size(v, j);
4917     s->nb_clauses -= n - j;
4918     s->stats.prob_clauses_deleted += n - j;
4919   }
4920 
4921 
4922   /*
4923    * Remove the marked (i.e. true) learned clauses for good
4924    */
4925   v = s->learned_clauses;
4926   n = get_cv_size(v);
4927   j = 0;
4928   for (i=0; i<n; i++) {
4929     if (is_clause_to_be_removed(v[i])) {
4930       delete_learned_clause(v[i]);
4931     } else {
4932       v[j] = v[i];
4933       j ++;
4934     }
4935   }
4936   set_cv_size(v, j);
4937   s->nb_clauses -= n - j;
4938   s->stats.learned_clauses_deleted += n - j;
4939 }
4940 
4941 
4942 /*
4943  * Clean up a binary-clause vector v
4944  * - assumes that v is non-null
4945  * - remove all literals of v that are assigned at the base level
4946  * - for each deleted literal, increment sol->stats.aux_literals.
4947  * This is sound only at level 0.
4948  */
cleanup_binary_clause_vector(smt_core_t * s,literal_t * v)4949 static void cleanup_binary_clause_vector(smt_core_t *s, literal_t *v) {
4950   uint32_t i, j;
4951   literal_t l;
4952 
4953   i = 0;
4954   j = 0;
4955   do {
4956     l = v[i++];
4957     if (unsafe_literal_is_unassigned(s, l)) { //keep l
4958       v[j ++] = l;
4959     }
4960   } while (l >= 0); // end-marker is copied too
4961 
4962   s->aux_literals += i - j;
4963   set_lv_size(v, j - 1);
4964 }
4965 
4966 
4967 /*
4968  * Simplify all binary vectors affected by the current assignment
4969  * - scan the literals in the stack from sol->simplify_bottom to sol->stack.top
4970  * - remove all the binary clauses that contain one such literal
4971  * - free the binary watch vectors
4972  *
4973  * Should not be used at base_level > 0, otherwise pop won't restore the
4974  * binary clauses properly.
4975  */
simplify_binary_vectors(smt_core_t * s)4976 static void simplify_binary_vectors(smt_core_t *s) {
4977   uint32_t i, j, n;
4978   literal_t l0, *v0, l1;
4979 
4980   assert(s->decision_level == 0 && s->base_level == 0);
4981 
4982   s->aux_literals = 0;   // counts the number of literals removed
4983   for (i = s->simplify_bottom; i < s->stack.top; i++) {
4984     l0 = s->stack.lit[i];
4985 
4986     // remove all binary clauses that contain l0
4987     v0 = s->bin[l0];
4988     if (v0 != NULL) {
4989       n = get_lv_size(v0);
4990       for (j=0; j<n; j++) {
4991         l1 = v0[j];
4992 	if (literal_is_unassigned(s, l1)) {
4993           // sol->bin[l1] is non null.
4994           assert(s->bin[l1] != NULL);
4995           cleanup_binary_clause_vector(s, s->bin[l1]);
4996         }
4997       }
4998 
4999       delete_literal_vector(v0);
5000       s->bin[l0] = NULL;
5001       s->aux_literals += n;
5002     }
5003 
5004     // remove all binary clauses that contain not(l0)
5005     l0 = not(l0);
5006     v0 = s->bin[l0];
5007     if (v0 != NULL) {
5008       s->aux_literals += get_lv_size(v0);
5009       delete_literal_vector(v0);
5010       s->bin[l0] = NULL;
5011     }
5012   }
5013 
5014   s->aux_literals /= 2;
5015   s->stats.bin_clauses_deleted += s->aux_literals;
5016   s->nb_bin_clauses -= s->aux_literals;
5017 
5018   s->aux_literals = 0;
5019 }
5020 
5021 
5022 /*
5023  * Simplify the database: problem clauses and learned clauses
5024  * - remove clauses that are true at the base level from the watched lists
5025  * - if base_level is 0, also remove binary clauses that are true at the
5026  *   base level.
5027  */
simplify_clause_database(smt_core_t * s)5028 static void simplify_clause_database(smt_core_t *s) {
5029   assert(s->stack.top == s->stack.prop_ptr && s->decision_level == s->base_level);
5030 
5031   simplify_clause_set(s);
5032   if (s->base_level == 0) {
5033     simplify_binary_vectors(s);
5034   }
5035 
5036   s->stats.simplify_calls ++;
5037 
5038   /*
5039    * The next call to simplify_clause_database is enabled when
5040    *   s->decision_level == base_level &&
5041    *   s->stack.top > s->simplify_bottom &&
5042    *   s->stats.propagations > s->simplify_props + s->simplify_threshold
5043    *
5044    * s->simplify_threshold is set to the total number of literals.
5045    *
5046    * This is an arbitrary choice that avoids calling simplify too often.
5047    * This is copied from Minisat.
5048    */
5049   s->simplify_bottom = s->stack.top;
5050   s->simplify_props = s->stats.propagations;
5051   s->simplify_threshold = s->stats.learned_literals + s->stats.prob_literals +
5052     2 * s->nb_bin_clauses;
5053 }
5054 
5055 
5056 
5057 
5058 /**************
5059  *  PUSH/POP  *
5060  *************/
5061 
5062 /*
5063  * Push:
5064  * - clear current assignment and reset status to IDLE if necessary
5065  * - save current base-level state
5066  * - notify the theory solver
5067  * - increase base level
5068  */
smt_push(smt_core_t * s)5069 void smt_push(smt_core_t *s) {
5070   uint32_t k;
5071 
5072   /*
5073    * Abort if push_pop is not enabled
5074    */
5075   assert((s->option_flag & PUSH_POP_MASK) != 0);
5076 
5077   /*
5078    * Reset assignment and status
5079    */
5080   if (s->status == STATUS_UNKNOWN || s->status == STATUS_SAT) {
5081     smt_clear(s);
5082   }
5083 
5084   assert(s->status == STATUS_IDLE && s->decision_level == s->base_level);
5085 
5086   /*
5087    * Save current state:
5088    * - number of variables
5089    * - number of unit clauses
5090    * - number of binary clauses
5091    * - number of problem clauses
5092    * - propagation pointers
5093    */
5094   trail_stack_save(&s->trail_stack,
5095                    s->nvars, s->nb_unit_clauses, s->binary_clauses.size,
5096                    get_cv_size(s->problem_clauses),
5097                    s->stack.prop_ptr, s->stack.theory_ptr);
5098 
5099   /*
5100    * Gate table
5101    */
5102   gate_table_push(&s->gates);
5103 
5104   /*
5105    * Notify the theory solver
5106    */
5107   s->th_ctrl.push(s->th_solver);
5108 
5109   /*
5110    * Increase the base_level (and decision_level)
5111    */
5112   k = s->base_level + 1;
5113   s->base_level = k;
5114   s->decision_level = k;
5115   if (s->stack.nlevels <= k) {
5116     increase_stack_levels(&s->stack);
5117   }
5118   s->stack.level_index[k] = s->stack.top;
5119 
5120 }
5121 
5122 
5123 /*
5124  * Mark all learned clauses for removal
5125  */
remove_all_learned_clauses(smt_core_t * s)5126 static void remove_all_learned_clauses(smt_core_t *s) {
5127   uint32_t i, n;
5128   clause_t **v;
5129 
5130   v = s->learned_clauses;
5131   n = get_cv_size(v);
5132 
5133   for (i=0; i<n; i++) {
5134     mark_for_removal(v[i]);
5135   }
5136 }
5137 
5138 
5139 /*
5140  * Mark problem clauses (at indices n, n+1, ...)
5141  */
remove_problem_clauses(smt_core_t * s,uint32_t n)5142 static void remove_problem_clauses(smt_core_t *s, uint32_t n) {
5143   uint32_t m;
5144   clause_t **v;
5145   clause_t *cl;
5146 
5147   v = s->problem_clauses;
5148   m = get_cv_size(v);
5149   while (n < m) {
5150     cl = v[n];
5151     if (! is_clause_to_be_removed(cl)) {
5152       mark_for_removal(cl);
5153     }
5154     n ++;
5155   }
5156 }
5157 
5158 
5159 /*
5160  * Reset the watch lists (to empty lists)
5161  */
reset_watch_lists(smt_core_t * s)5162 static void reset_watch_lists(smt_core_t *s) {
5163   uint32_t i, n;
5164 
5165   n = s->nlits;
5166   for (i=0; i<n; i++) {
5167     s->watch[i] = NULL_LINK;
5168   }
5169 }
5170 
5171 
5172 /*
5173  * Restore all non-binary/non-unit clauses (to previous base-level)
5174  * Also restore stats.prob_literals
5175  * - n = number of problem clauses at the start of the current base level
5176  */
restore_clauses(smt_core_t * s,uint32_t n)5177 static void restore_clauses(smt_core_t *s, uint32_t n) {
5178   uint32_t i, m, nlits;
5179   clause_t **v;
5180   clause_t *cl;
5181   literal_t l;
5182 
5183   // mark clauses for removal
5184   remove_all_learned_clauses(s);
5185   remove_problem_clauses(s, n);
5186 
5187   // empty the watch lists
5188   reset_watch_lists(s);
5189 
5190   // do the real deletion
5191   v = s->learned_clauses;
5192   m = get_cv_size(v);
5193   for (i=0; i<m; i++) {
5194     delete_learned_clause(v[i]);
5195   }
5196   reset_clause_vector(v);
5197 
5198   v = s->problem_clauses;
5199   m = get_cv_size(v);
5200   for (i=n; i<m; i++) {
5201     delete_clause(v[i]);
5202   }
5203   set_cv_size(v, n);
5204 
5205   /*
5206    * put all problem clauses back into the watch lists
5207    * and restore the marked problem clauses in v[0 ... n-1]
5208    */
5209   nlits = 0;   // to count the total number of literals
5210   for (i=0; i<n; i++) {
5211     cl = v[i];
5212     if (is_clause_to_be_removed(cl)) {
5213       restore_removed_clause(cl);
5214       assert(cl->cl[0] >= 0 && cl->cl[1] >= 0);
5215     }
5216     nlits += clause_length(cl);
5217 
5218     // add cl at the start of its watch lists
5219     l = cl->cl[0];
5220     s->watch[l] = cons(0, cl, s->watch[l]);
5221 
5222     l = cl->cl[1];
5223     s->watch[l] = cons(1, cl, s->watch[l]);
5224   }
5225 
5226 
5227   s->nb_clauses = n;
5228   s->nb_prob_clauses = n;
5229   s->stats.prob_literals = nlits;
5230   s->stats.learned_literals = 0;
5231 }
5232 
5233 
5234 /*
5235  * Keep binary clauses in binary_clauses[0... n-1]
5236  * Remove the ones in binary_clauses[n ... ]
5237  */
restore_binary_clauses(smt_core_t * s,uint32_t n)5238 static void restore_binary_clauses(smt_core_t *s, uint32_t n) {
5239   uint32_t i;
5240   literal_t l0, l1;
5241   literal_t *bin_clauses;
5242 
5243   bin_clauses = s->binary_clauses.data;
5244   i = s->binary_clauses.size;
5245   assert((i & 1) == 0  && (n & 1) == 0 && i >= n);
5246 
5247   // number of clauses removed = (i - n)/2
5248   s->nb_bin_clauses -= (i - n)/2;
5249 
5250   while (i > n) {
5251     i --;
5252     l0 = bin_clauses[i];
5253     i --;
5254     l1 = bin_clauses[i];
5255     // last clause added = { l1, l0 }
5256     assert(last_lv_elem(s->bin[l0]) == l1 && last_lv_elem(s->bin[l1]) == l0);
5257     literal_vector_pop(s->bin[l0]);
5258     literal_vector_pop(s->bin[l1]);
5259   }
5260 
5261   ivector_shrink(&s->binary_clauses, n);
5262 }
5263 
5264 
5265 /*
5266  * Keep variables 0 ... n-1. Remove the rest
5267  * Must be called after restore_clauses.
5268  *
5269  * Atoms are removed if needed, but we don't call
5270  * s->th_smt.delete_atom, since s->th_ctrl.pop has been
5271  * called before this.
5272  */
restore_variables(smt_core_t * s,uint32_t n)5273 static void restore_variables(smt_core_t *s, uint32_t n) {
5274   uint32_t i, nv;
5275   literal_t l0, l1;
5276 
5277   nv = s->nvars;
5278   for (i=n; i<nv; i++) {
5279     heap_remove(&s->heap, i);
5280     if (bvar_has_atom(s, i)) {
5281       remove_atom(&s->atoms, i);
5282     }
5283 
5284     l0 = pos_lit(i);
5285     l1 = neg_lit(i);
5286     delete_literal_vector(s->bin[l0]);
5287     delete_literal_vector(s->bin[l1]);
5288     s->bin[l0] = NULL;
5289     s->bin[l1] = NULL;
5290     s->watch[l0] = NULL_LINK;
5291     s->watch[l1] = NULL_LINK;
5292   }
5293 
5294   s->nvars = n;
5295   s->nlits = 2 * n;
5296 }
5297 
5298 
5299 /*
5300  * Remove the mark of all variables assigned at the current base_level
5301  */
clear_base_level_marks(smt_core_t * s)5302 static void clear_base_level_marks(smt_core_t *s) {
5303   uint32_t i, k, n;
5304   literal_t *u, l;
5305   bvar_t x;
5306 
5307   u = s->stack.lit;
5308   k = s->base_level;
5309   n = s->stack.top;
5310   for (i=s->stack.level_index[k]; i<n; i++) {
5311     l = u[i];
5312     x = var_of(l);
5313     assert(literal_value(s, l) == VAL_TRUE);
5314     assert(s->level[x] == k);
5315     assert(is_var_marked(s, x));
5316     clr_var_mark(s, x);
5317   }
5318 }
5319 
5320 
5321 /*
5322  * Pop: backtrack to previous base_level
5323  * - can be called after the search terminates or from an idle state
5324  * - should not be called if status is INTERRUPTED or SEARCHING
5325  */
smt_pop(smt_core_t * s)5326 void smt_pop(smt_core_t *s) {
5327   trail_t *top;
5328 
5329   /*
5330    * Abort if push_pop is not enabled or if there's no pushed state
5331    */
5332   assert((s->option_flag & PUSH_POP_MASK) != 0 && s->base_level > 0 &&
5333          s->status != STATUS_INTERRUPTED && s->status != STATUS_SEARCHING);
5334 
5335   // We need to backtrack before calling the pop function of th_solver
5336   backtrack_to_base_level(s);
5337   s->th_ctrl.pop(s->th_solver);
5338 
5339   clear_base_level_marks(s);
5340   top = trail_stack_top(&s->trail_stack);
5341   restore_clauses(s, top->nclauses);
5342   restore_binary_clauses(s, top->nbins);
5343 
5344   // the lemma queue may be non-empty so we must clear it here
5345   reset_lemma_queue(&s->lemmas);
5346 
5347   s->base_level --;
5348   backtrack(s, s->base_level);
5349   s->nb_unit_clauses = top->nunits;
5350 
5351   restore_variables(s, top->nvars);
5352 
5353   // restore the propagation pointers
5354   s->stack.prop_ptr = top->prop_ptr;
5355   s->stack.theory_ptr = top->theory_ptr;
5356 
5357   trail_stack_pop(&s->trail_stack);
5358 
5359   // gate table
5360   gate_table_pop(&s->gates);
5361 
5362   // reset status
5363   s->status = STATUS_IDLE;
5364 }
5365 
smt_interrupt_push(smt_core_t * s)5366 static void smt_interrupt_push(smt_core_t *s) {
5367   assert (!s->interrupt_push);
5368   smt_push(s);
5369   s->interrupt_push = true;
5370 }
5371 
smt_interrupt_pop(smt_core_t * s)5372 static void smt_interrupt_pop(smt_core_t *s) {
5373   if (s->interrupt_push) {
5374     smt_pop(s);
5375     s->interrupt_push = false;
5376   }
5377 }
5378 
5379 /*
5380  * Cleanup after search was interrupted or returned unsat
5381  * - the clean state was pushed on the trail stack on start_search
5382  * - we just call pop
5383  */
smt_cleanup(smt_core_t * s)5384 void smt_cleanup(smt_core_t *s) {
5385   assert((s->status == STATUS_INTERRUPTED || s->status == STATUS_UNSAT)
5386          && (s->option_flag & CLEAN_INTERRUPT_MASK) != 0);
5387   s->status = STATUS_IDLE; // make sure pop does not abort
5388   smt_interrupt_pop(s);
5389 }
5390 
5391 
5392 /*
5393  * Clear the current boolean assignment and reset status to IDLE
5394  */
smt_clear(smt_core_t * s)5395 void smt_clear(smt_core_t *s) {
5396   assert(s->status == STATUS_SAT || s->status == STATUS_UNKNOWN);
5397 
5398   // Give a chance to the theory solver to cleanup its own state
5399   s->th_ctrl.clear(s->th_solver);
5400 
5401   /*
5402    * In clean-interrupt mode, we restore the state to what it was
5403    * before the search started. This also backtracks to the base_level
5404    * and clears the current assignment.
5405    */
5406   if ((s->option_flag & CLEAN_INTERRUPT_MASK) != 0) {
5407     smt_interrupt_pop(s);
5408   } else {
5409     // no state to restore. Just backtrack and clear the assignment
5410     backtrack_to_base_level(s);
5411     s->status = STATUS_IDLE;
5412   }
5413 }
5414 
5415 
5416 /*
5417  * Cleanup after unsat.
5418  */
smt_clear_unsat(smt_core_t * s)5419 void smt_clear_unsat(smt_core_t *s) {
5420   smt_status_t saved_status;
5421 
5422   assert(s->status == STATUS_UNSAT);
5423   saved_status = STATUS_UNSAT;
5424 
5425   /*
5426    * Remove assumptions by backtracking to the base_level
5427    */
5428   if (s->has_assumptions) {
5429     backtrack_to_base_level(s);
5430 
5431     // cleanup
5432     s->has_assumptions = false;
5433     s->num_assumptions = 0;
5434     s->assumption_index = 0;
5435     s->assumptions = NULL;
5436     s->bad_assumption = null_literal;
5437 
5438     // status returns to IDLE
5439     s->status = STATUS_IDLE;
5440     saved_status = STATUS_IDLE;
5441   }
5442 
5443   assert(s->decision_level == s->base_level);
5444 
5445   /*
5446    * In clean-interrupt mode, we restore the state to what it was
5447    * before the search started (using pop).
5448    */
5449   if ((s->option_flag & CLEAN_INTERRUPT_MASK) != 0) {
5450     smt_interrupt_pop(s);
5451     s->status = saved_status;
5452   }
5453 }
5454 
5455 
5456 
5457 /*****************
5458  *  CHECKPOINTS  *
5459  ****************/
5460 
5461 /*
5462  * Record current decision level and number of variables
5463  * - any variables created after the checkpoints will
5464  * be deleted when the solver backtracks to a lower decision level
5465  */
smt_checkpoint(smt_core_t * s)5466 void smt_checkpoint(smt_core_t *s) {
5467   assert(s->status == STATUS_SEARCHING ||
5468          s->status == STATUS_INTERRUPTED);
5469   push_checkpoint(&s->checkpoints, s->decision_level, s->nvars);
5470   s->cp_flag = false;
5471 }
5472 
5473 
5474 /*
5475  * Heuristic for deletion of variables and atoms created on the fly:
5476  *
5477  * The checkpoints divide the boolean variables in disjoint segments
5478  * - the top segment is [n, s->nvars - 1] where n <= nvars
5479  * - each segment is assigned a decision level (the decision level at the
5480  *   time the checkpoint was created)
5481  * - the top segment can be deleted if the following conditions are satisfied:
5482  *   1) s->cp_flag is true (i.e., after backtracking)
5483  *   2) the segment level is <= the current decision level in s
5484  *   3) all variables in the segment are unassigned.
5485  * - if these conditions hold, we remove all variables in [n, s->nvars - 1]
5486  *   and all the atoms attached to these variable, then we consider the next
5487  *   segment in the checkpoint stack.
5488  * - after this, we remove all the clauses that refer to a deleted variables
5489  */
5490 
5491 
5492 /*
5493  * Attempt to remove the top segment [n, s->nvars - 1]
5494  * - if all variables in this segment are unassigned, then their
5495  *   atoms are removed and the function returns true
5496  * - otherwise, the function returns false and does nothing
5497  * Note: it does nothing if n == s->nvars, but returns true in that case.
5498  * The boolean variables are not fully deleted yet.
5499  */
delete_variables(smt_core_t * s,uint32_t n)5500 static bool delete_variables(smt_core_t *s, uint32_t n) {
5501   bvar_t x;
5502   atom_table_t *tbl;
5503   uint32_t m;
5504 
5505   assert(n <= s->nvars);
5506 
5507   m = s->nvars;
5508   for (x=n; x<m; x++) {
5509     if (bvar_is_assigned(s, x)) return false;
5510   }
5511 
5512   // delete the atoms
5513   tbl = &s->atoms;
5514   if (tbl->size < m) {
5515     m = tbl->size;
5516   }
5517   for (x=n; x<m; x++) {
5518     heap_remove(&s->heap, x);
5519     if (tst_bit(tbl->has_atom, x)) {
5520       s->th_smt.delete_atom(s->th_solver, tbl->atom[x]);
5521       remove_atom(tbl, x);
5522     }
5523   }
5524 
5525   // update s->nvars and s->nlits
5526   s->nvars = n;
5527   s->nlits = 2 * n;
5528 
5529   return true;
5530 }
5531 
5532 /*
5533  * Remove all literals >= max in literal vector v
5534  * - assumes that v is non-null
5535  */
cleanup_garbage_in_binary_clause_vector(smt_core_t * s,literal_t * v)5536 static void cleanup_garbage_in_binary_clause_vector(smt_core_t *s, literal_t *v) {
5537   uint32_t i, j;
5538   literal_t l, max;
5539 
5540   max = pos_lit(s->nvars);
5541   i = 0;
5542   j = 0;
5543   do {
5544     l = v[i++];
5545     if (l < max) { // keep l
5546       v[j ++] = l;
5547     }
5548   } while (l >= 0); // the end-marker is negative. It's copied too
5549 
5550   s->aux_literals += i - j; // number of deleted literals
5551   set_lv_size(v, j - 1);
5552 }
5553 
5554 
5555 /*
5556  * Remove all binary clauses that contain a removed variable.
5557  * - old_nvar = number of variables before removal
5558  */
remove_garbage_bin_clauses(smt_core_t * s,uint32_t old_nvars)5559 static void remove_garbage_bin_clauses(smt_core_t *s, uint32_t old_nvars) {
5560   literal_t max, l, l0, *v0;
5561   uint32_t i, j, n;
5562   ivector_t *v;
5563 
5564   max = pos_lit(s->nvars); // all literals of index >= max are dead
5565 
5566   // cleanup the binary_clause vector
5567   v = &s->binary_clauses;
5568   n = v->size;
5569   j = 0;
5570   for (i=0; i<n; i+=2) {
5571     if (v->data[i] < max && v->data[i+1] < max) {
5572       v->data[j] = v->data[i];
5573       v->data[j+1] = v->data[i+1];
5574       j += 2;
5575     }
5576   }
5577 
5578   // s->aux_literal counts the number of literals removed
5579   s->aux_literals = 0;
5580 
5581   // cleanup the vectors bin[l]
5582   for (l0=max; l0<pos_lit(old_nvars); l0++) {
5583     // l0 is a removed literal
5584     v0 = s->bin[l0];
5585     if (v0 != NULL) {
5586       n = get_lv_size(v0);
5587       for (j=0; j<n; j++) {
5588         l = v0[j];
5589         if (l < max && s->bin[l] != NULL) {
5590           cleanup_garbage_in_binary_clause_vector(s, s->bin[l]);
5591         }
5592       }
5593       delete_literal_vector(v0);
5594       s->bin[l0] = NULL;
5595       s->aux_literals += n;
5596       s->watch[l0] = NULL_LINK; // not strictly necessary
5597     }
5598   }
5599 
5600   // update the statistics
5601   s->aux_literals /= 2;
5602   s->stats.bin_clauses_deleted += s->aux_literals;
5603   s->nb_bin_clauses -= s->aux_literals;
5604 }
5605 
5606 
5607 
5608 /*
5609  * Check whether clause cl contains literals >= max
5610  * If it does, mark it for deletion.
5611  * Use s->aux_literals to count the number of literals kept
5612  */
mark_clause_to_remove(smt_core_t * s,clause_t * cl,literal_t max)5613 static void mark_clause_to_remove(smt_core_t *s, clause_t *cl, literal_t max) {
5614   uint32_t i;
5615   literal_t l;
5616 
5617   i = 0;
5618   l = cl->cl[i];
5619   while (l >= 0) {
5620     if (l >= max) {
5621       assert(! clause_is_locked(s, cl));
5622       mark_for_removal(cl);
5623       return;
5624     }
5625     i ++;
5626     l = cl->cl[i];
5627   }
5628   s->aux_literals += (i - 1);
5629 }
5630 
5631 
5632 
5633 /*
5634  * Cleanup the problem and learned clauses after removal of variables
5635  */
remove_garbage_clauses(smt_core_t * s)5636 static void remove_garbage_clauses(smt_core_t *s) {
5637   literal_t max;
5638   uint32_t i, j, n;
5639   clause_t **v;
5640 
5641   max = pos_lit(s->nvars); // all literals of index >= max are dead
5642 
5643   // mark clauses to be deleted
5644   s->aux_literals = 0;   // count the number of literals in non-deleted clauses
5645   v = s->problem_clauses;
5646   n = get_cv_size(v);
5647   for (i=0; i<n; i++) {
5648     mark_clause_to_remove(s, v[i], max);
5649   }
5650   s->stats.prob_literals = s->aux_literals;
5651 
5652   s->aux_literals = 0;
5653   v = s->learned_clauses;
5654   n = get_cv_size(v);
5655   for (i=0; i<n; i++) {
5656     mark_clause_to_remove(s, v[i], max);
5657   }
5658   s->stats.learned_literals = s->aux_literals;
5659 
5660   // clean up watched list for 0 ... nvars-1
5661   cleanup_watch_lists(s);
5662 
5663   // delete the problem clauses
5664   v = s->problem_clauses;
5665   n = get_cv_size(v);
5666   j = 0;
5667   for (i=0; i<n; i++) {
5668     if (is_clause_to_be_removed(v[i])) {
5669       delete_clause(v[i]);
5670     } else {
5671       v[j] = v[i];
5672       j++;
5673     }
5674   }
5675   set_cv_size(v, j);
5676   s->nb_clauses -= n - j;
5677   s->stats.prob_clauses_deleted += n - j;
5678 
5679   // delete the learned clauses
5680   v = s->learned_clauses;
5681   n = get_cv_size(v);
5682   j = 0;
5683   for (i=0; i<n; i++) {
5684     if (is_clause_to_be_removed(v[i])) {
5685       delete_learned_clause(v[i]);
5686     } else {
5687       v[j] = v[i];
5688       j ++;
5689     }
5690   }
5691   set_cv_size(v, j);
5692   s->nb_clauses -= n - j;
5693   s->stats.learned_clauses_deleted += n - j;
5694 }
5695 
5696 
5697 
5698 /*
5699  * Deletion of irrelevant atoms and variables
5700  */
delete_irrelevant_variables(smt_core_t * s)5701 static void delete_irrelevant_variables(smt_core_t *s) {
5702   uint32_t old_nvars;
5703   checkpoint_stack_t *cp;
5704   checkpoint_t *p;
5705   bool dflag;
5706 
5707   old_nvars = s->nvars;
5708 
5709   dflag = false; // true if some variables are removed
5710   cp = &s->checkpoints;
5711   for (;;) {
5712     if (empty_checkpoint_stack(cp)) break;
5713     p = top_checkpoint(cp);
5714     if (p->dlevel < s->decision_level) break; // can't delete that segment
5715     if (delete_variables(s, p->nvars)) {
5716       // variables in p->nvars to s->nvars have been removed
5717       dflag = true;
5718       pop_checkpoint(cp);
5719       assert(s->nvars == p->nvars);
5720     } else {
5721       break;
5722     }
5723   }
5724 
5725   if (dflag) {
5726     s->th_smt.end_atom_deletion(s->th_solver);
5727     remove_garbage_clauses(s);
5728     remove_garbage_bin_clauses(s, old_nvars);
5729   }
5730 }
5731 
5732 
5733 
5734 
5735 /*
5736  * Purge all literals that refer to a dynamic variable
5737  * from the assignment stack.
5738  */
purge_all_dynamic_atoms(smt_core_t * s)5739 static void purge_all_dynamic_atoms(smt_core_t *s) {
5740   checkpoint_stack_t *cp;
5741   literal_t *u, l;
5742   uint32_t base_nvars;
5743   uint32_t i, j, k;
5744   bvar_t x;
5745 
5746   assert(s->base_level == s->decision_level &&
5747          s->stack.top == s->stack.prop_ptr &&
5748          s->stack.top == s->stack.theory_ptr &&
5749          s->nb_unit_clauses == s->stack.top);
5750 
5751   cp = &s->checkpoints;
5752   if (non_empty_checkpoint_stack(cp)) {
5753     // number of variables to keep = nvars at the bottom checkpoint
5754     base_nvars = cp->data[0].nvars;
5755 
5756     // remove all literals whose var is >= base_nvars from
5757     // the assignment stack
5758     u = s->stack.lit;
5759     k = s->stack.top;
5760     j = 0;
5761     for (i=0; i<k; i++) {
5762       l = u[i];
5763       x = var_of(l);
5764       if (x >= base_nvars) {
5765         // variable to delete
5766         s->value[x] = VAL_UNDEF_FALSE;
5767       } else {
5768         // keep l
5769         u[j] = l;
5770         j ++;
5771       }
5772     }
5773 
5774     // restore the stack pointers
5775     s->stack.top = j;
5776     s->stack.prop_ptr = j;
5777     s->stack.theory_ptr = j;
5778 
5779     s->nb_unit_clauses = j;
5780   }
5781 
5782 }
5783 
5784 
5785 
5786 
5787 /**********************
5788  *  SEARCH FUNCTIONS  *
5789  *********************/
5790 
5791 /*
5792  * New round of assertions
5793  */
internalization_start(smt_core_t * s)5794 void internalization_start(smt_core_t *s) {
5795   assert(s->status == STATUS_IDLE && s->decision_level == s->base_level);
5796 
5797 #if TRACE
5798   printf("\n---> DPLL START\n");
5799   fflush(stdout);
5800 #endif
5801 
5802   s->inconsistent = false;
5803   s->theory_conflict = false;
5804   s->conflict = NULL;
5805   s->false_clause = NULL;
5806   s->th_ctrl.start_internalization(s->th_solver);
5807 }
5808 
5809 
5810 /*
5811  * Propagate at the base level
5812  * - this is used to detect early inconsistencies during internalization
5813  */
base_propagate(smt_core_t * s)5814 bool base_propagate(smt_core_t *s) {
5815   assert(s->status == STATUS_IDLE && s->decision_level == s->base_level);
5816 
5817 #if TRACE
5818   printf("\n---> DPLL BASE PROPAGATE\n");
5819   fflush(stdout);
5820 #endif
5821 
5822   /*
5823    * If s is inconsistent (i.e., the empty clause was added) then there's
5824    * nothing more to do.
5825    *
5826    * Otherwise, force a call to theory_propagation first
5827    * - this ensures that the theory solver has a chance to detect inconsistencies,
5828    *   even if it has not created atoms yet.
5829    * - this is necessary because asserted axioms may be handled directly by
5830    *   the solver, without causing literals/atoms to be created in the core.
5831    */
5832   if (!s->inconsistent && theory_propagation(s) && smt_propagation(s)) {
5833     return true;
5834   }
5835 
5836   assert(s->inconsistent);
5837   s->status = STATUS_UNSAT;
5838   return false;
5839 }
5840 
5841 /*
5842  * Prepare for the search:
5843  * - a = optional array of assumptions
5844  * - n = number of assumptions
5845  * - a[0 ... n-1] must all be valid literals in the core
5846  *
5847  * Effect:
5848  * - initialize variable heap
5849  * - store a pointer to the assumption array
5850  * - make an internal copy of the assumptions
5851  * - initialize variable heap
5852  * - set status to searching
5853  * - if clean_interrupt is enabled, save the current state to
5854  *   enable cleanup after interrupt (this uses push)
5855  */
start_search(smt_core_t * s,uint32_t n,const literal_t * a)5856 void start_search(smt_core_t *s, uint32_t n, const literal_t *a) {
5857   assert(s->status == STATUS_IDLE && s->decision_level == s->base_level);
5858 
5859 #if TRACE
5860   printf("\n---> DPLL START\n");
5861   fflush(stdout);
5862 #endif
5863 
5864   if ((s->option_flag & CLEAN_INTERRUPT_MASK) != 0) {
5865     /*
5866      * in clean-interrupt mode, save the current state so
5867      * that it can be restored after a call to stop_search.
5868      */
5869     smt_interrupt_push(s);
5870   }
5871 
5872   s->status = STATUS_SEARCHING;
5873   s->inconsistent = false;
5874   s->theory_conflict = false;
5875   s->conflict = NULL;
5876   s->false_clause = NULL;
5877 
5878   s->stats.restarts = 0;
5879   s->stats.simplify_calls = 0;
5880   s->stats.reduce_calls = 0;
5881   s->stats.decisions = 0;
5882   s->stats.random_decisions = 0;
5883   s->stats.conflicts = 0;
5884   s->simplify_bottom = 0;
5885   s->simplify_props = 0;
5886   s->simplify_threshold = 0;
5887 
5888   s->has_assumptions = (n > 0);
5889   s->num_assumptions = n;
5890   s->assumption_index = 0;
5891   s->assumptions = a;
5892   s->bad_assumption = null_literal;
5893 
5894   /*
5895    * Allow theory solver to do whatever initializations it needs
5896    */
5897   s->th_ctrl.start_search(s->th_solver);
5898 
5899 #if DEBUG
5900   check_heap_content(s);
5901   check_heap(s);
5902 #endif
5903 }
5904 
5905 
5906 /*
5907  * Stop the search: set status to interrupted
5908  * - this can be called from a signal handler to interrupt the solver
5909  * - if clean_interrupt is enabled,  the state at start_search can be restored by
5910  *   calling smt_cleanup(s)
5911  */
stop_search(smt_core_t * s)5912 void stop_search(smt_core_t *s) {
5913   if (s->status == STATUS_SEARCHING) {
5914     s->status = STATUS_INTERRUPTED;
5915   }
5916 }
5917 
5918 
5919 /*
5920  * Core solving function.
5921  *
5922  * It executes the following loop:
5923  * 1) if lemmas are present, integrate them to the clause database
5924  * 2) perform boolean and theory propagation
5925  * 3) if a conflict is found, resolve that conflict otherwise
5926  *    exit the loop.
5927  * 4) after a conflict is resolved, check whether the bound max_conflict
5928  *    is reached. If so exit.
5929  *
5930  * Output:
5931  * - true on normal exit
5932  * - false on early exit (i.e., max_conflict reached)
5933  */
smt_core_process(smt_core_t * s,uint64_t max_conflicts)5934 static bool smt_core_process(smt_core_t *s, uint64_t max_conflicts) {
5935   while (s->status == STATUS_SEARCHING) {
5936     if (s->inconsistent) {
5937       resolve_conflict(s);
5938       if (s->inconsistent) {
5939         // conflict could not be resolved: unsat problem
5940         // the lemma queue may be non-empty so we must clear it here
5941         reset_lemma_queue(&s->lemmas);
5942         s->status = STATUS_UNSAT;
5943       }
5944       // decay activities after every conflict
5945       s->cla_inc *= s->inv_cla_decay;
5946       s->heap.act_increment *= s->heap.inv_act_decay;
5947 
5948       // exit if max_conflict reached
5949       if (num_conflicts(s) >= max_conflicts) {
5950 	return false;
5951       }
5952 
5953     } else if (s->cp_flag) {
5954       delete_irrelevant_variables(s);
5955       s->cp_flag = false;
5956 
5957     } else if (! empty_lemma_queue(&s->lemmas)) {
5958       add_all_lemmas(s);
5959 
5960     } else {
5961       /*
5962        * propagation can create a conflict or add lemmas.
5963        * if it doesn't we're done.
5964        */
5965       if (smt_propagation(s) && empty_lemma_queue(&s->lemmas)) break;
5966     }
5967   }
5968 
5969   // try to simplify at the base level
5970   if (s->status == STATUS_SEARCHING &&
5971       s->decision_level == s->base_level &&
5972       s->stack.top > s->simplify_bottom &&
5973       s->stats.propagations >= s->simplify_props + s->simplify_threshold) {
5974     simplify_clause_database(s);
5975   }
5976 
5977   return true;
5978 }
5979 
5980 
5981 
5982 /*
5983  * Process with no conflict bounds
5984  */
smt_process(smt_core_t * s)5985 void smt_process(smt_core_t *s) {
5986   (void) smt_core_process(s, UINT64_MAX);
5987 }
5988 
5989 /*
5990  * Use a bound
5991  */
smt_bounded_process(smt_core_t * s,uint64_t max_conflicts)5992 bool smt_bounded_process(smt_core_t *s, uint64_t max_conflicts) {
5993   return smt_core_process(s, max_conflicts);
5994 }
5995 
5996 
5997 
5998 
5999 /*
6000  * End-of-search check: delayed theory solving:
6001  * - call the final_check function of the theory solver
6002  * - if that creates new variables or lemmas or report a conflict
6003  *   then smt_process is called
6004  * - otherwise the core status is updated to SAT or UNKNOWN and the search
6005  *   is done.
6006  */
smt_final_check(smt_core_t * s)6007 void smt_final_check(smt_core_t *s) {
6008   assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
6009 
6010   if (s->status == STATUS_SEARCHING) {
6011     switch (s->th_ctrl.final_check(s->th_solver)) {
6012     case FCHECK_CONTINUE:
6013       /*
6014        * deal with conflicts or lemmas if any.
6015        * leave status as it is so that the search can proceed
6016        */
6017       smt_process(s);
6018       break;
6019       /*
6020        * Otherwise: update status to stop the search
6021        */
6022     case FCHECK_SAT:
6023       s->status = STATUS_SAT;
6024       break;
6025     case FCHECK_UNKNOWN:
6026       s->status = STATUS_UNKNOWN;
6027       break;
6028     }
6029   }
6030 }
6031 
6032 
6033 
6034 /*
6035  * Search for a satisfiable assignment.
6036  * - stop on the first conflict and return false
6037  * - return true if all Boolean variables are assigned.
6038  */
smt_easy_sat(smt_core_t * s)6039 bool smt_easy_sat(smt_core_t *s) {
6040   literal_t l;
6041 
6042   assert(s->bool_only);
6043 
6044   for (;;) {
6045     assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
6046     smt_propagation(s);
6047     assert(empty_lemma_queue(&s->lemmas));
6048     assert(! s->cp_flag);
6049 
6050     if (s->inconsistent) {
6051       // clear the conflict
6052       backtrack_to_base_level(s);
6053       s->inconsistent = false;
6054       s->theory_conflict = false;
6055       return false;
6056     }
6057 
6058     l = select_unassigned_literal(s);
6059     if (l == null_literal) {
6060       s->status = STATUS_SAT;
6061       return true;
6062     }
6063     decide_literal(s, l);
6064   }
6065 }
6066 
6067 
6068 
6069 
6070 /***************
6071  *  RESTARTS   *
6072  **************/
6073 
6074 /*
6075  * Three variants of restart:
6076  * - full restart: backtrack to the base_level
6077  * - partial restart: lazier version: backtrack(s, k) for some
6078  *   level k >= base_level determined by variable activities:
6079  * - partial_restart_var: even lazier version: if partial restart
6080  *   would backtrack to level k then partial_restart_var backtracks
6081  *   to k' >= k.
6082  * - benchmarking shows that partial_restart_var seems to work best.
6083  */
6084 
6085 /*
6086  * Cleanup the heap to prepare for a partial restart:
6087  * - remove variables until the top var is unassigned
6088  *   or until the heap is empty
6089  */
cleanup_heap(smt_core_t * s)6090 static void cleanup_heap(smt_core_t *s) {
6091   var_heap_t *heap;
6092   bvar_t x;
6093 
6094   heap = &s->heap;
6095   while (! heap_is_empty(heap)) {
6096     x = heap->heap[1];
6097     if (bvar_is_unassigned(s, x)) {
6098       break;
6099     }
6100     assert(x >= 0 && heap->heap_last > 0);
6101     heap->heap_index[x] = -1;
6102     update_down(heap, 1);
6103   }
6104 }
6105 
6106 
6107 /*
6108  * Check whether all variables assigned at level k have
6109  * activity less than ax
6110  */
level_has_lower_activity(smt_core_t * s,double ax,uint32_t k)6111 static bool level_has_lower_activity(smt_core_t *s, double ax, uint32_t k) {
6112   prop_stack_t *stack;
6113   uint32_t i, n;
6114   bvar_t x;
6115 
6116   assert(s->base_level <= k && k <= s->decision_level);
6117 
6118   stack = &s->stack;
6119 
6120   // i := start of level k
6121   // n := end of level k
6122   i = stack->level_index[k];
6123   n = stack->top;
6124   if (k < s->decision_level) {
6125     n = stack->level_index[k+1];
6126   }
6127 
6128   while (i < n) {
6129     x = var_of(stack->lit[i]);
6130     assert(bvar_is_assigned(s, x) && s->level[x] == k);
6131     if (s->heap.activity[x] >= ax) {
6132       return false;
6133     }
6134     i ++;
6135   }
6136 
6137   return true;
6138 }
6139 
6140 
6141 /*
6142  * Do a full restart: backtrack to base_level
6143  */
full_restart(smt_core_t * s)6144 static void full_restart(smt_core_t *s) {
6145   assert(s->base_level < s->decision_level);
6146 
6147   backtrack(s, s->base_level);
6148   s->th_ctrl.backtrack(s->th_solver, s->base_level);
6149   // clear the checkpoints
6150   if (s->cp_flag) {
6151     purge_all_dynamic_atoms(s);
6152   }
6153 }
6154 
6155 /*
6156  * Partial restart: backtrack to level k
6157  */
partial_restart(smt_core_t * s,uint32_t k)6158 static void partial_restart(smt_core_t *s, uint32_t k) {
6159   assert(s->base_level <= k && k < s->decision_level);
6160 
6161   backtrack(s, k);
6162   s->th_ctrl.backtrack(s->th_solver, k);
6163 }
6164 
6165 
6166 /*
6167  * Full restart: cause s and the theory solver to backtrack to base_level
6168  * (do nothing if decision_level == base_level)
6169  */
smt_restart(smt_core_t * s)6170 void smt_restart(smt_core_t *s) {
6171 
6172   assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
6173 
6174 #if TRACE
6175   printf("\n---> DPLL RESTART\n");
6176 #endif
6177   s->stats.restarts ++;
6178   if (s->base_level < s->decision_level) {
6179     full_restart(s);
6180   }
6181 }
6182 
6183 
6184 /*
6185  * Partial restart: attempt to reuse the assignment stack
6186  * - find the unassigned variable of highest activity
6187  * - keep all current decisions that have an activity higher than that
6188  */
smt_partial_restart(smt_core_t * s)6189 void smt_partial_restart(smt_core_t *s) {
6190   double ax;
6191   bvar_t x;
6192   uint32_t i, k, n;
6193 
6194   assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
6195 
6196 #if TRACE
6197   printf("\n---> DPLL PARTIAL RESTART\n");
6198 #endif
6199 
6200   s->stats.restarts ++;
6201 
6202   if (s->base_level < s->decision_level) {
6203     cleanup_heap(s);
6204     if (heap_is_empty(&s->heap)) {
6205       full_restart(s);
6206     } else {
6207       // x = most active unassigned variable
6208       // ax = its activity
6209       x = s->heap.heap[1];
6210       assert(x >= 0 && bvar_is_unassigned(s, x));
6211       ax = s->heap.activity[x];
6212 
6213       /*
6214        * search for the first level i whose decision level has
6215        * activity less than ax, then backtrack to level i-1.
6216        */
6217       n = s->decision_level;
6218       for (i=s->base_level+1; i<=n; i++) {
6219 	k = s->stack.level_index[i];
6220 	x = var_of(s->stack.lit[k]);  // decision variable for level i
6221 	assert(bvar_is_assigned(s, x) &&
6222 	       s->level[x] == i &&
6223 	       s->antecedent[x] == mk_literal_antecedent(null_literal));
6224 
6225 	if (s->heap.activity[x] < ax) {
6226 	  partial_restart(s, i - 1);
6227 	  break;
6228 	}
6229       }
6230     }
6231   }
6232 }
6233 
6234 
6235 /*
6236  * Variant:
6237  * - find the unassigned variable of highest activity
6238  * - keep all current decision levels that have at least one variable
6239  *   with higher activity than that
6240  */
smt_partial_restart_var(smt_core_t * s)6241 void smt_partial_restart_var(smt_core_t *s) {
6242   double ax;
6243   bvar_t x;
6244   uint32_t i, n;
6245 
6246   assert(s->status == STATUS_SEARCHING || s->status == STATUS_INTERRUPTED);
6247 
6248 #if TRACE
6249   printf("\n---> DPLL PARTIAL RESTART (VARIANT)\n");
6250 #endif
6251 
6252   s->stats.restarts ++;
6253   if (s->base_level < s->decision_level) {
6254     cleanup_heap(s);
6255     if (heap_is_empty(&s->heap)) {
6256       full_restart(s);
6257     } else {
6258       x = s->heap.heap[1];
6259       assert(x >= 0 && bvar_is_unassigned(s, x));
6260       ax = s->heap.activity[x];
6261 
6262       n = s->decision_level;
6263       for (i=s->base_level+1; i<=n; i++) {
6264 	if (level_has_lower_activity(s, ax, i)) {
6265 	  partial_restart(s, i - 1);
6266 	  break;
6267 	}
6268       }
6269     }
6270   }
6271 }
6272 
6273 
6274 
6275 
6276 
6277 
6278 /*******************
6279  *  CHECK CLAUSES  *
6280  ******************/
6281 
6282 /*
6283  * Check whether all binary clauses are true in the current assignment
6284  */
all_binary_clauses_are_true(smt_core_t * s)6285 static bool all_binary_clauses_are_true(smt_core_t *s) {
6286   literal_t l0, l, *v;
6287 
6288   for (l0=0; l0<s->nlits; l0++) {
6289     if (literal_value(s, l0) != VAL_TRUE) {
6290       // check whether l is true for all binary clauses {l0, l}
6291       v = s->bin[l0];
6292       if (v != NULL) {
6293         // this loop terminates with l<0 (end-marker) if all clauses {l0, l} are true
6294         do {
6295 	  l = *v ++;
6296 	} while (l >= 0 && literal_value(s, l) == VAL_TRUE);
6297         if (l >= 0) return false;
6298       }
6299     }
6300   }
6301 
6302   return true;
6303 }
6304 
6305 
6306 /*
6307  * Check whether clause cl is true
6308  */
clause_is_true(smt_core_t * s,clause_t * cl)6309 static bool clause_is_true(smt_core_t *s, clause_t *cl) {
6310   uint32_t i;
6311   literal_t l;
6312 
6313   i = 0;
6314   do {
6315     l = cl->cl[i];
6316     i ++;
6317     if (literal_value(s, l) == VAL_TRUE) return true;
6318   } while (l >= 0);
6319 
6320   return false;
6321 }
6322 
6323 
6324 /*
6325  * Check whether all problem clauses are true
6326  */
all_problem_clauses_are_true(smt_core_t * s)6327 static bool all_problem_clauses_are_true(smt_core_t *s) {
6328   uint32_t i, n;
6329   clause_t **v;
6330 
6331   v = s->problem_clauses;
6332   n = get_cv_size(v);
6333   for (i=0; i<n; i++) {
6334     if (! clause_is_true(s, v[i])) return false;
6335   }
6336 
6337   return true;
6338 }
6339 
6340 
6341 /*
6342  * Check whether all problem clauses are true in the current assignment
6343  */
all_clauses_true(smt_core_t * s)6344 bool all_clauses_true(smt_core_t *s) {
6345   return all_binary_clauses_are_true(s) && all_problem_clauses_are_true(s);
6346 }
6347 
6348 
6349 
6350 
6351 /*******************************************
6352  *   MODEL GENERATION/LITERAL ASSIGNMENTS  *
6353  ******************************************/
6354 
6355 /*
6356  * Collect all true literals in vector v
6357  */
collect_true_literals(smt_core_t * s,ivector_t * v)6358 void collect_true_literals(smt_core_t *s, ivector_t *v) {
6359   uint32_t i, n;
6360   literal_t *lit;
6361 
6362   ivector_reset(v);
6363 
6364   lit = s->stack.lit;
6365   n = s->stack.top;
6366   for (i=0; i<n; i++) {
6367     ivector_push(v, lit[i]);
6368   }
6369 }
6370 
6371 
6372 /*
6373  * Collect all the decision literals: store them in v
6374  */
collect_decision_literals(smt_core_t * s,ivector_t * v)6375 void collect_decision_literals(smt_core_t *s, ivector_t *v) {
6376   uint32_t i, k, n;
6377   literal_t *lit;
6378 
6379   ivector_reset(v);
6380 
6381   lit = s->stack.lit;
6382   n = s->decision_level;
6383   for (k=s->base_level+1; k<=n; k++) {
6384     i = s->stack.level_index[k];
6385     ivector_push(v, lit[i]);
6386   }
6387 }
6388 
6389 
6390 /******************
6391  * IMPORT A MODEL *
6392  *****************/
6393 
6394 /*
6395  * Sets the value of variable x
6396  */
set_bvar_value(smt_core_t * s,bvar_t x,bval_t val)6397 void set_bvar_value(smt_core_t *s, bvar_t x, bval_t val) {
6398   assert(0 <= x && x < s->nvars);
6399   s->value[x] = val;
6400 }
6401 
6402 
6403 /**************************************
6404  * CHECK WHETHER THE CONTEXT IS EMPTY *
6405  *************************************/
6406 
6407 /*
6408  * Check whether the core is trivially SAT
6409  * - i.e., check whether there are no problem clauses
6410  */
smt_trivially_sat(smt_core_t * s)6411 bool smt_trivially_sat(smt_core_t *s) {
6412   return num_prob_clauses(s) + num_binary_clauses(s) + num_unit_clauses(s) == 0;
6413 }
6414 
6415 
6416 
6417 
6418 /****************************
6419  * UNCONSTRAINED VARIABLES  *
6420  ***************************/
6421 
6422 /*
6423  * Initialized fv structure:
6424  * - n = number of variables
6425  */
init_free_bool_vars(free_bool_vars_t * fv,uint32_t n)6426 void init_free_bool_vars(free_bool_vars_t *fv, uint32_t n) {
6427   fv->free = safe_malloc(n *  sizeof(uint8_t));
6428   fv->nvars = n;
6429 }
6430 
6431 /*
6432  * Delete fv
6433  */
delete_free_bool_vars(free_bool_vars_t * fv)6434 void delete_free_bool_vars(free_bool_vars_t *fv) {
6435   safe_free(fv->free);
6436   fv->free = NULL;
6437 }
6438 
6439 /*
6440  * Mark var_of(l) as not free in fv
6441  */
mark_lit_not_free(free_bool_vars_t * fv,literal_t l)6442 static inline void mark_lit_not_free(free_bool_vars_t *fv, literal_t l) {
6443   bvar_t x;
6444 
6445   x = var_of(l);
6446   assert(0 <= x && x < fv->nvars);
6447   fv->free[x] = false;
6448 }
6449 
6450 /*
6451  * Collect all the vars occurring in a unit clause
6452  */
collect_vars_in_unit_clauses(free_bool_vars_t * fv,const smt_core_t * s)6453 static void collect_vars_in_unit_clauses(free_bool_vars_t *fv, const smt_core_t *s) {
6454   uint32_t i, n;
6455   literal_t l;
6456 
6457   n = s->stack.top;
6458   if (s->decision_level >= 1) {
6459     n = s->stack.level_index[1];
6460   }
6461   for (i=0; i<n; i++) {
6462     l = s->stack.lit[i];
6463     assert(literal_is_assigned(s, l));
6464     mark_lit_not_free(fv, l);
6465   }
6466 }
6467 
6468 /*
6469  * Collect all vars in the binary clauses
6470  * - mark then as constrained
6471  */
collect_vars_in_binary_clauses(free_bool_vars_t * fv,const smt_core_t * s)6472 static void collect_vars_in_binary_clauses(free_bool_vars_t *fv, const smt_core_t *s) {
6473   literal_t l0, l, *v;
6474 
6475   for (l0=0; l0 < s->nlits; l0++) {
6476     v = s->bin[l0];
6477     if (v != NULL) {
6478       for (;;) {
6479 	l = *v ++;
6480 	if (l < 0) break;
6481 	mark_lit_not_free(fv, l);
6482       }
6483     }
6484   }
6485 }
6486 
6487 /*
6488  * Collect all vars in clause cl
6489  */
collect_vars_in_clause(free_bool_vars_t * fv,const clause_t * cl)6490 static void collect_vars_in_clause(free_bool_vars_t *fv, const clause_t *cl) {
6491   uint32_t i;
6492   literal_t l;
6493 
6494   i = 0;
6495   for (;;) {
6496     l = cl->cl[i];
6497     if (l < 0) break;
6498     mark_lit_not_free(fv, l);
6499     i ++;
6500   }
6501 }
6502 
6503 /*
6504  * Collect the variables that occur in a problem clause
6505  */
collect_vars_in_problem_clauses(free_bool_vars_t * fv,const smt_core_t * s)6506 static void collect_vars_in_problem_clauses(free_bool_vars_t *fv, const smt_core_t *s) {
6507   uint32_t i, n;
6508   clause_t **v;
6509 
6510   v = s->problem_clauses;
6511   n = get_cv_size(v);
6512   for (i=0; i<n; i++) {
6513     collect_vars_in_clause(fv, v[i]);
6514   }
6515 }
6516 
6517 /*
6518  * Collect all the free variables in a solver s
6519  * - store them in fv
6520  * - fv must be initialized and large enough to store
6521  *   all the variables of s
6522  */
collect_free_bool_vars(free_bool_vars_t * fv,const smt_core_t * s)6523 void collect_free_bool_vars(free_bool_vars_t *fv, const smt_core_t *s) {
6524   uint32_t i, n;
6525 
6526   assert(s->nvars <= fv->nvars);
6527 
6528   n = fv->nvars;
6529   for (i=0; i<n; i++) {
6530     fv->free[i] = true;
6531   }
6532 
6533   mark_lit_not_free(fv, true_literal);
6534   collect_vars_in_unit_clauses(fv, s);
6535   collect_vars_in_binary_clauses(fv, s);
6536   collect_vars_in_problem_clauses(fv, s);
6537 }
6538 
6539 
6540 
6541 
6542 
6543 /*************************
6544  *  DEBUGGING FUNCTIONS  *
6545  ************************/
6546 
6547 #if DEBUG
6548 
6549 /*
6550  * Check that all unassigned variables are in the heap
6551  */
check_heap_content(smt_core_t * s)6552 static void check_heap_content(smt_core_t *s) {
6553   uint32_t x;
6554 
6555   if (s->heap.size < s->nvars) {
6556     printf("ERROR: incorrect heap: heap_size is smaller than the number of variables\n");
6557     fflush(stdout);
6558     return;
6559   }
6560 
6561   for (x=0; x<s->nvars; x++) {
6562     if (bval_is_undef(s->value[x]) && s->heap.heap_index[x] < 0) {
6563       printf("ERROR: incorrect heap: unassigned variable %"PRIu32" is not in the heap\n", x);
6564       fflush(stdout);
6565     }
6566   }
6567 }
6568 
6569 
6570 /*
6571  * Check that the heap is correct
6572  */
check_heap(smt_core_t * s)6573 static void check_heap(smt_core_t *s) {
6574   double *act;
6575   bvar_t *h, x;
6576   int32_t *index;
6577   uint32_t j, k, last;
6578 
6579   h = s->heap.heap;
6580   index = s->heap.heap_index;
6581   act = s->heap.activity;
6582   last = s->heap.heap_last;
6583 
6584   for (j=1; j<=last; j++) {
6585     x = h[j];
6586     if (index[x] != j) {
6587       printf("ERROR: incorrect heap: inconsistent index for variable %"PRId32"\n", x);
6588       printf("       heap_index is %"PRId32", should be %"PRIu32"\n", index[x], j);
6589       fflush(stdout);
6590     }
6591 
6592     k = j>>1;
6593     if (k < j && act[h[k]] < act[x]) {
6594     //    if (k < j && heap_precedes(act, x, h[k])) {
6595       printf("ERROR: incorrect heap order: child %"PRIu32" has higher activity than its parent %"PRIu32"\n", j, k);
6596       fflush(stdout);
6597     }
6598   }
6599 }
6600 
6601 
6602 
6603 /*
6604  * Check propagation results
6605  */
check_propagation_bin(smt_core_t * s,literal_t l0)6606 static void check_propagation_bin(smt_core_t *s, literal_t l0) {
6607   literal_t l1, *v;
6608 
6609   v = s->bin[l0];
6610   if (v == NULL || literal_value(s, l0) != VAL_FALSE) return;
6611 
6612   l1 = *v ++;
6613   while (l1 >= 0) {
6614     if (literal_is_unassigned(s, l1)) {
6615       printf("ERROR: missed propagation. Binary clause {%"PRId32", %"PRId32"}\n", l0, l1);
6616     } else if (literal_value(s, l1) == VAL_FALSE) {
6617       printf("ERROR: missed conflict. Binary clause {%"PRId32", %"PRId32"}\n", l0, l1);
6618     }
6619     l1 = *v ++;
6620   }
6621 }
6622 
indicator(bval_t v,bval_t c)6623 static inline int32_t indicator(bval_t v, bval_t c) {
6624   return (v == c) ? 1 : 0;
6625 }
6626 
check_watch_list(smt_core_t * s,literal_t l,clause_t * cl)6627 static void check_watch_list(smt_core_t *s, literal_t l, clause_t *cl) {
6628   link_t lnk;
6629 
6630   for (lnk = s->watch[l]; lnk != NULL_LINK; lnk = next_of(lnk)) {
6631     if (clause_of(lnk) == cl) {
6632       return;
6633     }
6634   }
6635 
6636   printf("ERROR: missing watch, literal = %"PRId32", clause = %p\n", l, clause_of(lnk));
6637 }
6638 
6639 
check_propagation_clause(smt_core_t * s,clause_t * cl)6640 static void check_propagation_clause(smt_core_t *s, clause_t *cl) {
6641   literal_t l0, l1, l;
6642   literal_t *d;
6643   int32_t nf, nt, nu;
6644   uint32_t i;
6645   bval_t v;
6646 
6647   nf = 0;
6648   nt = 0;
6649   nu = 0;
6650 
6651   l0 = get_first_watch(cl);
6652   v = literal_value(s, l0);
6653   nf += indicator(v, VAL_FALSE);
6654   nt += indicator(v, VAL_TRUE);
6655   nu += indicator(v, VAL_UNDEF_FALSE) + indicator(v, VAL_UNDEF_TRUE);
6656 
6657   l1 = get_second_watch(cl);
6658   v = literal_value(s, l1);
6659   nf += indicator(v, VAL_FALSE);
6660   nt += indicator(v, VAL_TRUE);
6661   nu += indicator(v, VAL_UNDEF_FALSE) + indicator(v, VAL_UNDEF_TRUE);
6662 
6663   d = cl->cl;
6664   i = 2;
6665   l = d[i];
6666   while (l >= 0) {
6667     v = literal_value(s, l);
6668     nf += indicator(v, VAL_FALSE);
6669     nt += indicator(v, VAL_TRUE);
6670     nu += indicator(v, VAL_UNDEF_FALSE) + indicator(v, VAL_UNDEF_TRUE);
6671 
6672     i ++;
6673     l = d[i];
6674   }
6675 
6676   if (nt == 0 && nu == 0) {
6677     printf("ERROR: missed conflict. Clause {%"PRId32", %"PRId32"", l0, l1);
6678     i = 2;
6679     l = d[i];
6680     while (l >= 0) {
6681       printf(", %"PRId32"", l);
6682       i ++;
6683       l = d[i];
6684     }
6685     printf("} (addr = %p)\n", cl);
6686   }
6687 
6688   if (nt == 0 && nu == 1) {
6689     printf("ERROR: missed propagation. Clause {%"PRId32", %"PRId32"", l0, l1);
6690     i = 2;
6691     l = d[i];
6692     while (l >= 0) {
6693       printf(", %"PRId32"", l);
6694       i ++;
6695       l = d[i];
6696     }
6697     printf("} (addr = %p)\n", cl);
6698   }
6699 
6700   check_watch_list(s, l0, cl);
6701   check_watch_list(s, l1, cl);
6702 }
6703 
check_propagation(smt_core_t * s)6704 static void check_propagation(smt_core_t *s) {
6705   literal_t l0;
6706   uint32_t i, n;
6707   clause_t **v;
6708 
6709   for (l0=0; l0<s->nlits; l0++) {
6710     check_propagation_bin(s, l0);
6711   }
6712 
6713   v = s->problem_clauses;
6714   n = get_cv_size(v);
6715   for (i=0; i<n; i++) {
6716     if (! is_clause_to_be_removed(v[i])) {
6717       check_propagation_clause(s, v[i]);
6718     }
6719   }
6720 
6721   v = s->learned_clauses;
6722   n = get_cv_size(v);
6723   for (i=0; i<n; i++) check_propagation_clause(s, v[i]);
6724 }
6725 
6726 
6727 
6728 /*
6729  * Check that marks/levels and assignments are consistent
6730  */
check_marks(smt_core_t * s)6731 static void check_marks(smt_core_t *s) {
6732   uint32_t i, n;
6733   bvar_t x;
6734   literal_t l;
6735 
6736   for (x=0; x<s->nvars; x++) {
6737     if (is_var_marked(s, x) && s->level[x] > s->base_level) {
6738       printf("Warning: var %"PRId32" marked but level[%"PRId32"] = %"PRIu32"\n", x, x, s->level[x]);
6739       fflush(stdout);
6740     }
6741   }
6742 
6743   n = s->nb_unit_clauses;
6744   for (i=0; i<n; i++) {
6745     l = s->stack.lit[i];
6746     if (is_lit_unmarked(s, l)) {
6747       printf("Warning: literal %"PRId32" assigned at level %"PRIu32" but not marked\n",
6748              l, s->level[var_of(l)]);
6749       fflush(stdout);
6750     }
6751   }
6752 }
6753 
6754 
6755 /*
6756  * Auxiliary function: print array of literal as a clause (array a)
6757  * - a must be terminated by null_literal
6758  */
print_literal_array(literal_t * a)6759 static void print_literal_array(literal_t *a) {
6760   uint32_t i;
6761   literal_t l;
6762 
6763   printf("{");
6764   i = 0;
6765   l = a[i];
6766   while (l >= 0) {
6767     printf(" ");
6768     print_literal(stdout, l);
6769     i ++;
6770     l = a[i];
6771   }
6772   printf(" }");
6773 }
6774 
6775 /*
6776  * Check that all literals in a are false (theory conflict)
6777  * - a must be terminated by null_literal
6778  */
check_theory_conflict(smt_core_t * s,literal_t * a)6779 static void check_theory_conflict(smt_core_t *s, literal_t *a) {
6780   uint32_t i;
6781   literal_t l;
6782 
6783   i = 0;
6784   l = a[i];
6785   while (l >= 0) {
6786     if (literal_value(s, l) != VAL_FALSE) {
6787       printf("Warning: invalid theory conflict. Literal %"PRId32" is not false\n", l);
6788       printf("Conflict: ");
6789       print_literal_array(a);
6790       printf("\n");
6791       fflush(stdout);
6792       return;
6793     }
6794     i ++;
6795     l = a[i];
6796   }
6797 }
6798 
6799 /*
6800  * Auxiliary function: if flag is true, print warning message when v
6801  * is an invalid explanation.
6802  */
print_theory_explanation_warning(ivector_t * v,literal_t l0,bool * flag)6803 static void print_theory_explanation_warning(ivector_t *v, literal_t l0, bool *flag) {
6804   uint32_t i;
6805   literal_t l;
6806 
6807   if (*flag) {
6808     printf("\nWarning: invalid theory explanation:");
6809     for (i=0; i<v->size; i++) {
6810       l = v->data[i];
6811       printf(" ");
6812       print_literal(stdout, l);
6813     }
6814     printf(" for  ");
6815     print_literal(stdout, l0);
6816     printf("\n");
6817     *flag = false;
6818   }
6819 }
6820 
6821 /*
6822  * Return true if l0 is before l in the assignment queue
6823  * both must have the same decision level k
6824  */
check_precedence(smt_core_t * s,literal_t l0,literal_t l)6825 static bool check_precedence(smt_core_t *s, literal_t l0, literal_t l) {
6826   uint32_t k, i;
6827   literal_t l1;
6828 
6829   if (l0 == l) return false;
6830 
6831   k = d_level(s, l0);
6832   assert(k == d_level(s, l));
6833   i = s->stack.level_index[k];
6834   for (;;) {
6835     assert(i < s->stack.top);
6836     l1 = s->stack.lit[i];
6837     assert(d_level(s, l1) == k);
6838     if (l1 == l0) return true;
6839     if (l1 == l) return false;
6840     i ++;
6841   }
6842 }
6843 
6844 /*
6845  * Check causality on theory explanations:
6846  * - l: literal assigned by theory propagation
6847  * - s->explanation: literals that imply l
6848  * (s->explanation is interpreted as a conjunction of literals)
6849  * all literals in explanation must be before l in the assignment stack
6850  */
check_theory_explanation(smt_core_t * s,literal_t l)6851 static void check_theory_explanation(smt_core_t *s, literal_t l) {
6852   uint32_t i, n, k;
6853   literal_t l0;
6854   bool print;
6855 
6856   k = d_level(s, l);
6857   n = s->explanation.size;
6858   print = true;
6859   for (i=0; i<n; i++) {
6860     l0 = s->explanation.data[i];
6861 
6862     if (literal_value(s, l0) != VAL_TRUE) {
6863       print_theory_explanation_warning(&s->explanation, l, &print);
6864       printf("Literal %"PRId32" should be true\n", l0);
6865 
6866     } else if (d_level(s, l0) > k) {
6867       print_theory_explanation_warning(&s->explanation, l, &print);
6868       printf("Literal %"PRId32" has higher decision level than %"PRId32"\n", l0, l);
6869 
6870     } else if (d_level(s, l0) == k && ! check_precedence(s, l0, l)) {
6871       print_theory_explanation_warning(&s->explanation, l, &print);
6872       printf("Literal %"PRId32" is after %"PRId32" in the assignment queue\n", l0, l);
6873 
6874     }
6875   }
6876   if (print) {
6877     fflush(stdout);
6878   }
6879 }
6880 
6881 
6882 /*
6883  * Check whether a[0] and a[1] are valid watched literals for
6884  * the clause a[0] ... a[n-1]. (n >= 2)
6885  */
print_lit_val_level(literal_t l,bval_t v,uint32_t k)6886 static void print_lit_val_level(literal_t l, bval_t v, uint32_t k) {
6887   printf("---> ");
6888   print_literal(stdout, l);
6889   printf(": value = ");
6890   print_bval(stdout, v);
6891   if (bval_is_def(v)) {
6892     printf(" at level %"PRIu32, k);
6893   }
6894   printf("\n");
6895 }
6896 
6897 /*
6898  * Check whether (v1, k1) must be preferred to (v2, k2)
6899  * - rule1:  (undef, _) < (false, _)
6900  * - rule2:  k2 < k1 implies (false, k1) < (false, k2)
6901  */
check_prefer(bval_t v1,uint32_t k1,bval_t v2,uint32_t k2)6902 static bool check_prefer(bval_t v1, uint32_t k1, bval_t v2, uint32_t k2) {
6903   return (bval_is_undef(v1) && v2 == VAL_FALSE)
6904     || (v1 == VAL_FALSE && v2 == VAL_FALSE && k1 > k2);
6905 }
6906 
check_watched_literals(smt_core_t * s,uint32_t n,literal_t * a)6907 static void check_watched_literals(smt_core_t *s, uint32_t n, literal_t *a) {
6908   literal_t l;
6909   bval_t v0, v1, v;
6910   uint32_t k0, k1, k, i;
6911 
6912   l = a[0];
6913   v0 = literal_value(s, l);
6914   k0 = s->level[var_of(l)];
6915 
6916   l = a[1];
6917   v1 = literal_value(s, l);
6918   k1 = s->level[var_of(l)];
6919 
6920   for (i=2; i<n; i++) {
6921     l = a[i];
6922     v = literal_value(s, l);
6923     k = s->level[var_of(l)];
6924     if (check_prefer(v, k, v0, k0) || check_prefer(v, k, v1, k1)) {
6925       goto error;
6926     }
6927   }
6928   return;
6929 
6930  error:
6931   printf("Error: incorrect watched literals in new clause\n");
6932   printf("Clause: {");
6933   for (i=0; i<n; i++) {
6934     printf(" ");
6935     print_literal(stdout, a[i]);
6936   }
6937   printf(" }\n");
6938   print_lit_val_level(a[0], v0, k0);
6939   print_lit_val_level(a[1], v1, k1);
6940   print_lit_val_level(l, v, k);
6941 }
6942 
check_lemma(smt_core_t * s,uint32_t n,literal_t * a)6943 static void check_lemma(smt_core_t *s, uint32_t n, literal_t *a) {
6944   uint32_t i;
6945   literal_t l;
6946 
6947   for (i=0; i<n; i++) {
6948     l = a[i];
6949     if (l < 0 || l >= s->nlits) {
6950       printf("Error: invalid literal in lemma (l = %"PRId32")\n", l);
6951       fflush(stdout);
6952     }
6953   }
6954 }
6955 
6956 #endif
6957 
6958