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  * STAND-ALONE SAT SOLVER
21  */
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <inttypes.h>
26 #include <float.h>
27 
28 #include "solvers/cdcl/new_sat_solver2.h"
29 #include "solvers/cdcl/new_gate_hash_map.h"
30 #include "solvers/cdcl/wide_truth_tables.h"
31 #include "utils/cputime.h"
32 #include "utils/memalloc.h"
33 #include "utils/int_array_sort.h"
34 #include "utils/uint_array_sort.h"
35 #include "utils/uint_array_sort2.h"
36 
37 
38 /*
39  * Enable diving
40  */
41 #define USE_DIVING 0
42 
43 /*
44  * Set these flags to 1 for debugging, trace, data collection
45  */
46 #define DEBUG 0
47 #define TRACE 0
48 #define DATA  0
49 
50 #if DEBUG
51 
52 /*
53  * The following functions check internal consistency. They are defined
54  * at the end of this file. They print an error on stderr if the checks fail.
55  */
56 static void check_clause_pool_counters(const clause_pool_t *pool);
57 static void check_clause_pool_learned_index(const clause_pool_t *pool);
58 static void check_candidate_clauses_to_delete(const sat_solver_t *solver, const cidx_t *a, uint32_t n);
59 static void check_watch_vectors(const sat_solver_t *solver);
60 static void check_propagation(const sat_solver_t *solver);
61 static void check_marks(const sat_solver_t *solver);
62 static void check_all_unmarked(const sat_solver_t *solver);
63 static void check_elim_heap(const sat_solver_t *solver);
64 
65 #else
66 
67 /*
68  * Placeholders: do nothing
69  */
check_clause_pool_counters(const clause_pool_t * pool)70 static inline void check_clause_pool_counters(const clause_pool_t *pool) { }
check_clause_pool_learned_index(const clause_pool_t * pool)71 static inline void check_clause_pool_learned_index(const clause_pool_t *pool) { }
check_heap(const nvar_heap_t * heap)72 static inline void check_heap(const nvar_heap_t *heap) { }
check_candidate_clauses_to_delete(const sat_solver_t * solver,const cidx_t * a,uint32_t n)73 static inline void check_candidate_clauses_to_delete(const sat_solver_t *solver, const cidx_t *a, uint32_t n) { }
check_watch_vectors(const sat_solver_t * solver)74 static inline void check_watch_vectors(const sat_solver_t *solver) { }
check_propagation(const sat_solver_t * solver)75 static inline void check_propagation(const sat_solver_t *solver) { }
check_marks(const sat_solver_t * solver)76 static inline void check_marks(const sat_solver_t *solver) { }
check_all_unmarked(const sat_solver_t * solver)77 static inline void check_all_unmarked(const sat_solver_t *solver) {}
check_elim_heap(const sat_solver_t * solver)78 static inline void check_elim_heap(const sat_solver_t *solver) {}
79 
80 #endif
81 
82 
83 /*
84  * Function to show details and data
85  */
86 static void show_assigned_vars(FILE *f, const sat_solver_t *solver);
87 static void show_var_def(const sat_solver_t *solver, bvar_t x);
88 static void show_tt(const ttbl_t *tt);
89 static void show_subst(const sat_solver_t *solver);
90 extern void show_all_var_defs(const sat_solver_t *solver);
91 
92 // utility: for printing a literal l: pol(l) is ~ if l is negative
pol(literal_t l)93 static int pol(literal_t l) {
94   return is_pos(l) ? ' ' : '~';
95 }
96 
97 
98 #if DATA
99 
100 /*
101  * DATA COLLECTION/STATISTICS
102  */
103 
104 /*
105  * Open the internal data file
106  * - if this fails, solver->data stays NULL and no data is collected
107  */
nsat_open_datafile(sat_solver_t * solver,const char * name)108 void nsat_open_datafile(sat_solver_t *solver, const char *name) {
109   solver->data = fopen(name, "w");
110 }
111 
close_datafile(sat_solver_t * solver)112 static void close_datafile(sat_solver_t *solver) {
113   if (solver->data != NULL) {
114     fclose(solver->data);
115   }
116 }
117 
reset_datafile(sat_solver_t * solver)118 static void reset_datafile(sat_solver_t *solver) {
119   close_datafile(solver);
120   solver->data = NULL;
121 }
122 
123 
124 /*
125  * Write data after a conflict
126  * - lbd = lbd of the learned clause
127  *
128  * When this is called:
129  * - solver->conflict_tag = either CTAG_CLAUSE or CTAG_BINARY
130  * - solver->conflict_index = index of the conflict clause (if CTAG_CLAUSE)
131  * - solver->buffer = conflict clause (if CTAG_BINARY)
132  * - solver->buffer contains the learned clause
133  * - solver->decision_level = the conflict level
134  * - solver->backtrack_level = where to backtrack
135  * - solver->stats.conflicts = number of conflicts (including this one)
136  * - solver->slow_ema, fast_ema have been updated
137  *
138  * Data exported:
139  * - stats.conflicts
140  * - stats.decisions
141  * - stats.propagations
142  * - slow_ema
143  * - fast_ema
144  * - lbd
145  * - conflict level
146  * - backtrack level
147  * - size of the learned clause
148  * - then the learned clause (as an array of literals)
149  *
150  * The data is stored as raw binary data (little endian for x86)
151  */
152 typedef struct conflict_data {
153   uint64_t conflicts;
154   uint64_t decisions;
155   uint64_t propagations;
156   uint64_t slow_ema;
157   uint64_t fast_ema;
158   uint32_t lbd;
159   uint32_t conflict_level;
160   uint32_t backtrack_level;
161   uint32_t learned_clause_size;
162 } conflict_data_t;
163 
export_conflict_data(sat_solver_t * solver,uint32_t lbd)164 static void export_conflict_data(sat_solver_t *solver, uint32_t lbd) {
165   conflict_data_t buffer;
166   size_t w, n;
167 
168   if (solver->data != NULL) {
169     buffer.conflicts = solver->stats.conflicts;
170     buffer.decisions = solver->stats.decisions;
171     buffer.propagations = solver->stats.propagations;
172     buffer.slow_ema = solver->slow_ema;
173     buffer.fast_ema = solver->fast_ema;
174     buffer.lbd = lbd;
175     buffer.conflict_level = solver->decision_level;
176     buffer.backtrack_level = solver->backtrack_level;
177     buffer.learned_clause_size = solver->buffer.size;;
178     w = fwrite(&buffer, sizeof(buffer), 1, solver->data);
179     if (w < 1) goto write_error;
180     n = solver->buffer.size;
181     w = fwrite(solver->buffer.data, sizeof(literal_t), n, solver->data);
182     if (w < n) goto write_error;
183   }
184 
185   return;
186 
187  write_error:
188   // close and reset solver->data to zero
189   perror("export_conflict_data");
190   fprintf(stderr, "export_conflict_data: write failed at conflict %"PRIu64"\n", solver->stats.conflicts);
191   fclose(solver->data);
192   solver->data = NULL;
193 }
194 
195 /*
196  * Last conflict: at level 0, the learned clause is empty.
197  */
export_last_conflict(sat_solver_t * solver)198 static void export_last_conflict(sat_solver_t *solver) {
199   conflict_data_t buffer;
200   size_t w;
201 
202   if (solver->data != NULL) {
203     buffer.conflicts = solver->stats.conflicts;
204     buffer.decisions = solver->stats.decisions;
205     buffer.propagations = solver->stats.propagations;
206     buffer.slow_ema = solver->slow_ema;
207     buffer.fast_ema = solver->fast_ema;
208     buffer.lbd = 0;
209     buffer.conflict_level = 0;
210     buffer.backtrack_level = 0;
211     buffer.learned_clause_size = 0;;
212     w = fwrite(&buffer, sizeof(buffer), 1, solver->data);
213     if (w < 1) goto write_error;
214   }
215   return;
216 
217  write_error:
218   // close and reset solver->data to zero
219   perror("export_last_conflict");
220   fprintf(stderr, "export_last_conflict: write failed at conflict %"PRIu64"\n", solver->stats.conflicts);
221   fclose(solver->data);
222   solver->data = NULL;
223 }
224 
225 #else
226 
227 /*
228  * Placeholders: they do nothing
229  */
nsat_open_datafile(sat_solver_t * solver,const char * name)230 void nsat_open_datafile(sat_solver_t *solver, const char *name) { }
231 
close_datafile(sat_solver_t * solver)232 static inline void close_datafile(sat_solver_t *solver) { }
reset_datafile(sat_solver_t * solver)233 static inline void reset_datafile(sat_solver_t *solver) { }
export_conflict_data(sat_solver_t * solver,uint32_t lbd)234 static inline void export_conflict_data(sat_solver_t *solver, uint32_t lbd) { }
export_last_conflict(sat_solver_t * solver)235 static inline void export_last_conflict(sat_solver_t *solver) { }
236 
237 #endif
238 
239 
240 
241 
242 /************************
243  *  DEFAULT PARAMETERS  *
244  ***********************/
245 
246 /*
247  * Clause activities
248  */
249 #define CLAUSE_DECAY_FACTOR            0.999F
250 #define CLAUSE_ACTIVITY_THRESHOLD      (1e20f)
251 #define INV_CLAUSE_ACTIVITY_THRESHOLD  (1e-20f)
252 #define INIT_CLAUSE_ACTIVITY_INCREMENT 1.0
253 
254 /*
255  * Default random_factor = 2% of decisions are random (more or less)
256  * - the heuristic generates a random 24 bit integer
257  * - if that number is <= random_factor * 2^24, then a random variable
258  *   is chosen
259  * - so we store random_factor * 2^24 = random_factor * 0x1000000 in
260  *   the randomness field of a sat solver.
261  */
262 #define VAR_RANDOM_FACTOR 0.02F
263 
264 // mask to extract 24 bits out of an unsigned 32bit integer
265 #define VAR_RANDOM_MASK  ((uint32_t)0xFFFFFF)
266 #define VAR_RANDOM_SCALE (VAR_RANDOM_MASK+1)
267 
268 /*
269  * Clause deletion parameters
270  * - we don't delete clauses of lbd <= keep_lbd
271  * - we trigger the deletion when the number of learned clauses becomes
272  *   larger than solver->reduce_next.
273  * - the initial value of reduce_next is initially set to
274  *     min(MIN_REDUCE_NEXT, number of problem clauses/4)
275  * - after every reduction, the reduce_threhsold is updated to
276  *    reduce_next * REDUCE_FACTOR
277  * - each deletion round removes a fraction of the clauses equal
278  *   to REDUCE_FRACTION/32 (approximately).
279  */
280 #define KEEP_LBD 4
281 #define MIN_REDUCE_NEXT 1000
282 #define REDUCE_FACTOR 1.05
283 #define REDUCE_FRACTION 16
284 
285 #define REDUCE_INTERVAL 2000
286 #define REDUCE_DELTA    300
287 
288 
289 /*
290  * We use two modes:
291  * - search_mode is the default. In this mode, we're trying to
292  *   learn useful clauses (low LBD).
293  * - if we don't learn small clauses for a long time, we switch
294  *   to diving. In this mode, we hope the formula is satisfiable
295  *   and we try to go deep into the search tree.
296  * To determine when to switch to diving mode, we use a search_period
297  * and a search_counter.
298  * - every search_period conflicts, we check whether we're making
299  *   progress. If we don't make progress for search_counter successive
300  *   periods, we switch to diving.
301  */
302 #define SEARCH_PERIOD 10000
303 #define SEARCH_COUNTER 20
304 
305 /*
306  * Minimal Number of conflicts between two restarts
307  */
308 #define RESTART_INTERVAL 10
309 
310 /*
311  * Stacking of learned clauses
312  * - clauses of LBD higher than this threshold are not stored in the
313  *   data set but in the stack (of temporary clauses).
314  */
315 #define STACK_THRESHOLD 4
316 
317 /*
318  * Diving
319  * - diving budget = number of conflicts after which we stop diving
320  */
321 #define DIVING_BUDGET 10000
322 
323 /*
324  * Parameters to control preprocessing
325  *
326  * - subsumption checks can be expensive. To reduce the cost,
327  *   we don't check whether a clause C subsumes anything if that would
328  *   require visiting more than subsume_skip clauses.
329  *
330  * - for variable elimination, we only consider variables that have
331  *   few positive or few negative occurrences. If x has too many
332  *   positive and negative occurrence, it's not likely that we'll be
333  *   able to eliminate x anyway.
334  *
335  * - we also don't want to create large clauses when eliminating
336  *   variables, so we don't eliminate x if that would create a
337  *   clause of size > res_clause_limit
338  */
339 #define SUBSUME_SKIP 3000
340 #define VAR_ELIM_SKIP 10
341 #define RES_CLAUSE_LIMIT 20
342 
343 /*
344  * Parameters to control simplify
345  */
346 #define SIMPLIFY_INTERVAL 100
347 #define SIMPLIFY_BIN_DELTA 100
348 #define SIMPLIFY_SUBST_DELTA 40
349 
350 
351 
352 /**********
353  *  PRNG  *
354  *********/
355 
356 /*
357  * PARAMETERS FOR THE PSEUDO RANDOM NUMBER GENERATOR
358  *
359  * We  use the same linear congruence as in prng.h,
360  * but we use a local implementation so that different
361  * solvers can use different seeds.
362  */
363 
364 #define PRNG_MULTIPLIER 1664525
365 #define PRNG_CONSTANT   1013904223
366 #define PRNG_SEED       0xabcdef98
367 
368 
369 /*
370  * Return a 32bit unsigned int
371  */
random_uint32(sat_solver_t * s)372 static inline uint32_t random_uint32(sat_solver_t *s) {
373   uint32_t x;
374 
375   x = s->prng;
376   s->prng = x * ((uint32_t) PRNG_MULTIPLIER) + ((uint32_t) PRNG_CONSTANT);
377   return x;
378 }
379 
380 
381 /*
382  * Return a 32bit integer between 0 and n-1
383  */
random_uint(sat_solver_t * s,uint32_t n)384 static inline uint32_t random_uint(sat_solver_t *s, uint32_t n) {
385   return (random_uint32(s) >> 8) % n;
386 }
387 
388 
389 /*********************
390  *  INTEGER VECTOR   *
391  ********************/
392 
393 /*
394  * Capacity increase for vectors:
395  * - about 50% increase rounded up to a multiple of four
396  */
vector_cap_increase(uint32_t cap)397 static inline uint32_t vector_cap_increase(uint32_t cap) {
398   return ((cap >> 1) + 8) & ~3;
399 }
400 
401 /*
402  * Initialize
403  */
init_vector(vector_t * v)404 static void init_vector(vector_t *v) {
405   uint32_t n;
406 
407   n = DEF_VECTOR_SIZE;
408   assert(n <= MAX_VECTOR_SIZE);
409   v->data = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
410   v->capacity = n;
411   v->size = 0;
412 }
413 
414 /*
415  * Make it larger.
416  */
extend_vector(vector_t * v)417 static void extend_vector(vector_t *v) {
418   uint32_t n;
419 
420   n = v->capacity + vector_cap_increase(v->capacity);
421   assert(n > v->capacity);
422   if (n > MAX_VECTOR_SIZE) {
423     out_of_memory();
424   }
425   v->data = (uint32_t *) safe_realloc(v->data, n * sizeof(uint32_t));
426   v->capacity = n;
427 }
428 
429 /*
430  * Add integer x at the end of v
431  */
vector_push(vector_t * v,uint32_t x)432 static void vector_push(vector_t *v, uint32_t x) {
433   uint32_t i;
434 
435   i = v->size;
436   if (i == v->capacity) {
437     extend_vector(v);
438   }
439   assert(i < v->capacity);
440   v->data[i] = x;
441   v->size = i+1;
442 }
443 
444 /*
445  * Remove the last element and return it
446  * - v must not be empty
447  */
vector_pop(vector_t * v)448 static uint32_t vector_pop(vector_t *v) {
449   assert(v->size > 0);
450   v->size --;
451   return v->data[v->size];
452 }
453 
454 /*
455  * Reset: empty the buffer
456  */
reset_vector(vector_t * v)457 static inline void reset_vector(vector_t *v) {
458   v->size = 0;
459 }
460 
461 /*
462  * Reset and make room for one element (literal)
463  */
vector_reset_and_reserve(vector_t * v)464 static inline void vector_reset_and_reserve(vector_t *v) {
465   assert(v->capacity >= 1);
466   v->size = 1;
467 }
468 
469 /*
470  * Free memory
471  */
delete_vector(vector_t * v)472 static void delete_vector(vector_t *v) {
473   safe_free(v->data);
474   v->data = NULL;
475 }
476 
477 
478 
479 /*******************
480  *  INTEGER QUEUE  *
481  ******************/
482 
483 /*
484  * Capacity increase: same as for vector
485  */
queue_cap_increase(uint32_t cap)486 static inline uint32_t queue_cap_increase(uint32_t cap) {
487   return ((cap >> 1) + 8) & ~3;
488 }
489 
490 /*
491  * Initialize
492  */
init_queue(queue_t * q)493 static void init_queue(queue_t *q) {
494   uint32_t n;
495 
496   n = DEF_QUEUE_SIZE;
497   assert(n <= MAX_QUEUE_SIZE);
498   q->data = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
499   q->capacity = n;
500   q->head = 0;
501   q->tail = 0;
502 }
503 
504 /*
505  * Make the queue bigger
506  */
extend_queue(queue_t * q)507 static void extend_queue(queue_t *q) {
508   uint32_t n;
509 
510   n = q->capacity + queue_cap_increase(q->capacity);
511   assert(n > q->capacity);
512   if (n > MAX_QUEUE_SIZE) {
513     out_of_memory();
514   }
515   q->data = (uint32_t *) safe_realloc(q->data, n * sizeof(uint32_t));
516   q->capacity = n;
517 }
518 
519 /*
520  * Add x at the end of the queue
521  */
queue_push(queue_t * q,uint32_t x)522 static void queue_push(queue_t *q, uint32_t x) {
523   uint32_t i, n, j;
524 
525   i = q->tail;
526   q->data[i] = x;
527   i++;
528   if (i == q->capacity) {
529     i = 0;
530   }
531   q->tail = i;
532 
533   if (i == q->head) {
534     /*
535      * full queue in q->data[0 ... i-1] + q->data[head .. cap-1].
536      * make the array bigger
537      * if i>0, shift data[head ... cap - 1] to the end of the new array.
538      */
539     n = q->capacity;    // cap before increase
540     extend_queue(q);
541     if (i == 0) {
542       q->tail = n;
543     } else {
544       j = q->capacity;
545       do {
546         n --;
547         j --;
548         q->data[j] = q->data[n];
549       } while (n > i);
550       q->head = j;
551     }
552   }
553 }
554 
555 
556 /*
557  * Check emptiness
558  */
queue_is_empty(const queue_t * q)559 static inline bool queue_is_empty(const queue_t *q) {
560   return q->head == q->tail;
561 }
562 
563 
564 /*
565  * Remove the first element and return it.
566  * - the queue must not be empty
567  */
queue_pop(queue_t * q)568 static uint32_t queue_pop(queue_t *q) {
569   uint32_t x;
570   uint32_t i;
571 
572   assert(! queue_is_empty(q));
573 
574   i = q->head;
575   x = q->data[i];
576   i ++;
577   q->head = (i < q->capacity) ? i : 0;
578 
579   return x;
580 }
581 
582 
583 /*
584  * Empty the queue
585  */
reset_queue(queue_t * q)586 static inline void reset_queue(queue_t *q) {
587   q->head = 0;
588   q->tail = 0;
589 }
590 
591 
592 /*
593  * Delete
594  */
delete_queue(queue_t * q)595 static void delete_queue(queue_t *q) {
596   safe_free(q->data);
597   q->data = NULL;
598 }
599 
600 
601 
602 /*********************************
603  *  STACK FOR IMPLICATION GRAPH  *
604  ********************************/
605 
606 /*
607  * Initialize the stack. Nothing allocated yet.
608  */
init_gstack(gstack_t * gstack)609 static void init_gstack(gstack_t *gstack) {
610   gstack->data = NULL;
611   gstack->top = 0;
612   gstack->size = 0;
613 }
614 
615 /*
616  * Increment in size: 50% of the current size, rounded up to a multiple of 2.
617  */
gstack_size_increase(uint32_t n)618 static inline uint32_t gstack_size_increase(uint32_t n) {
619   return ((n>>1) + 3) & ~1;
620 }
621 
622 /*
623  * Make the stack larger
624  */
extend_gstack(gstack_t * gstack)625 static void extend_gstack(gstack_t *gstack) {
626   uint32_t n;
627 
628   n = gstack->size;
629   if (n == 0) {
630     // first allocation
631     n = DEF_GSTACK_SIZE;
632     assert(n <= MAX_GSTACK_SIZE);
633     gstack->data = (gstack_elem_t *) safe_malloc(n * sizeof(gstack_elem_t));
634     gstack->size = n;
635   } else {
636     // increase size by 50%, rounded to a multiple of 2
637     n += gstack_size_increase(n);
638     if (n > MAX_GSTACK_SIZE) {
639       out_of_memory();
640     }
641     gstack->data = (gstack_elem_t *) safe_realloc(gstack->data, n * sizeof(gstack_elem_t));
642     gstack->size = n;
643   }
644 }
645 
646 /*
647  * Delete the stack
648  */
delete_gstack(gstack_t * gstack)649 static void delete_gstack(gstack_t *gstack) {
650   safe_free(gstack->data);
651   gstack->data = NULL;
652 }
653 
654 /*
655  * Push pair (x, n) on the stack
656  */
gstack_push_vertex(gstack_t * gstack,uint32_t x,uint32_t n)657 static void gstack_push_vertex(gstack_t *gstack, uint32_t x, uint32_t n) {
658   uint32_t i;
659 
660   i = gstack->top;
661   if (i == gstack->size) {
662     extend_gstack(gstack);
663   }
664   assert(i < gstack->size);
665   gstack->data[i].vertex = x;
666   gstack->data[i].index = n;
667   gstack->top = i+1;
668 }
669 
670 /*
671  * Check emptiness
672  */
gstack_is_empty(gstack_t * gstack)673 static inline bool gstack_is_empty(gstack_t *gstack) {
674   return gstack->top == 0;
675 }
676 
677 /*
678  * Get top element
679  */
gstack_top(gstack_t * gstack)680 static inline gstack_elem_t *gstack_top(gstack_t *gstack) {
681   assert(gstack->top > 0);
682   return gstack->data + (gstack->top - 1);
683 }
684 
685 /*
686  * Remove the top element
687  */
gstack_pop(gstack_t * gstack)688 static inline void gstack_pop(gstack_t *gstack) {
689   assert(gstack->top > 0);
690   gstack->top --;
691 }
692 
693 /*
694  * Empty the stack
695  */
reset_gstack(gstack_t * gstack)696 static inline void reset_gstack(gstack_t *gstack) {
697   gstack->top = 0;
698 }
699 
700 
701 
702 
703 
704 
705 /******************
706  *  CLAUSE POOL   *
707  *****************/
708 
709 /*
710  * Capacity increase:
711  * cap += ((cap >> 1) + (cap >> 6) + (cap >> 7) + 2048) & ~3
712  *
713  * Since the initial capacity is 262144, we get an increasing
714  * sequence: 262144, 401408, 613568,  ..., 4265187980,
715  * which gets us close to 2^32.  The next increase after that
716  * causes an arithmetic overflow.
717  */
pool_cap_increase(uint32_t cap)718 static inline uint32_t pool_cap_increase(uint32_t cap) {
719   return ((cap >> 1) + (cap >> 6) + (cap >> 7) + 2048) & ~3;
720 }
721 
722 /*
723  * Maximal capacity after reset.
724  * On a call to reset, we try to save memory by reducing
725  * the pool capacity to this. This size is what we'd get
726  * after 14 rounds on pool_cal_increase (about 126 MB).
727  */
728 #define RESET_CLAUSE_POOL_CAPACITY 33155608
729 
is_multiple_of_four(uint32_t x)730 static bool is_multiple_of_four(uint32_t x) {
731   return (x & 3) == 0;
732 }
733 
734 
735 /*
736  * Some consistency checks
737  */
738 #ifndef NDEBUG
clause_pool_invariant(const clause_pool_t * pool)739 static bool clause_pool_invariant(const clause_pool_t *pool) {
740   return
741     pool->learned <= pool->size &&
742     pool->size <= pool->capacity &&
743     pool->available == pool->capacity - pool->size &&
744     is_multiple_of_four(pool->learned) &&
745     is_multiple_of_four(pool->size) &&
746     is_multiple_of_four(pool->capacity);
747 }
748 #endif
749 
750 /*
751  * Global operations
752  */
init_clause_pool(clause_pool_t * pool)753 static void init_clause_pool(clause_pool_t *pool) {
754   pool->data = (uint32_t *) safe_malloc(DEF_CLAUSE_POOL_CAPACITY * sizeof(uint32_t));
755   pool->learned = 0;
756   pool->size = 0;
757   pool->capacity = DEF_CLAUSE_POOL_CAPACITY;
758   pool->available = DEF_CLAUSE_POOL_CAPACITY;
759   pool->padding = 0;
760 
761   pool->num_prob_clauses = 0;
762   pool->num_prob_literals = 0;
763   pool->num_learned_clauses = 0;
764   pool->num_learned_literals = 0;
765 
766   assert(clause_pool_invariant(pool));
767 }
768 
delete_clause_pool(clause_pool_t * pool)769 static void delete_clause_pool(clause_pool_t *pool) {
770   assert(clause_pool_invariant(pool));
771   safe_free(pool->data);
772   pool->data = NULL;
773 }
774 
reset_clause_pool(clause_pool_t * pool)775 static void reset_clause_pool(clause_pool_t *pool) {
776   assert(clause_pool_invariant(pool));
777 
778   if (pool->capacity > RESET_CLAUSE_POOL_CAPACITY) {
779     safe_free(pool->data);
780     pool->data = (uint32_t *) safe_malloc(RESET_CLAUSE_POOL_CAPACITY * sizeof(uint32_t));
781     pool->capacity = RESET_CLAUSE_POOL_CAPACITY;
782   }
783 
784   pool->learned = 0;
785   pool->size = 0;
786   pool->available = pool->capacity;
787   pool->padding = 0;
788 
789   pool->num_prob_clauses = 0;
790   pool->num_prob_literals = 0;
791   pool->num_learned_clauses = 0;
792   pool->num_learned_literals = 0;
793 
794   assert(clause_pool_invariant(pool));
795 }
796 
797 
798 /*
799  * Make sure there's enough room for allocating n elements
800  * - this should be called only when resize is required
801  */
resize_clause_pool(clause_pool_t * pool,uint32_t n)802 static void resize_clause_pool(clause_pool_t *pool, uint32_t n) {
803   uint32_t min_cap, cap, increase;
804 
805   assert(clause_pool_invariant(pool));
806 
807   min_cap = pool->size + n;
808   if (min_cap < n || min_cap > MAX_CLAUSE_POOL_CAPACITY) {
809     // can't make the pool large enough
810     out_of_memory();
811   }
812 
813   cap = pool->capacity;
814   do {
815     increase = pool_cap_increase(cap);
816     cap += increase;
817     if (cap < increase) { // arithmetic overflow
818       cap = MAX_CLAUSE_POOL_CAPACITY;
819     }
820   } while (cap < min_cap);
821 
822   pool->data = (uint32_t *) safe_realloc(pool->data, cap * sizeof(uint32_t));;
823   pool->capacity = cap;
824   pool->available = cap - pool->size;
825 
826   assert(clause_pool_invariant(pool));
827 }
828 
829 
830 /*
831  * Allocate an array of n integers in the pool and return its idx
832  */
clause_pool_alloc_array(clause_pool_t * pool,uint32_t n)833 static cidx_t clause_pool_alloc_array(clause_pool_t *pool, uint32_t n) {
834   cidx_t i;
835 
836   assert(clause_pool_invariant(pool));
837 
838   n = (n + 3) & ~3; // round up to the next multiple of 4
839   if (n > pool->available) {
840     resize_clause_pool(pool, n);
841   }
842   assert(n <= pool->available);
843 
844   i = pool->size;
845   pool->size += n;
846   pool->available -= n;
847 
848   assert(clause_pool_invariant(pool));
849 
850   return i;
851 }
852 
853 
854 /*
855  * CLAUSE ADDITION
856  */
857 
858 /*
859  * Initialize the clause that starts at index cidx:
860  * - set the header: length = n, aux = 0
861  * - copy the literals
862  */
clause_pool_init_clause(clause_pool_t * pool,cidx_t cidx,uint32_t n,const literal_t * a)863 static void clause_pool_init_clause(clause_pool_t *pool, cidx_t cidx, uint32_t n, const literal_t *a) {
864   uint32_t i;
865   uint32_t *p;
866 
867   pool->data[cidx] = n;
868   pool->data[cidx + 1] = 0;
869   p = pool->data + cidx + 2;
870   for (i=0; i<n; i++) {
871     p[i] = a[i];
872   }
873 }
874 
875 /*
876  * Add a problem clause
877  */
clause_pool_add_problem_clause(clause_pool_t * pool,uint32_t n,const literal_t * a)878 static cidx_t clause_pool_add_problem_clause(clause_pool_t *pool, uint32_t n, const literal_t *a) {
879   uint32_t cidx;
880 
881   assert(pool->learned == pool->size);
882 
883   cidx = clause_pool_alloc_array(pool, n+2);
884   clause_pool_init_clause(pool, cidx, n, a);
885 
886   pool->num_prob_clauses ++;
887   pool->num_prob_literals += n;
888   pool->learned = pool->size;
889 
890   return cidx;
891 }
892 
893 /*
894  * Add a learned clause
895  */
clause_pool_add_learned_clause(clause_pool_t * pool,uint32_t n,const literal_t * a)896 static cidx_t clause_pool_add_learned_clause(clause_pool_t *pool, uint32_t n, const literal_t *a) {
897   uint32_t cidx;
898 
899   cidx = clause_pool_alloc_array(pool, n+2);
900   clause_pool_init_clause(pool, cidx, n, a);
901 
902   pool->num_learned_clauses ++;
903   pool->num_learned_literals += n;
904 
905   return cidx;
906 }
907 
908 
909 /*
910  * ACCESS CLAUSES
911  */
912 #ifndef NDEBUG
good_clause_idx(const clause_pool_t * pool,cidx_t idx)913 static inline bool good_clause_idx(const clause_pool_t *pool, cidx_t idx) {
914   return ((idx & 3) == 0) && idx < pool->size;
915 }
916 #endif
917 
is_learned_clause_idx(const clause_pool_t * pool,cidx_t idx)918 static inline bool is_learned_clause_idx(const clause_pool_t *pool, cidx_t idx) {
919   assert(good_clause_idx(pool, idx));
920   return  idx >= pool->learned;
921 }
922 
is_problem_clause_idx(const clause_pool_t * pool,cidx_t idx)923 static inline bool is_problem_clause_idx(const clause_pool_t *pool, cidx_t idx) {
924   assert(good_clause_idx(pool, idx));
925   return  idx < pool->learned;
926 }
927 
clause_of_idx(const clause_pool_t * pool,cidx_t idx)928 static inline nclause_t *clause_of_idx(const clause_pool_t *pool, cidx_t idx) {
929   assert(good_clause_idx(pool, idx));
930   return (nclause_t *) ((char *) (pool->data + idx));
931 }
932 
933 
934 
935 /*
936  * MARKS ON CLAUSES
937  */
938 
939 /*
940  * In preprocessing and during garbage collection, we mark clauses
941  * by setting the high-order bit of the clause's length.
942  * This is safe since a clause can't have more than MAX_VARIABLES literals
943  * and MAX_VARIABLES < 2^31.
944  */
945 #define CLAUSE_MARK (((uint32_t) 1) << 31)
946 
mark_clause(clause_pool_t * pool,cidx_t idx)947 static inline void mark_clause(clause_pool_t *pool, cidx_t idx) {
948   assert(good_clause_idx(pool, idx));
949   pool->data[idx] |= CLAUSE_MARK;
950 }
951 
unmark_clause(clause_pool_t * pool,cidx_t idx)952 static inline void unmark_clause(clause_pool_t *pool, cidx_t idx) {
953   assert(good_clause_idx(pool, idx));
954   pool->data[idx] &= ~CLAUSE_MARK;
955 }
956 
clause_is_unmarked(const clause_pool_t * pool,cidx_t idx)957 static inline bool clause_is_unmarked(const clause_pool_t *pool, cidx_t idx) {
958   assert(good_clause_idx(pool, idx));
959   return (pool->data[idx] & CLAUSE_MARK) == 0;
960 }
961 
962 #ifndef NDEBUG
clause_is_marked(const clause_pool_t * pool,cidx_t idx)963 static inline bool clause_is_marked(const clause_pool_t *pool, cidx_t idx) {
964   return !clause_is_unmarked(pool, idx);
965 }
966 #endif
967 
968 
969 /*
970  * Length of a clause
971  */
clause_length(const clause_pool_t * pool,cidx_t idx)972 static inline uint32_t clause_length(const clause_pool_t *pool, cidx_t idx) {
973   assert(good_clause_idx(pool, idx));
974   return pool->data[idx] & ~CLAUSE_MARK;
975 }
976 
977 /*
978  * Start of the literal array for clause idx
979  */
clause_literals(const clause_pool_t * pool,cidx_t idx)980 static inline literal_t *clause_literals(const clause_pool_t *pool, cidx_t idx) {
981   assert(good_clause_idx(pool, idx));
982   return (literal_t *) pool->data + idx + 2;
983 }
984 
985 /*
986  * Full size of a clause of n literals:
987  * - 2 + n, rounded up to the next multiple of four
988  */
full_length(uint32_t n)989 static inline uint32_t full_length(uint32_t n) {
990   return (n + 5) & ~3;
991 }
992 
clause_full_length(const clause_pool_t * pool,uint32_t idx)993 static inline uint32_t clause_full_length(const clause_pool_t *pool, uint32_t idx) {
994   return full_length(clause_length(pool, idx));
995 }
996 
997 
998 /*
999  * Get watch literals of clause cidx
1000  * - the first literal is the implied literal if any
1001  */
first_literal_of_clause(const clause_pool_t * pool,cidx_t cidx)1002 static inline literal_t first_literal_of_clause(const clause_pool_t *pool, cidx_t cidx) {
1003   assert(good_clause_idx(pool, cidx));
1004   return pool->data[cidx + 2];
1005 }
1006 
second_literal_of_clause(const clause_pool_t * pool,cidx_t cidx)1007 static inline literal_t second_literal_of_clause(const clause_pool_t *pool, cidx_t cidx) {
1008   assert(good_clause_idx(pool, cidx));
1009   return pool->data[cidx + 3];
1010 }
1011 
1012 
1013 /*
1014  * Watched literal that's not equal to l
1015  */
other_watched_literal_of_clause(const clause_pool_t * pool,cidx_t cidx,literal_t l)1016 static literal_t other_watched_literal_of_clause(const clause_pool_t *pool, cidx_t cidx, literal_t l) {
1017   literal_t l0, l1;
1018   l0 = first_literal_of_clause(pool, cidx);
1019   l1 = second_literal_of_clause(pool, cidx);
1020   assert(l0 == l || l1 == l);
1021   return l0 ^ l1 ^ l;
1022 }
1023 
1024 
1025 /*
1026  * CLAUSE ACTIVITY
1027  */
set_learned_clause_activity(clause_pool_t * pool,cidx_t cidx,float act)1028 static inline void set_learned_clause_activity(clause_pool_t *pool, cidx_t cidx, float act) {
1029   nclause_t *c;
1030 
1031   assert(is_learned_clause_idx(pool, cidx) && sizeof(float) == sizeof(uint32_t));
1032 
1033   c = clause_of_idx(pool, cidx);
1034   c->aux.f = act;
1035 }
1036 
get_learned_clause_activity(const clause_pool_t * pool,cidx_t cidx)1037 static inline float get_learned_clause_activity(const clause_pool_t *pool, cidx_t cidx) {
1038   nclause_t *c;
1039 
1040   assert(is_learned_clause_idx(pool, cidx) && sizeof(float) == sizeof(uint32_t));
1041 
1042   c = clause_of_idx(pool, cidx);
1043   return c->aux.f;
1044 }
1045 
increase_learned_clause_activity(clause_pool_t * pool,cidx_t cidx,float incr)1046 static inline void increase_learned_clause_activity(clause_pool_t *pool, cidx_t cidx, float incr) {
1047   nclause_t *c;
1048 
1049   assert(is_learned_clause_idx(pool, cidx) && sizeof(float) == sizeof(uint32_t));
1050 
1051   c = clause_of_idx(pool, cidx);
1052   c->aux.f += incr;
1053 }
1054 
multiply_learned_clause_activity(clause_pool_t * pool,cidx_t cidx,float scale)1055 static inline void multiply_learned_clause_activity(clause_pool_t *pool, cidx_t cidx, float scale) {
1056   nclause_t *c;
1057 
1058   assert(is_learned_clause_idx(pool, cidx) && sizeof(float) == sizeof(uint32_t));
1059 
1060   c = clause_of_idx(pool, cidx);
1061   c->aux.f *= scale;
1062 }
1063 
1064 
1065 /*
1066  * SIGNATURE/ABSTRACTION OF A CLAUSE
1067  */
1068 
1069 /*
1070  * To accelerate subsumption checking, we keep track of the variables occurring in clause cidx
1071  * as a 32-bit vector in the clause's auxiliary data.
1072  */
var_signature(bvar_t x)1073 static inline uint32_t var_signature(bvar_t x) {
1074   return 1u << (x & 31u);
1075 }
1076 
set_clause_signature(clause_pool_t * pool,cidx_t cidx)1077 static void set_clause_signature(clause_pool_t *pool, cidx_t cidx) {
1078   nclause_t *c;
1079   uint32_t i, n, w;
1080 
1081   assert(is_problem_clause_idx(pool, cidx));
1082 
1083   w = 0;
1084   c = clause_of_idx(pool, cidx);
1085   n = c->len & ~CLAUSE_MARK;
1086   for (i=0; i<n; i++) {
1087     w |= var_signature(var_of(c->c[i]));
1088   }
1089   c->aux.d = w;
1090 }
1091 
clause_signature(clause_pool_t * pool,cidx_t cidx)1092 static inline uint32_t clause_signature(clause_pool_t *pool, cidx_t cidx) {
1093   nclause_t *c;
1094 
1095   assert(is_problem_clause_idx(pool, cidx));
1096 
1097   c = clause_of_idx(pool, cidx);
1098   return c->aux.d;
1099 }
1100 
1101 
1102 
1103 
1104 /*
1105  * PADDING BLOCKS
1106  */
1107 
1108 /*
1109  * Check whether i is the start of a padding block
1110  */
is_padding_start(const clause_pool_t * pool,uint32_t i)1111 static inline bool is_padding_start(const clause_pool_t *pool, uint32_t i) {
1112   assert(i < pool->size && is_multiple_of_four(i));
1113   return pool->data[i] == 0;
1114 }
1115 
1116 /*
1117  * Check whether i is the start of a clause
1118  */
is_clause_start(const clause_pool_t * pool,uint32_t i)1119 static inline bool is_clause_start(const clause_pool_t *pool, uint32_t i) {
1120   return !is_padding_start(pool, i);
1121 }
1122 
1123 /*
1124  * Length of the padding block that starts at index i
1125  */
padding_length(const clause_pool_t * pool,uint32_t i)1126 static inline uint32_t padding_length(const clause_pool_t *pool, uint32_t i) {
1127   assert(is_padding_start(pool, i));
1128   return pool->data[i+1];
1129 }
1130 
1131 
1132 /*
1133  * Store a padding block of size n at index i
1134  * - we want to keep i in the interval [0 ... pool->size - 1]
1135  */
clause_pool_padding(clause_pool_t * pool,uint32_t i,uint32_t n)1136 static void clause_pool_padding(clause_pool_t *pool, uint32_t i, uint32_t n) {
1137   uint32_t j;
1138 
1139   assert(i < pool->size && is_multiple_of_four(i)
1140          && is_multiple_of_four(n) && n > 0);
1141 
1142   pool->padding += n;
1143 
1144   j = i+n;
1145   if (j < pool->size && is_padding_start(pool, j)) {
1146     // merge the two padding blocks
1147     n += padding_length(pool, j);
1148   }
1149   pool->data[i] = 0;
1150   pool->data[i+1] = n;
1151 
1152   assert(clause_pool_invariant(pool));
1153 }
1154 
1155 
1156 /*
1157  * DELETE CLAUSES
1158  */
1159 
1160 /*
1161  * Delete the clause that start at index idx
1162  */
clause_pool_delete_clause(clause_pool_t * pool,cidx_t idx)1163 static void clause_pool_delete_clause(clause_pool_t *pool, cidx_t idx) {
1164   uint32_t n;
1165 
1166   assert(good_clause_idx(pool, idx));
1167 
1168   n = clause_length(pool, idx);
1169 
1170   // update the statistics: we must do this first because
1171   // padding may reduce pool->size.
1172   if (is_problem_clause_idx(pool, idx)) {
1173     assert(pool->num_prob_clauses > 0);
1174     assert(pool->num_prob_literals >= n);
1175     pool->num_prob_clauses --;
1176     pool->num_prob_literals -= n;
1177   } else {
1178     assert(pool->num_learned_clauses > 0);
1179     assert(pool->num_learned_literals >= n);
1180     pool->num_learned_clauses --;
1181     pool->num_learned_literals -= n;
1182   }
1183 
1184   clause_pool_padding(pool, idx, full_length(n));
1185 }
1186 
1187 
1188 /*
1189  * Shrink clause idx: n = new size
1190  */
clause_pool_shrink_clause(clause_pool_t * pool,cidx_t idx,uint32_t n)1191 static void clause_pool_shrink_clause(clause_pool_t *pool, cidx_t idx, uint32_t n) {
1192   uint32_t old_n, old_len, new_len, mark;
1193 
1194   assert(good_clause_idx(pool, idx) && n >= 2 && n <= clause_length(pool, idx));
1195 
1196   old_n = pool->data[idx];    // length + mark
1197   mark = old_n & CLAUSE_MARK; // mark only
1198   old_n &= ~CLAUSE_MARK;      // length
1199 
1200   assert(old_n == clause_length(pool, idx));
1201 
1202   old_len = full_length(old_n);
1203   new_len = full_length(n);
1204 
1205   if (is_problem_clause_idx(pool, idx)) {
1206     assert(pool->num_prob_clauses > 0);
1207     assert(pool->num_prob_literals >= old_n);
1208     pool->num_prob_literals -= (old_n - n);
1209   } else {
1210     assert(pool->num_learned_clauses > 0);
1211     assert(pool->num_learned_literals >= old_n);
1212     pool->num_learned_literals -= (old_n - n);
1213   }
1214 
1215   assert(new_len <= old_len);
1216   if (new_len < old_len) {
1217     clause_pool_padding(pool, idx + new_len, old_len - new_len);
1218   }
1219 
1220   pool->data[idx] = mark | n;
1221 }
1222 
1223 
1224 /*
1225  * SCAN THE SET OF CLAUSES
1226  */
1227 
1228 /*
1229  * Find the next clause, scanning from index i
1230  * - i may be the start of a clause or a padding block
1231  * - if there's no more clause after i then we return pool->size
1232  */
next_clause_index(const clause_pool_t * pool,cidx_t i)1233 static cidx_t next_clause_index(const clause_pool_t *pool, cidx_t i) {
1234   while (i < pool->size && is_padding_start(pool, i)) {
1235     i += padding_length(pool, i);
1236   }
1237   return i;
1238 }
1239 
clause_pool_first_clause(const clause_pool_t * pool)1240 static inline cidx_t clause_pool_first_clause(const clause_pool_t *pool) {
1241   return next_clause_index(pool, 0);
1242 }
1243 
clause_pool_first_learned_clause(const clause_pool_t * pool)1244 static inline cidx_t clause_pool_first_learned_clause(const clause_pool_t *pool) {
1245   return next_clause_index(pool, pool->learned);
1246 }
1247 
1248 /*
1249  * Clause that follows idx:
1250  * - idx may be either the start of a padding block, or the start of a clause,
1251  *   or the end mark (pool->size)
1252  */
clause_pool_next_clause(const clause_pool_t * pool,cidx_t idx)1253 static cidx_t clause_pool_next_clause(const clause_pool_t *pool, cidx_t idx) {
1254   uint32_t n;
1255 
1256   assert(idx <= pool->size);
1257 
1258   if (idx == pool->size) {
1259     return idx;
1260   }
1261 
1262   n = 0;
1263   if (is_clause_start(pool, idx)) {
1264     n = clause_full_length(pool, idx);
1265   }
1266   return next_clause_index(pool, idx + n);
1267 }
1268 
1269 /*
1270  * Check whether cidx is a valid clause
1271  * - cidx is an integer stored in a watch vector.
1272  * - it can be a placeholder for a clause that was removed from the watch vector
1273  *   (then cidx is not  a multiple of four).
1274  * - otherwise, cidx is a multiple of four, we check whether cidx
1275  *   is the start of a clause (it can also be the start of a padding block)
1276  */
clause_is_live(const clause_pool_t * pool,cidx_t cidx)1277 static inline bool clause_is_live(const clause_pool_t *pool, cidx_t cidx) {
1278   return is_multiple_of_four(cidx) && is_clause_start(pool, cidx);
1279 }
1280 
1281 
1282 
1283 /*****************
1284  *  WATCH LISTS  *
1285  ****************/
1286 
1287 /*
1288  * Initial capacity: smallish.
1289  *
1290  * We set MAX_WATCH_CAPACITY to ensure two properties:
1291  * 1) (MAX + watch_cap_increase(MAX)) doesn't overflow for uint32_t.
1292  * 2) (sizeof(watch_t) + MAX * sizeof(unit32_t)) doesn't overflow for size_t.
1293  *
1294  * For condition 1, we need MAX <= 0xAAAAAAA7 = 2863311527.
1295  * For condition 2, we need MAX <= (SIZE_MAX/4) - 2.
1296  */
1297 #define DEF_WATCH_CAPACITY 6
1298 
1299 #if ((SIZE_MAX/4) - 2) < 2863311527
1300 #define MAX_WATCH_CAPACITY ((uint32_t) ((SIZE_MAX/4) - 2))
1301 #else
1302 #define MAX_WATCH_CAPACITY ((uint32_t) 2863311527)
1303 #endif
1304 
1305 
1306 /*
1307  * Capacity increase for watch vectors:
1308  * - about 50% increase, rounded up to force the increment to be a multiple of four
1309  */
watch_cap_increase(uint32_t cap)1310 static inline uint32_t watch_cap_increase(uint32_t cap) {
1311   return ((cap >> 1) + 8) & ~3;
1312 }
1313 
1314 /*
1315  * Allocate or extend vector v
1316  * - this makes sure there's room for k more element
1317  * - k should be 1 or 2
1318  * Returns v unchanged if v's capacity is large enough.
1319  * Returns the newly allocated/extended v otherwise.
1320  */
resize_watch(watch_t * v,uint32_t k)1321 static watch_t *resize_watch(watch_t *v, uint32_t k) {
1322   uint32_t i, n;
1323 
1324   assert(k <= 2);
1325 
1326   if (v == NULL) {
1327     n = DEF_WATCH_CAPACITY;
1328     v = (watch_t *) safe_malloc(sizeof(watch_t) + n * sizeof(uint32_t));
1329     v->capacity = n;
1330     v->size = 0;
1331     assert(n >= k);
1332   } else {
1333     i = v->size;
1334     n = v->capacity;
1335     if (i + k > n) {
1336       n += watch_cap_increase(n);
1337       if (n > MAX_WATCH_CAPACITY) {
1338         out_of_memory();
1339       }
1340       v = (watch_t *) safe_realloc(v, sizeof(watch_t) + n * sizeof(uint32_t));
1341       v->capacity = n;
1342       assert(i + k <= n);
1343     }
1344   }
1345 
1346   return v;
1347 }
1348 
1349 /*
1350  * Make v smaller if possible.
1351  * - v must not be NULL
1352  */
shrink_watch(watch_t * v)1353 static watch_t *shrink_watch(watch_t *v) {
1354   uint32_t n, cap;
1355 
1356   assert(v != NULL && v->size <= v->capacity && v->capacity <= MAX_WATCH_CAPACITY);
1357 
1358   n = v->size;
1359 
1360   // search for the minimal capacity >= v->size
1361   // since n <= MAX_WATCH_CAPACITY, there's no risk of numerical overflow
1362   cap = DEF_WATCH_CAPACITY;
1363   while (cap < n) {
1364     cap += watch_cap_increase(cap);
1365   }
1366 
1367   if (cap < v->capacity) {
1368     v = (watch_t *) safe_realloc(v, sizeof(watch_t) + cap * sizeof(uint32_t));
1369     v->capacity = cap;
1370     assert(v->size <= v->capacity);
1371   }
1372 
1373   return v;
1374 }
1375 
1376 
1377 /*
1378  * Reset: empty w. It must not be null
1379  */
reset_watch(watch_t * w)1380 static inline void reset_watch(watch_t *w) {
1381   w->size = 0;
1382 }
1383 
1384 
1385 /*
1386  * Add k at the end of vector *w.
1387  * - if *w is NULL, allocate a vector of default size
1388  * - if *w if full, make it 50% larger.
1389  */
add_watch(watch_t ** w,uint32_t k)1390 static void add_watch(watch_t **w, uint32_t k) {
1391   watch_t *v;
1392   uint32_t i;
1393 
1394   v = resize_watch(*w, 1);
1395   *w = v;
1396   i = v->size;
1397   assert(i < v->capacity);
1398   v->data[i] = k;
1399   v->size = i+1;
1400 }
1401 
1402 /*
1403  * Add two elements k1 and k2 at the end of vector *w
1404  */
add_watch2(watch_t ** w,uint32_t k1,uint32_t k2)1405 static void add_watch2(watch_t **w, uint32_t k1, uint32_t k2) {
1406   watch_t *v;
1407   uint32_t i;
1408 
1409   v = resize_watch(*w, 2);
1410   *w = v;
1411   i = v->size;
1412   assert(i + 1 < v->capacity);
1413   v->data[i] = k1;
1414   v->data[i+1] = k2;
1415   v->size = i+2;
1416 }
1417 
1418 /*
1419  * Delete all watch vectors in w[0 ... n-1]
1420  */
delete_watch_vectors(watch_t ** w,uint32_t n)1421 static void delete_watch_vectors(watch_t **w, uint32_t n) {
1422   uint32_t i;
1423 
1424   for (i=0; i<n; i++) {
1425     safe_free(w[i]);
1426     w[i] = NULL;
1427   }
1428 }
1429 
1430 
1431 
1432 /*************************
1433  *  SAVED-CLAUSE VECTOR  *
1434  ************************/
1435 
1436 /*
1437  * Initialization: don't allocate anything yet.
1438  */
init_clause_vector(nclause_vector_t * v)1439 static void init_clause_vector(nclause_vector_t *v) {
1440   v->data = NULL;
1441   v->top = 0;
1442   v->capacity = 0;
1443 }
1444 
1445 /*
1446  * Free memory
1447  */
delete_clause_vector(nclause_vector_t * v)1448 static void delete_clause_vector(nclause_vector_t *v) {
1449   safe_free(v->data);
1450   v->data = NULL;
1451 }
1452 
1453 /*
1454  * Empty the vector
1455  */
reset_clause_vector(nclause_vector_t * v)1456 static void reset_clause_vector(nclause_vector_t *v) {
1457   v->top = 0;
1458 }
1459 
1460 
1461 /*
1462  * Capacity increase: add about 50%
1463  */
clause_vector_new_cap(uint32_t cap)1464 static uint32_t clause_vector_new_cap(uint32_t cap) {
1465   uint32_t ncap;
1466 
1467   if (cap == 0) {
1468     ncap = DEF_CLAUSE_VECTOR_CAPACITY;
1469   } else {
1470     ncap = cap + (((cap >> 1) + 8) & ~3);
1471     if (ncap < cap) { // arithmetic overflow
1472       ncap = MAX_CLAUSE_VECTOR_CAPACITY;
1473     }
1474   }
1475   return ncap;
1476 }
1477 
1478 
1479 /*
1480  * Make room for at least (n + 1) elements at the end of v->data.
1481  */
resize_clause_vector(nclause_vector_t * v,uint32_t n)1482 static void resize_clause_vector(nclause_vector_t *v, uint32_t n) {
1483   uint32_t new_top, cap;
1484 
1485   new_top = v->top + n + 1;
1486   if (new_top <= v->top || new_top > MAX_CLAUSE_VECTOR_CAPACITY) {
1487     // arithmetic overflow or request too large
1488     out_of_memory();
1489   }
1490 
1491   if (v->capacity < new_top) {
1492     cap = clause_vector_new_cap(v->capacity);
1493     while (cap < new_top) {
1494       cap = clause_vector_new_cap(cap);
1495     }
1496     v->data = (uint32_t *) safe_realloc(v->data, cap * sizeof(uint32_t));
1497     v->capacity = cap;
1498   }
1499 }
1500 
1501 
1502 /*
1503  * Store clause a[0 ... n-1] at the end of v
1504  * - l = distinguished literal in the clause (stored last).
1505  * - l must occur in a[0 ... n-1]
1506  * - the vector must have room for n literals
1507  */
clause_vector_save_clause(nclause_vector_t * v,uint32_t n,const literal_t * a,literal_t l)1508 static void clause_vector_save_clause(nclause_vector_t *v, uint32_t n, const literal_t *a, literal_t l) {
1509   uint32_t i, j;
1510   literal_t z;
1511 
1512   assert(v->top + n <= v->capacity);
1513 
1514   j = v->top;
1515   for (i=0; i<n; i++) {
1516     z = a[i];
1517     if (z != l) {
1518       v->data[j] = z;
1519       j ++;
1520     }
1521   }
1522   assert(j - v->top == n - 1);
1523   v->data[j] = l;
1524   v->top = j+1;
1525 }
1526 
1527 
1528 /*
1529  * Store s (block size) at the end of v
1530  */
clause_vector_add_block_length(nclause_vector_t * v,uint32_t s)1531 static void clause_vector_add_block_length(nclause_vector_t *v, uint32_t s) {
1532   uint32_t j;
1533 
1534   j = v->top;
1535   assert(j < v->capacity);
1536   v->data[j] = s;
1537   v->top = j+1;
1538 }
1539 
1540 /*
1541  * Store block for a variable eliminated by substitution:
1542  * - for l := l0, we store l0, not(l), 2.
1543  */
clause_vector_save_subst_clause(nclause_vector_t * v,literal_t l0,literal_t l)1544 static void clause_vector_save_subst_clause(nclause_vector_t *v, literal_t l0, literal_t l) {
1545   uint32_t j;
1546 
1547   resize_clause_vector(v, 2);
1548   assert(v->top + 3 <= v->capacity);
1549 
1550   j = v->top;
1551   v->data[j] = l0;
1552   v->data[j+1] = not(l);
1553   v->data[j+2] = 2;
1554   v->top = j + 3;
1555 }
1556 
1557 
1558 
1559 /**********************
1560  *  ELIMINATION HEAP  *
1561  *********************/
1562 
1563 /*
1564  * Initialize: don't allocate anything yet
1565  */
init_elim_heap(elim_heap_t * heap)1566 static void init_elim_heap(elim_heap_t *heap) {
1567   heap->data = NULL;
1568   heap->elim_idx = NULL;
1569   heap->size = 0;
1570   heap->capacity = 0;
1571 }
1572 
1573 /*
1574  * Prepare: n = number of variables
1575  * - this allocates the data array and the elim_idx array
1576  */
prepare_elim_heap(elim_heap_t * heap,uint32_t n)1577 static void prepare_elim_heap(elim_heap_t *heap, uint32_t n) {
1578   uint32_t k;
1579 
1580   assert(heap->data == NULL && heap->elim_idx == NULL && n > 0);
1581 
1582   k = DEF_ELIM_HEAP_SIZE;
1583   assert(0 < k && k <= MAX_ELIM_HEAP_SIZE);
1584   heap->data = (bvar_t *) safe_malloc(k * sizeof(bvar_t));
1585   heap->elim_idx = (int32_t *) safe_malloc(n * sizeof(int32_t));
1586   heap->size = 1;
1587   heap->capacity = k;
1588 
1589   heap->data[0] = 0;
1590   heap->elim_idx[0] = 0;
1591   for (k=1; k<n; k++) {
1592     heap->elim_idx[k] = -1;
1593   }
1594 }
1595 
1596 /*
1597  * Capacity increase for the data array
1598  */
elim_heap_cap_increase(uint32_t cap)1599 static inline uint32_t elim_heap_cap_increase(uint32_t cap) {
1600   return ((cap >> 1) + 8) & ~3;
1601 }
1602 
1603 /*
1604  * Make the data array larger
1605  */
extend_elim_heap(elim_heap_t * heap)1606 static void extend_elim_heap(elim_heap_t *heap) {
1607   uint32_t n;
1608 
1609   n = heap->capacity + elim_heap_cap_increase(heap->capacity);
1610   assert(n > heap->capacity);
1611   if (n > MAX_ELIM_HEAP_SIZE) {
1612     out_of_memory();
1613   }
1614   heap->data = (bvar_t *) safe_realloc(heap->data, n * sizeof(bvar_t));
1615   heap->capacity = n;
1616 }
1617 
delete_elim_heap(elim_heap_t * heap)1618 static void delete_elim_heap(elim_heap_t *heap) {
1619   safe_free(heap->data);
1620   safe_free(heap->elim_idx);
1621   heap->data = NULL;
1622   heap->elim_idx = NULL;
1623 }
1624 
reset_elim_heap(elim_heap_t * heap)1625 static void reset_elim_heap(elim_heap_t *heap) {
1626   delete_elim_heap(heap);
1627   heap->size = 0;
1628   heap->capacity = 0;
1629 }
1630 
1631 
1632 
1633 /**********************
1634  *  ASSIGNMENT STACK  *
1635  *********************/
1636 
1637 /*
1638  * Initialize stack s for nvar
1639  */
init_stack(sol_stack_t * s,uint32_t nvar)1640 static void init_stack(sol_stack_t *s, uint32_t nvar) {
1641   s->lit = (literal_t *) safe_malloc(nvar * sizeof(literal_t));
1642   s->level_index = (uint32_t *) safe_malloc(DEFAULT_NLEVELS * sizeof(uint32_t));
1643   s->level_index[0] = 0;
1644   s->top = 0;
1645   s->prop_ptr = 0;
1646   s->nlevels = DEFAULT_NLEVELS;
1647 }
1648 
1649 /*
1650  * Extend the stack: nvar = new size
1651  */
extend_stack(sol_stack_t * s,uint32_t nvar)1652 static void extend_stack(sol_stack_t *s, uint32_t nvar) {
1653   s->lit = (literal_t *) safe_realloc(s->lit, nvar * sizeof(literal_t));
1654 }
1655 
1656 /*
1657  * Extend the level_index array by 50%
1658  *
1659  * (since nlevels <= number of variables <= UINT32/4, we know
1660  *  that nlevels + (nlevels>>1) can't overflow).
1661  */
increase_stack_levels(sol_stack_t * s)1662 static void increase_stack_levels(sol_stack_t *s) {
1663   uint32_t n;
1664 
1665   n = s->nlevels;
1666   n += n>>1;
1667   s->level_index = (uint32_t *) safe_realloc(s->level_index, n * sizeof(uint32_t));
1668   s->nlevels = n;
1669 }
1670 
1671 /*
1672  * Free memory used by stack s
1673  */
delete_stack(sol_stack_t * s)1674 static void delete_stack(sol_stack_t *s) {
1675   safe_free(s->lit);
1676   safe_free(s->level_index);
1677   s->lit = NULL;
1678   s->level_index = NULL;
1679 }
1680 
1681 /*
1682  * Empty the stack
1683  */
reset_stack(sol_stack_t * s)1684 static void reset_stack(sol_stack_t *s) {
1685   s->top = 0;
1686   s->prop_ptr = 0;
1687   assert(s->level_index[0] == 0);
1688 }
1689 
1690 /*
1691  * Push literal l on top of stack s
1692  */
push_literal(sol_stack_t * s,literal_t l)1693 static void push_literal(sol_stack_t *s, literal_t l) {
1694   uint32_t i;
1695 
1696   i = s->top;
1697   s->lit[i] = l;
1698   s->top = i + 1;
1699 }
1700 
1701 
1702 
1703 /*******************
1704  *  CLAUSE STACK   *
1705  ******************/
1706 
1707 /*
1708  * Initialize the stack
1709  */
init_clause_stack(clause_stack_t * s)1710 static void init_clause_stack(clause_stack_t *s) {
1711   s->data = (uint32_t *) safe_malloc(DEF_CLAUSE_STACK_CAPACITY * sizeof(uint32_t));
1712   s->top = 0;
1713   s->capacity = DEF_CLAUSE_STACK_CAPACITY;
1714   s->level = (uint32_t *) safe_malloc(DEFAULT_NLEVELS * sizeof(uint32_t));
1715   s->level[0] = 0;
1716   s->nlevels = DEFAULT_NLEVELS;
1717 }
1718 
1719 
1720 /*
1721  * Extend the level array by 50%
1722  */
increase_clause_stack_levels(clause_stack_t * s)1723 static void increase_clause_stack_levels(clause_stack_t *s) {
1724   uint32_t n;
1725 
1726   n = s->nlevels;
1727   n += n>>1;
1728   s->level = (uint32_t *) safe_realloc(s->level, n * sizeof(uint32_t));
1729   s->nlevels = n;
1730 }
1731 
1732 /*
1733  * Free memory
1734  */
delete_clause_stack(clause_stack_t * s)1735 static void delete_clause_stack(clause_stack_t *s) {
1736   safe_free(s->data);
1737   safe_free(s->level);
1738   s->data = NULL;
1739   s->level = NULL;
1740 }
1741 
1742 /*
1743  * Empty the stack
1744  */
reset_clause_stack(clause_stack_t * s)1745 static void reset_clause_stack(clause_stack_t *s) {
1746   s->top = 0;
1747   assert(s->level[0] == 0);
1748 }
1749 
1750 
1751 #if USE_DIVING
1752 
1753 /*
1754  * Capacity increase:
1755  * - about 50% larger than the current cap
1756  * - rounded up to the next multiple of four
1757  */
clause_stack_cap_increase(uint32_t cap)1758 static inline uint32_t clause_stack_cap_increase(uint32_t cap) {
1759   return ((cap >> 1) + 8) & ~3;
1760 }
1761 
1762 /*
1763  * Increase the stack size until we have enough room for n elements
1764  */
resize_clause_stack(clause_stack_t * s,uint32_t n)1765 static void resize_clause_stack(clause_stack_t *s, uint32_t n) {
1766   uint32_t min_cap, cap, increase;
1767 
1768   min_cap = s->top + n;
1769   if (min_cap < n || min_cap >= MAX_CLAUSE_STACK_CAPACITY) {
1770     // can't make the stack that large
1771     out_of_memory();
1772   }
1773 
1774   cap = s->capacity;
1775   do {
1776     increase = clause_stack_cap_increase(cap);
1777     cap += increase;
1778     if (cap < increase) {
1779       // arithmetic overflow
1780       cap = MAX_CLAUSE_STACK_CAPACITY;
1781     }
1782   } while (cap < min_cap);
1783 
1784   s->data = (uint32_t *) safe_realloc(s->data, cap * sizeof(uint32_t));
1785   s->capacity = cap;
1786 }
1787 
1788 /*
1789  * Make room to push n integers on top of the stack
1790  */
clause_stack_alloc(clause_stack_t * s,uint32_t n)1791 static cidx_t clause_stack_alloc(clause_stack_t *s, uint32_t n) {
1792   cidx_t i;
1793 
1794   i = s->top;
1795   n = (n + 3) & ~3; // round up to a multiple of four
1796   if (i + n >= s->capacity) {
1797     resize_clause_stack(s, n);
1798   }
1799   s->top = i+n;
1800 
1801   return i;
1802 }
1803 
1804 
1805 /*
1806  * Add a clause to the stack and return the clause idx.
1807  * - n = size of the clause
1808  * - a = literal array
1809  */
push_clause(clause_stack_t * s,uint32_t n,const literal_t * a)1810 static cidx_t push_clause(clause_stack_t *s, uint32_t n, const literal_t *a) {
1811   uint32_t i, cidx;
1812   uint32_t *p;
1813 
1814   cidx = clause_stack_alloc(s, n+2);
1815   s->data[cidx] = n;
1816   s->data[cidx + 1] = 0;
1817   p = s->data + cidx + 2;
1818   for (i=0; i<n; i++) {
1819     p[i] = a[i];
1820   }
1821   return cidx;
1822 }
1823 
1824 #endif
1825 
1826 /*
1827  * READ STACKED CLAUSES
1828  */
1829 #ifndef NDEBUG
good_stacked_clause_idx(const clause_stack_t * s,cidx_t idx)1830 static inline bool good_stacked_clause_idx(const clause_stack_t *s, cidx_t idx) {
1831   return ((idx & 3) == 0) && idx < s->top;
1832 }
1833 #endif
1834 
stacked_clause_length(const clause_stack_t * s,cidx_t idx)1835 static inline uint32_t stacked_clause_length(const clause_stack_t *s, cidx_t idx) {
1836   assert(good_stacked_clause_idx(s, idx));
1837   return s->data[idx];
1838 }
1839 
stacked_clause_literals(const clause_stack_t * s,cidx_t idx)1840 static inline literal_t *stacked_clause_literals(const clause_stack_t *s, cidx_t idx) {
1841   assert(good_stacked_clause_idx(s, idx));
1842   return (literal_t *) s->data + idx + 2;
1843 }
1844 
1845 
1846 #if DEBUG
next_stacked_clause(const clause_stack_t * s,cidx_t idx)1847 static inline cidx_t next_stacked_clause(const clause_stack_t *s, cidx_t idx) {
1848   return idx + full_length(stacked_clause_length(s, idx)); // length + 2 rounded up to a multiple of four
1849 }
1850 #endif
1851 
1852 #if DEBUG || !defined(NDEBUG)
first_literal_of_stacked_clause(const clause_stack_t * s,cidx_t idx)1853 static inline literal_t first_literal_of_stacked_clause(const clause_stack_t *s, cidx_t idx) {
1854   assert(good_stacked_clause_idx(s, idx));
1855   return s->data[idx + 2];
1856 }
1857 #endif
1858 
1859 
1860 
1861 
1862 /*******************
1863  *  VARIABLE HEAP  *
1864  ******************/
1865 
1866 /*
1867  * Initialize heap for size n and nv variables
1868  * - heap is initially empty: heap_last = 0
1869  * - heap[0] = 0 is a marker, with rank[0] higher
1870  *   than any other variable
1871  */
init_heap(nvar_heap_t * heap,uint32_t n,uint32_t nv)1872 static void init_heap(nvar_heap_t *heap, uint32_t n, uint32_t nv) {
1873   uint32_t i;
1874 
1875   heap->rank = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
1876   heap->heap_index = (int32_t *) safe_malloc(n * sizeof(int32_t));
1877   heap->heap = (bvar_t *) safe_malloc(n * sizeof(bvar_t));
1878 
1879   // marker
1880   heap->rank[0] = UINT32_MAX;
1881   heap->heap_index[0] = 0;
1882   heap->heap[0] = 0;
1883 
1884   for (i=1; i<nv; i++) {
1885     heap->heap_index[i] = -1;
1886     heap->rank[i] = 0;
1887   }
1888 
1889   heap->heap_last = 0;
1890   heap->size = n;
1891   heap->nvars = nv;
1892   heap->vmax = 1;
1893   heap->max_rank = 0;
1894 
1895   check_heap(heap);
1896 }
1897 
1898 /*
1899  * Extend the heap: n = new size.
1900  * - keep nvar unchanged
1901  */
extend_heap(nvar_heap_t * heap,uint32_t n)1902 static void extend_heap(nvar_heap_t *heap, uint32_t n) {
1903   assert(heap->size < n);
1904 
1905   heap->rank = (uint32_t *) safe_realloc(heap->rank, n * sizeof(uint32_t));
1906   heap->heap_index = (int32_t *) safe_realloc(heap->heap_index, n * sizeof(int32_t));
1907   heap->heap = (bvar_t *) safe_realloc(heap->heap, n * sizeof(int32_t));
1908   heap->size = n;
1909 
1910   check_heap(heap);
1911 }
1912 
1913 
1914 /*
1915  * Increase the number of variables to n
1916  */
heap_add_vars(nvar_heap_t * heap,uint32_t n)1917 static void heap_add_vars(nvar_heap_t *heap, uint32_t n) {
1918   uint32_t old_nvars, i;
1919 
1920   old_nvars = heap->nvars;
1921   assert(n <= heap->size);
1922   for (i=old_nvars; i<n; i++) {
1923     heap->heap_index[i] = -1;
1924     heap->rank[i] = 0;
1925   }
1926   heap->nvars = n;
1927 
1928   check_heap(heap);
1929 }
1930 
1931 
1932 
1933 /*
1934  * Free the heap
1935  */
delete_heap(nvar_heap_t * heap)1936 static void delete_heap(nvar_heap_t *heap) {
1937   safe_free(heap->rank);
1938   safe_free(heap->heap_index);
1939   safe_free(heap->heap);
1940   heap->rank = NULL;
1941   heap->heap_index = NULL;
1942   heap->heap = NULL;
1943 }
1944 
1945 /*
1946  * Reset: empty the heap
1947  */
reset_heap(nvar_heap_t * heap)1948 static void reset_heap(nvar_heap_t *heap) {
1949   uint32_t i, n;
1950 
1951   heap->heap_last = 0;
1952   heap->vmax = 1;
1953 
1954   n = heap->nvars;
1955   for (i=1; i<n; i++) {
1956     heap->heap_index[i] = -1;
1957     heap->rank[i] = 0.0;
1958   }
1959   check_heap(heap);
1960 }
1961 
1962 /*
1963  * Move x up in the heap.
1964  * i = current position of x in the heap (or heap_last if x is being inserted)
1965  */
update_up(nvar_heap_t * heap,bvar_t x,uint32_t i)1966 static void update_up(nvar_heap_t *heap, bvar_t x, uint32_t i) {
1967   uint32_t rx, *rnk;
1968   int32_t *index;
1969   bvar_t *h, y;
1970   uint32_t j;
1971 
1972   h = heap->heap;
1973   index = heap->heap_index;
1974   rnk = heap->rank;
1975 
1976   rx = rnk[x];
1977 
1978   for (;;) {
1979     j = i >> 1;    // parent of i
1980     y = h[j];      // variable at position j in the heap
1981 
1982     // The loop terminates since rank[h[0]] = UINT32_MAX
1983     if (rnk[y] >= rx) break;
1984 
1985     // move y down, into position i
1986     h[i] = y;
1987     index[y] = i;
1988 
1989     // move i up
1990     i = j;
1991   }
1992 
1993   // i is the new position for variable x
1994   h[i] = x;
1995   index[x] = i;
1996 
1997   check_heap(heap);
1998 }
1999 
2000 /*
2001  * Remove root of the heap (i.e., heap->heap[1]):
2002  * - move the variable currently in heap->heap[last]
2003  *   into a new position.
2004  * - decrement last.
2005  */
update_down(nvar_heap_t * heap)2006 static void update_down(nvar_heap_t *heap) {
2007   uint32_t *rnk;
2008   int32_t *index;
2009   bvar_t *h;
2010   bvar_t x, y, z;
2011   uint32_t rx, ry, rz;
2012   uint32_t i, j, last;
2013 
2014   last = heap->heap_last;
2015   heap->heap_last = last - 1;
2016   if (last <= 1) { // empty heap.
2017     assert(heap->heap_last == 0);
2018     return;
2019   }
2020 
2021   h = heap->heap;
2022   index = heap->heap_index;
2023   rnk = heap->rank;
2024 
2025   z = h[last];   // last element
2026   rz = rnk[z];   // rank of the last element
2027 
2028   i = 1;      // root
2029   j = 2;      // left child of i
2030   while (j < last) {
2031     /*
2032      * find child of i with highest rank.
2033      */
2034     x = h[j];
2035     rx = rnk[x];
2036     if (j+1 < last) {
2037       y = h[j+1];
2038       ry = rnk[y];
2039       if (ry > rx) {
2040         j++;
2041         x = y;
2042         rx = ry;
2043       }
2044     }
2045 
2046     // x = child of node i of highest rank
2047     // j = position of x in the heap (j = 2i or j = 2i+1)
2048     if (rz >= rx) break;
2049 
2050     // move x up, into heap[i]
2051     h[i] = x;
2052     index[x] = i;
2053 
2054     // go down one step.
2055     i = j;
2056     j <<= 1;
2057   }
2058 
2059   h[i] = z;
2060   index[z] = i;
2061 
2062   check_heap(heap);
2063 }
2064 
2065 /*
2066  * Insert x into the heap, using its current rank.
2067  * No effect if x is already in the heap.
2068  * - x must be between 0 and nvars - 1
2069  */
heap_insert(nvar_heap_t * heap,bvar_t x)2070 static void heap_insert(nvar_heap_t *heap, bvar_t x) {
2071   if (heap->heap_index[x] < 0) {
2072     // x not in the heap
2073     heap->heap_last ++;
2074     update_up(heap, x, heap->heap_last);
2075   }
2076 }
2077 
2078 /*
2079  * Check whether the heap is empty
2080  */
heap_is_empty(nvar_heap_t * heap)2081 static inline bool heap_is_empty(nvar_heap_t *heap) {
2082   return heap->heap_last == 0;
2083 }
2084 
2085 /*
2086  * Get and remove the top element
2087  * - the heap must not be empty
2088  */
heap_get_top(nvar_heap_t * heap)2089 static bvar_t heap_get_top(nvar_heap_t *heap) {
2090   bvar_t top;
2091 
2092   assert(heap->heap_last > 0);
2093 
2094   // remove top element
2095   top = heap->heap[1];
2096   heap->heap_index[top] = -1;
2097 
2098   // repair the heap
2099   update_down(heap);
2100 
2101   return top;
2102 }
2103 
2104 /*
2105  * Rescale variable ranks
2106  */
rescale_var_ranks(nvar_heap_t * heap)2107 static void rescale_var_ranks(nvar_heap_t *heap) {
2108   uint32_t i, n, r;
2109   bvar_t x;
2110 
2111   // make sure all variables are in the heap
2112   n = heap->nvars;
2113   for (i=1; i<n; i++) {
2114     heap_insert(heap, i);
2115   }
2116 
2117   // extract variables one by one and update their rank
2118   r = n + 1;
2119   while (! heap_is_empty(heap)) {
2120     x = heap_get_top(heap);
2121     assert(r > 0);
2122     heap->rank[x] = r;
2123     r --;
2124   }
2125 
2126   // put all variables back
2127   for (i=1; i<n; i++) {
2128     heap_insert(heap, i);
2129   }
2130 
2131   heap->max_rank = n + 1;
2132 }
2133 
2134 /*
2135  * Move x to the top of the heap
2136  */
move_var_to_front(nvar_heap_t * heap,bvar_t x)2137 static void move_var_to_front(nvar_heap_t *heap, bvar_t x) {
2138   int32_t i;
2139   uint32_t r;
2140 
2141   if (heap->max_rank > UINT32_MAX-1) {
2142     rescale_var_ranks(heap);
2143   }
2144 
2145   r = heap->max_rank + 1;
2146   heap->rank[x] = r;
2147   heap->max_rank = r;
2148 
2149   // move x up if it's in the heap
2150   i = heap->heap_index[x];
2151   if (i >= 0) update_up(heap, x, i);
2152 }
2153 
2154 /*
2155  * Increate the rank of variable x to r
2156  */
update_var_rank(nvar_heap_t * heap,bvar_t x,uint32_t r)2157 static void update_var_rank(nvar_heap_t *heap, bvar_t x, uint32_t r) {
2158   int32_t i;
2159 
2160   assert(r > heap->rank[x]);
2161 
2162   heap->rank[x] = r;
2163   i = heap->heap_index[x];
2164   if (i >= 0) update_up(heap, x, i);
2165 }
2166 
2167 /*
2168  * Cleanup the heap: remove variables until the top var is unassigned
2169  * or until the heap is empty
2170  */
cleanup_heap(sat_solver_t * solver)2171 static void cleanup_heap(sat_solver_t *solver) {
2172   nvar_heap_t *heap;
2173   bvar_t x;
2174 
2175   heap = &solver->heap;
2176   while (! heap_is_empty(heap)) {
2177     x = heap->heap[1];
2178     if (var_is_unassigned(solver, x) && solver->ante_tag[x] < ATAG_PURE) {
2179       break;
2180     }
2181     assert(x >= 0 && heap->heap_last > 0);
2182     heap->heap_index[x] = -1;
2183     update_down(heap);
2184   }
2185 }
2186 
2187 
2188 /*
2189  * Initial ranking
2190  */
init_var_ranks(sat_solver_t * solver)2191 static void init_var_ranks(sat_solver_t *solver) {
2192   nvar_heap_t *heap;
2193   uint32_t i, n;
2194 
2195   heap = &solver->heap;
2196   n = heap->nvars;
2197   for (i=1; i<n; i++) {
2198     heap->rank[i] = i;
2199     heap->heap_index[i] = -1;
2200   }
2201   for (i=1; i<n; i++) {
2202     update_up(heap, i, i);
2203   }
2204   heap->heap_last = n - 1;
2205   heap->max_rank = n - 1;
2206 }
2207 
2208 
2209 /*
2210  * Rank of variable x or a literal l
2211  */
var_rank(const sat_solver_t * solver,bvar_t x)2212 static inline uint32_t var_rank(const sat_solver_t *solver, bvar_t x) {
2213   assert(x < solver->nvars);
2214   return solver->heap.rank[x];
2215 }
2216 
lit_rank(const sat_solver_t * solver,literal_t l)2217 static inline uint32_t lit_rank(const sat_solver_t *solver, literal_t l) {
2218   return var_rank(solver, var_of(l));
2219 }
2220 
2221 
2222 /*
2223  * Increase rank of literal l to r
2224  * - assumes r > lit_rank(l)
2225  */
update_lit_rank(sat_solver_t * solver,literal_t l,uint32_t r)2226 static inline void update_lit_rank(sat_solver_t *solver, literal_t l, uint32_t r) {
2227   update_var_rank(&solver->heap, var_of(l), r);
2228 }
2229 
2230 
2231 /*
2232  * MARKS ON VARIABLES
2233  */
2234 
2235 /*
2236  * Set/clear/test the mark on variable x
2237  * - we use the high order bit of the ante_tag
2238  * - if this bit is 1, x is marked
2239  */
mark_variable(sat_solver_t * solver,bvar_t x)2240 static inline void mark_variable(sat_solver_t *solver, bvar_t x) {
2241   assert(x < solver->nvars);
2242   solver->ante_tag[x] |= (uint8_t) 0x80;
2243 }
2244 
unmark_variable(sat_solver_t * solver,bvar_t x)2245 static inline void unmark_variable(sat_solver_t *solver, bvar_t x) {
2246   assert(x < solver->nvars);
2247   solver->ante_tag[x] &= (uint8_t) 0x7F;
2248 }
2249 
variable_is_marked(const sat_solver_t * solver,bvar_t x)2250 static inline bool variable_is_marked(const sat_solver_t *solver, bvar_t x) {
2251   assert(x < solver->nvars);
2252   return (solver->ante_tag[x] & (uint8_t) 0x80) != 0;
2253 }
2254 
literal_is_marked(const sat_solver_t * solver,literal_t l)2255 static inline bool literal_is_marked(const sat_solver_t *solver, literal_t l) {
2256   return variable_is_marked(solver, var_of(l));
2257 }
2258 
2259 
2260 
2261 /**************************
2262  *  VARIABLE DESCRIPTORS  *
2263  *************************/
2264 
2265 /*
2266  * Initialize the descriptor table: nothing allocated
2267  */
init_descriptors(descriptors_t * table)2268 static void init_descriptors(descriptors_t *table) {
2269   table->tag = NULL;
2270   table->desc = NULL;
2271   table->size = 0;
2272   table->capacity = 0;
2273 }
2274 
2275 /*
2276  * Delete
2277  */
delete_descriptors(descriptors_t * table)2278 static void delete_descriptors(descriptors_t *table) {
2279   safe_free(table->tag);
2280   safe_free(table->desc);
2281   table->tag = NULL;
2282   table->desc = NULL;
2283 }
2284 
2285 /*
2286  * Empty
2287  */
reset_descriptors(descriptors_t * table)2288 static inline void reset_descriptors(descriptors_t *table) {
2289   table->size = 0;
2290 }
2291 
2292 /*
2293  * Capacity increase: like for vector
2294  * - about 50% increase rounded up to a multiple of four
2295  */
descriptors_cap_increase(uint32_t cap)2296 static inline uint32_t descriptors_cap_increase(uint32_t cap) {
2297   return ((cap >> 1) + 8) & ~3;
2298 }
2299 
2300 /*
2301  * Increase cap until it's larger than n
2302  */
descriptors_new_cap(uint32_t cap,uint32_t n)2303 static uint32_t descriptors_new_cap(uint32_t cap, uint32_t n) {
2304   if (cap == 0) {
2305     cap = DEF_DESCRIPTORS_SIZE;
2306     if (cap > n) return cap;
2307   }
2308 
2309   do {
2310     cap += descriptors_cap_increase(cap);
2311     if (cap > MAX_DESCRIPTORS_SIZE) {
2312       out_of_memory();
2313     }
2314   } while (cap <= n);
2315 
2316   return cap;
2317 }
2318 
2319 
2320 /*
2321  * Make sure the arrays are large enough to store data about variable x
2322  */
resize_descriptors(descriptors_t * table,bvar_t x)2323 static void resize_descriptors(descriptors_t *table, bvar_t x) {
2324   uint32_t new_cap;
2325 
2326   assert(x >= 0);
2327   new_cap = descriptors_new_cap(table->capacity, (uint32_t) x);
2328 
2329   table->tag = (uint8_t *) safe_realloc(table->tag, new_cap * sizeof(uint8_t));
2330   table->desc = (uint32_t *) safe_realloc(table->desc, new_cap * sizeof(uint32_t));
2331   table->capacity = new_cap;
2332 }
2333 
2334 /*
2335  * Store a descriptor for variable x:
2336  * - tag = tag for x
2337  * - d = auxiliary data
2338  */
add_descriptor(descriptors_t * table,bvar_t x,descriptor_tag_t tag,uint32_t d)2339 static void add_descriptor(descriptors_t *table, bvar_t x, descriptor_tag_t tag, uint32_t d) {
2340   uint32_t i;
2341 
2342   assert(0 <= x && x < MAX_VARIABLES);
2343 
2344   if (x >= table->capacity) {
2345     resize_descriptors(table, x);
2346     assert(x < table->capacity);
2347   }
2348 
2349   if (x >= table->size) {
2350     for (i=table->size; i<x; i++) {
2351       table->tag[i] = DTAG_NONE;
2352     }
2353     table->size = x+1;
2354   }
2355 
2356   table->tag[x] = tag;
2357   table->desc[x] = d;
2358 }
2359 
2360 
2361 /*
2362  * Check whether x is marked as a keeper
2363  */
bvar_to_keep(const descriptors_t * table,bvar_t x)2364 static bool bvar_to_keep(const descriptors_t *table, bvar_t x) {
2365   assert(0 <= x);
2366   return x < table->size && table->tag[x] == DTAG_TO_KEEP;
2367 }
2368 
2369 
2370 /*
2371  * Check whether x has a gate definition
2372  */
bvar_is_gate(const descriptors_t * table,bvar_t x)2373 static bool bvar_is_gate(const descriptors_t *table, bvar_t x) {
2374   assert(0 <= x);
2375   return x < table->size && table->tag[x] == DTAG_GATE;
2376 }
2377 
2378 /*
2379  * Get the gate index for variable x
2380  */
bvar_get_gate(const descriptors_t * table,bvar_t x)2381 static uint32_t bvar_get_gate(const descriptors_t *table, bvar_t x) {
2382   assert(bvar_is_gate(table, x));
2383   return table->desc[x];
2384 }
2385 
2386 
2387 
2388 /********************************
2389  *  SAT SOLVER INITIALIZATION   *
2390  *******************************/
2391 
2392 /*
2393  * Initialize a statistics record
2394  */
init_stats(solver_stats_t * stat)2395 static void init_stats(solver_stats_t *stat) {
2396   stat->decisions = 0;
2397   stat->random_decisions = 0;
2398   stat->propagations = 0;
2399   stat->conflicts = 0;
2400   stat->prob_clauses_deleted = 0;
2401   stat->learned_clauses_deleted = 0;
2402   stat->subsumed_literals = 0;
2403   stat->starts = 0;
2404   stat->dives = 0;
2405   stat->simplify_calls = 0;
2406   stat->reduce_calls = 0;
2407   stat->subst_calls = 0;
2408   stat->successful_dive = 0;
2409   stat->scc_calls = 0;
2410   stat->subst_vars = 0;
2411   stat->subst_units = 0;
2412   stat->equivs = 0;
2413   stat->pp_pure_lits = 0;
2414   stat->pp_unit_lits = 0;
2415   stat->pp_subst_vars = 0;
2416   stat->pp_subst_units = 0;
2417   stat->pp_equivs = 0;
2418   stat->pp_clauses_deleted = 0;
2419   stat->pp_subsumptions = 0;
2420   stat->pp_strengthenings = 0;
2421   stat->pp_unit_strengthenings = 0;
2422   stat->pp_cheap_elims = 0;
2423   stat->pp_var_elims = 0;
2424 }
2425 
2426 /*
2427  * Search parameters
2428  */
init_params(solver_param_t * params)2429 static void init_params(solver_param_t *params) {
2430   params->seed = PRNG_SEED;
2431   params->randomness = (uint32_t) (VAR_RANDOM_FACTOR * VAR_RANDOM_SCALE);
2432   params->inv_cla_decay = ((float) 1)/CLAUSE_DECAY_FACTOR;
2433   params->stack_threshold = STACK_THRESHOLD;
2434   params->keep_lbd = KEEP_LBD;
2435   params->reduce_fraction = REDUCE_FRACTION;
2436   params->reduce_interval = REDUCE_INTERVAL;
2437   params->reduce_delta = REDUCE_DELTA;
2438   params->restart_interval = RESTART_INTERVAL;
2439   params->search_period = SEARCH_PERIOD;
2440   params->search_counter = SEARCH_COUNTER;
2441   params->diving_budget = DIVING_BUDGET;
2442 
2443   params->var_elim_skip = VAR_ELIM_SKIP;
2444   params->subsume_skip = SUBSUME_SKIP;
2445   params->res_clause_limit = RES_CLAUSE_LIMIT;
2446 
2447   params->simplify_interval = SIMPLIFY_INTERVAL;
2448   params->simplify_bin_delta = SIMPLIFY_BIN_DELTA;
2449   params->simplify_subst_delta = SIMPLIFY_SUBST_DELTA;
2450 }
2451 
2452 /*
2453  * Initialization:
2454  * - sz = initial size of the variable-indexed arrays.
2455  * - pp = flag to enable preprocessing
2456  *
2457  * - if sz is zero, the default size is used.
2458  * - the solver is initialized with one variable (the reserved variable 0).
2459  */
init_nsat_solver(sat_solver_t * solver,uint32_t sz,bool pp)2460 void init_nsat_solver(sat_solver_t *solver, uint32_t sz, bool pp) {
2461   uint32_t n;
2462 
2463   if (sz > MAX_VARIABLES) {
2464     out_of_memory();
2465   }
2466 
2467   n = sz;
2468   if (sz == 0) {
2469     n = SAT_SOLVER_DEFAULT_VSIZE;
2470   }
2471   assert(n >= 1 && n <= MAX_VARIABLES);
2472 
2473   solver->status = STAT_UNKNOWN;
2474   solver->decision_level = 0;
2475   solver->backtrack_level = 0;
2476   solver->preprocess = pp;
2477 
2478   solver->verbosity = 0;
2479   solver->reports = 0;
2480 
2481   solver->nvars = 1;
2482   solver->nliterals = 2;
2483   solver->vsize = n;
2484   solver->lsize = 2 * n;
2485 
2486   solver->value = (uint8_t *) safe_malloc(n * 2 * sizeof(uint8_t));
2487   solver->ante_tag = (uint8_t *) safe_malloc(n * sizeof(uint8_t));
2488   solver->ante_data = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
2489   solver->level = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
2490   solver->watch = (watch_t **) safe_malloc(n * 2 * sizeof(watch_t *));
2491 
2492   solver->occ = NULL;
2493   if (solver->preprocess) {
2494     solver->occ = (uint32_t *) safe_malloc(n * 2 * sizeof(uint32_t)); // one counter per literal
2495     solver->occ[0] = 0;  // for literal 0 = true
2496     solver->occ[1] = 0;  // for literal 1 = false
2497   }
2498 
2499   // variable 0: true
2500   solver->value[0] = VAL_TRUE;
2501   solver->value[1] = VAL_FALSE;
2502   solver->ante_tag[0] = ATAG_UNIT;
2503   solver->ante_data[0] = 0;
2504   solver->level[0] = 0;
2505   solver->watch[0] = NULL;
2506   solver->watch[1] = NULL;
2507 
2508   init_heap(&solver->heap, n, 1);
2509   init_stack(&solver->stack, n);
2510 
2511   solver->has_empty_clause = false;
2512   solver->units = 0;
2513   solver->binaries = 0;
2514   init_clause_pool(&solver->pool);
2515 
2516   init_clause_stack(&solver->stash);
2517 
2518   solver->conflict_tag = CTAG_NONE;
2519 
2520   init_params(&solver->params);
2521 
2522   init_stats(&solver->stats);
2523 
2524   solver->cidx_array = NULL;
2525 
2526   init_vector(&solver->buffer);
2527   init_vector(&solver->aux);
2528   init_gstack(&solver->gstack);
2529   init_tag_map(&solver->map, 0); // use default size
2530 
2531   init_clause_vector(&solver->saved_clauses);
2532 
2533   init_queue(&solver->lqueue);
2534   init_elim_heap(&solver->elim);
2535   init_queue(&solver->cqueue);
2536   init_vector(&solver->cvector);
2537   solver->scan_index = 0;
2538 
2539   init_vector(&solver->vertex_stack);
2540   init_gstack(&solver->dfs_stack);
2541   init_vector(&solver->subst_vars);
2542   init_vector(&solver->subst_units);
2543   solver->label = NULL;
2544   solver->visit = NULL;
2545 
2546   init_descriptors(&solver->descriptors);
2547   init_bgate_array(&solver->gates);
2548 
2549   solver->data = NULL;
2550 }
2551 
2552 
2553 /*
2554  * Set the verbosity level
2555  */
nsat_set_verbosity(sat_solver_t * solver,uint32_t level)2556 void nsat_set_verbosity(sat_solver_t *solver, uint32_t level) {
2557   solver->verbosity = level;
2558 }
2559 
2560 /*
2561  * Free memory
2562  */
delete_nsat_solver(sat_solver_t * solver)2563 void delete_nsat_solver(sat_solver_t *solver) {
2564   safe_free(solver->value);
2565   safe_free(solver->ante_tag);
2566   safe_free(solver->ante_data);
2567   safe_free(solver->level);
2568   delete_watch_vectors(solver->watch, solver->nliterals);
2569   safe_free(solver->watch);
2570 
2571   solver->value = NULL;
2572   solver->ante_tag = NULL;
2573   solver->ante_data = NULL;
2574   solver->level = NULL;
2575   solver->watch = NULL;
2576 
2577   if (solver->occ != NULL) {
2578     safe_free(solver->occ);
2579     solver->occ = NULL;
2580   }
2581 
2582   delete_heap(&solver->heap);
2583   delete_stack(&solver->stack);
2584   delete_clause_stack(&solver->stash);
2585   delete_clause_pool(&solver->pool);
2586 
2587   safe_free(solver->cidx_array);
2588   solver->cidx_array = NULL;
2589 
2590   delete_vector(&solver->buffer);
2591   delete_vector(&solver->aux);
2592   delete_gstack(&solver->gstack);
2593   delete_tag_map(&solver->map);
2594 
2595   delete_clause_vector(&solver->saved_clauses);
2596 
2597   delete_queue(&solver->lqueue);
2598   delete_elim_heap(&solver->elim);
2599   delete_queue(&solver->cqueue);
2600   delete_vector(&solver->cvector);
2601 
2602   delete_vector(&solver->vertex_stack);
2603   delete_gstack(&solver->dfs_stack);
2604   delete_vector(&solver->subst_vars);
2605   delete_vector(&solver->subst_units);
2606   if (solver->label != NULL) {
2607     safe_free(solver->label);
2608     safe_free(solver->visit);
2609     solver->label = NULL;
2610     solver->visit = NULL;
2611   }
2612 
2613   delete_descriptors(&solver->descriptors);
2614   delete_bgate_array(&solver->gates);
2615 
2616   close_datafile(solver);
2617 }
2618 
2619 
2620 /*
2621  * Reset: remove all variables and clauses
2622  * - reset heuristics parameters
2623  */
reset_nsat_solver(sat_solver_t * solver)2624 void reset_nsat_solver(sat_solver_t *solver) {
2625   solver->status = STAT_UNKNOWN;
2626   solver->decision_level = 0;
2627   solver->backtrack_level = 0;
2628   solver->nvars = 1;
2629   solver->nliterals = 2;
2630 
2631   reset_heap(&solver->heap);
2632   reset_stack(&solver->stack);
2633 
2634   solver->has_empty_clause = false;
2635   solver->units = 0;
2636   solver->binaries = 0;
2637   reset_clause_pool(&solver->pool);
2638 
2639   reset_clause_stack(&solver->stash);
2640 
2641   solver->conflict_tag = CTAG_NONE;
2642 
2643   init_stats(&solver->stats);
2644 
2645   safe_free(solver->cidx_array);
2646   solver->cidx_array = NULL;
2647 
2648   reset_vector(&solver->buffer);
2649   reset_vector(&solver->aux);
2650   reset_gstack(&solver->gstack);
2651   clear_tag_map(&solver->map);
2652 
2653   reset_clause_vector(&solver->saved_clauses);
2654 
2655   reset_queue(&solver->lqueue);
2656   reset_elim_heap(&solver->elim);
2657   reset_queue(&solver->cqueue);
2658   reset_vector(&solver->cvector);
2659 
2660   reset_vector(&solver->vertex_stack);
2661   reset_gstack(&solver->dfs_stack);
2662   reset_vector(&solver->subst_vars);
2663   reset_vector(&solver->subst_units);
2664   if (solver->label != NULL) {
2665     safe_free(solver->label);
2666     safe_free(solver->visit);
2667     solver->label = NULL;
2668     solver->visit = NULL;
2669   }
2670 
2671   reset_descriptors(&solver->descriptors);
2672   reset_bgate_array(&solver->gates);
2673 
2674   reset_datafile(solver);
2675 }
2676 
2677 
2678 
2679 /**************************
2680  *  HEURISTIC PARAMETERS  *
2681  *************************/
2682 
2683 /*
2684  * Clause activity decay: must be between 0 and 1.0
2685  * - smaller means faster decay
2686  */
nsat_set_clause_decay_factor(sat_solver_t * solver,float factor)2687 void nsat_set_clause_decay_factor(sat_solver_t *solver, float factor) {
2688   assert(0.0F < factor && factor < 1.0F);
2689   solver->params.inv_cla_decay = 1/factor;
2690 }
2691 
2692 /*
2693  * Randomness: the parameter is approximately the ratio of random
2694  * decisions.
2695  * - randomness = 0: no random decisions
2696  * - randomness = 1.0: all decisions are random
2697  */
nsat_set_randomness(sat_solver_t * solver,float randomness)2698 void nsat_set_randomness(sat_solver_t *solver, float randomness) {
2699   assert(0.0F <= randomness && randomness <= 1.0F);
2700   solver->params.randomness = (uint32_t)(randomness * VAR_RANDOM_SCALE);
2701 }
2702 
2703 /*
2704  * Set the prng seed
2705  */
nsat_set_random_seed(sat_solver_t * solver,uint32_t seed)2706 void nsat_set_random_seed(sat_solver_t *solver, uint32_t seed) {
2707   solver->params.seed = seed;
2708 }
2709 
2710 /*
2711  * LBD threshold for clause deletion. Clauses of lbd <= keep_lbd are not deleted.
2712  */
nsat_set_keep_lbd(sat_solver_t * solver,uint32_t threshold)2713 void nsat_set_keep_lbd(sat_solver_t *solver, uint32_t threshold) {
2714   solver->params.keep_lbd = threshold;
2715 }
2716 
2717 /*
2718  * Reduce fraction for clause deletion. f must be between 0 and 32.
2719  * Each call to reduce_learned_clause_set removes a fraction (f/32) of the clauses
2720  */
nsat_set_reduce_fraction(sat_solver_t * solver,uint32_t f)2721 void nsat_set_reduce_fraction(sat_solver_t *solver, uint32_t f) {
2722   assert(f <= 32);
2723   solver->params.reduce_fraction = f;
2724 }
2725 
2726 /*
2727  * Interval between two calls to reduce (number of conflicts)
2728  */
nsat_set_reduce_interval(sat_solver_t * solver,uint32_t n)2729 void nsat_set_reduce_interval(sat_solver_t *solver, uint32_t n) {
2730   solver->params.reduce_interval = n;
2731 }
2732 
2733 /*
2734  * Adjustment to the reduce interval (check init_reduce and done_reduce).
2735  */
nsat_set_reduce_delta(sat_solver_t * solver,uint32_t d)2736 void nsat_set_reduce_delta(sat_solver_t *solver, uint32_t d) {
2737   solver->params.reduce_delta = d;
2738 }
2739 
2740 /*
2741  * Minimal number of conflicts between two calls to restart
2742  */
nsat_set_restart_interval(sat_solver_t * solver,uint32_t n)2743 void nsat_set_restart_interval(sat_solver_t *solver, uint32_t n) {
2744   solver->params.restart_interval = n;
2745 }
2746 
2747 /*
2748  * Periodic check for switching to dive
2749  */
nsat_set_search_period(sat_solver_t * solver,uint32_t n)2750 void nsat_set_search_period(sat_solver_t *solver, uint32_t n) {
2751   solver->params.search_period = n;
2752 }
2753 
2754 /*
2755  * Counter used in determining when to switch
2756  */
nsat_set_search_counter(sat_solver_t * solver,uint32_t n)2757 void nsat_set_search_counter(sat_solver_t *solver, uint32_t n) {
2758   solver->params.search_counter = n;
2759 }
2760 
2761 
2762 /*
2763  * Stack clause threshold: learned clauses of LBD greater than threshold are
2764  * treated as temporary clauses (not stored in the clause database).
2765  */
nsat_set_stack_threshold(sat_solver_t * solver,uint32_t f)2766 void nsat_set_stack_threshold(sat_solver_t *solver, uint32_t f) {
2767   solver->params.stack_threshold = f;
2768 }
2769 
2770 
2771 /*
2772  * Dive bugdet
2773  */
nsat_set_dive_budget(sat_solver_t * solver,uint32_t n)2774 void nsat_set_dive_budget(sat_solver_t *solver, uint32_t n) {
2775   solver->params.diving_budget = n;
2776 }
2777 
2778 
2779 
2780 /*
2781  * PREPROCESSING PARAMETERS
2782  */
2783 
2784 /*
2785  * Subsumption limit: skip subsumption checks for a clause cls if that
2786  * would require visiting more than subsume_skip clauses.
2787  */
nsat_set_subsume_skip(sat_solver_t * solver,uint32_t limit)2788 void nsat_set_subsume_skip(sat_solver_t *solver, uint32_t limit) {
2789   solver->params.subsume_skip = limit;
2790 }
2791 
2792 /*
2793  * Var-elimination limit: if x has too many positive and negative occurrences,
2794  * we don't try to eliminate x.
2795  */
nsat_set_var_elim_skip(sat_solver_t * solver,uint32_t limit)2796 void nsat_set_var_elim_skip(sat_solver_t *solver, uint32_t limit) {
2797   solver->params.var_elim_skip = limit;
2798 }
2799 
2800 /*
2801  * Resolvent limit: if eliminating x would create a clause larger than
2802  * res_clause_limit, we keep x.
2803  */
nsat_set_res_clause_limit(sat_solver_t * solver,uint32_t limit)2804 void nsat_set_res_clause_limit(sat_solver_t *solver, uint32_t limit) {
2805   solver->params.res_clause_limit = limit;
2806 }
2807 
2808 
2809 /*
2810  * SIMPLIFY PARAMETERS
2811  */
nsat_set_simplify_interval(sat_solver_t * solver,uint32_t n)2812 void nsat_set_simplify_interval(sat_solver_t *solver, uint32_t n) {
2813   solver->params.simplify_interval = n;
2814 }
2815 
nsat_set_simplify_bin_delta(sat_solver_t * solver,uint32_t d)2816 void nsat_set_simplify_bin_delta(sat_solver_t *solver, uint32_t d) {
2817   solver->params.simplify_bin_delta = d;
2818 }
2819 
nsat_set_simplify_subst_delta(sat_solver_t * solver,uint32_t d)2820 void nsat_set_simplify_subst_delta(sat_solver_t *solver, uint32_t d) {
2821   solver->params.simplify_subst_delta = d;
2822 }
2823 
2824 
2825 
2826 /********************
2827  *  ADD VARIABLES   *
2828  *******************/
2829 
2830 /*
2831  * Extend data structures:
2832  * - new_size = new vsize for variable indexed arrays
2833  */
sat_solver_extend(sat_solver_t * solver,uint32_t new_size)2834 static void sat_solver_extend(sat_solver_t *solver, uint32_t new_size) {
2835   if (new_size > MAX_VARIABLES) {
2836     out_of_memory();
2837   }
2838 
2839   solver->vsize = new_size;
2840   solver->lsize = 2 * new_size;
2841 
2842   solver->value = (uint8_t *) safe_realloc(solver->value, new_size * 2 * sizeof(uint8_t));
2843   solver->ante_tag = (uint8_t *) safe_realloc(solver->ante_tag, new_size * sizeof(uint8_t));
2844   solver->ante_data = (uint32_t *) safe_realloc(solver->ante_data, new_size * sizeof(uint32_t));
2845   solver->level = (uint32_t *) safe_realloc(solver->level, new_size * sizeof(uint32_t));
2846   solver->watch = (watch_t **) safe_realloc(solver->watch, new_size * 2 * sizeof(watch_t *));
2847 
2848   if (solver->preprocess) {
2849     solver->occ = (uint32_t *) safe_realloc(solver->occ, new_size * 2 * sizeof(uint32_t));
2850   }
2851 
2852   extend_heap(&solver->heap, new_size);
2853   extend_stack(&solver->stack, new_size);
2854 }
2855 
2856 
2857 /*
2858  * Add n variables
2859  */
nsat_solver_add_vars(sat_solver_t * solver,uint32_t n)2860 void nsat_solver_add_vars(sat_solver_t *solver, uint32_t n) {
2861   uint32_t i, nv, new_size;
2862 
2863   nv = solver->nvars + n;
2864   if (nv  < n) {
2865     // arithmetic overflow: too many variables
2866     out_of_memory();
2867   }
2868 
2869   if (nv > solver->vsize) {
2870     new_size = solver->vsize + 1;
2871     new_size += new_size >> 1;
2872     if (new_size < nv) {
2873       new_size = nv;
2874     }
2875     sat_solver_extend(solver, new_size);
2876     assert(nv <= solver->vsize);
2877   }
2878 
2879   for (i=solver->nvars; i<nv; i++) {
2880     solver->value[pos_lit(i)] = VAL_UNDEF_FALSE;
2881     solver->value[neg_lit(i)] = VAL_UNDEF_TRUE;
2882     solver->ante_tag[i] = ATAG_NONE;
2883     solver->ante_data[i] = 0;
2884     solver->level[i] = UINT32_MAX;
2885     solver->watch[pos_lit(i)] = NULL;
2886     solver->watch[neg_lit(i)] = NULL;
2887   }
2888 
2889   if (solver->preprocess) {
2890     for (i=solver->nvars; i<nv; i++) {
2891       solver->occ[pos_lit(i)] = 0;
2892       solver->occ[neg_lit(i)] = 0;
2893     }
2894   }
2895 
2896   heap_add_vars(&solver->heap, nv);
2897 
2898   solver->nvars = nv;
2899   solver->nliterals = 2 * nv;
2900 }
2901 
2902 
2903 /*
2904  * Allocate and return a fresh Boolean variable
2905  */
nsat_solver_new_var(sat_solver_t * solver)2906 bvar_t nsat_solver_new_var(sat_solver_t *solver) {
2907   bvar_t x;
2908 
2909   x = solver->nvars;
2910   nsat_solver_add_vars(solver, 1);
2911   assert(solver->nvars == x + 1);
2912   return x;
2913 }
2914 
2915 
2916 /*
2917  * EXPERIMENTAL FUNCTIONS
2918  */
2919 
2920 /*
2921  * Set initial rank and branching polarity for variable x
2922  * - polarity: true means true is preferred
2923  */
nsat_solver_activate_var(sat_solver_t * solver,bvar_t x,uint32_t rank,bool polarity)2924 void nsat_solver_activate_var(sat_solver_t *solver, bvar_t x, uint32_t rank, bool polarity) {
2925   nvar_heap_t *heap;
2926 
2927   assert(0 <= x && x < solver->nvars);
2928 
2929   heap = &solver->heap;
2930   if (heap->heap_index[x] < 0) {
2931     heap->rank[x] = rank;
2932     heap_insert(heap, x);
2933   }
2934   if (polarity) {
2935     solver->value[pos_lit(x)] = VAL_UNDEF_TRUE;
2936     solver->value[neg_lit(x)] = VAL_UNDEF_FALSE;
2937   } else {
2938     solver->value[pos_lit(x)] = VAL_UNDEF_FALSE;
2939     solver->value[neg_lit(x)] = VAL_UNDEF_TRUE;
2940   }
2941 
2942   fprintf(stderr, "activate %"PRId32", polarity = %d\n", x, polarity);
2943 }
2944 
2945 
2946 /*
2947  * Mark variable x as a variable to keep: it will not be deleted during
2948  * preprocessing. By default, all variables are considered candidates for
2949  * elimination.
2950  */
nsat_solver_keep_var(sat_solver_t * solver,bvar_t x)2951 void nsat_solver_keep_var(sat_solver_t *solver, bvar_t x) {
2952   assert(0 <= x && x < solver->nvars);
2953   add_descriptor(&solver->descriptors, x, DTAG_TO_KEEP, 0);
2954   assert(bvar_to_keep(&solver->descriptors, x));
2955 }
2956 
2957 
2958 /*
2959  * Convert l to true_literal or false_literal if it's assigned.
2960  * Otherwise, return l.
2961  */
nsat_base_literal(const sat_solver_t * solver,literal_t l)2962 static literal_t nsat_base_literal(const sat_solver_t *solver, literal_t l) {
2963   bvar_t x;
2964 
2965   assert(solver->decision_level == 0);
2966 
2967   x = var_of(l);
2968   switch (solver->ante_tag[x]) {
2969   case ATAG_NONE:
2970   case ATAG_DECISION:
2971   case ATAG_SUBST:
2972   case ATAG_ELIM:
2973     // l is assigned to some random value
2974     return l;
2975 
2976   default:
2977     switch (lit_value(solver, l)) {
2978     case VAL_FALSE:
2979       l = false_literal;
2980       break;
2981 
2982     case VAL_TRUE:
2983       l = true_literal;
2984       break;
2985 
2986     default:
2987       break;
2988     }
2989 
2990     return l;
2991   }
2992 }
2993 
2994 
2995 /*
2996  * Add a definition for variable x.
2997  * There are two forms: binary and ternary definitions.
2998  *
2999  * A binary definition is x = (OP l1 l2) where l1 and l2 are literals
3000  * and OP is a binary operator defined by a truth table.
3001  *
3002  * A ternary definition is similar, but with three literals:
3003  * x = (OP l1 l2 l3).
3004  *
3005  * The truth table is defined by the  8 low-order bit of parameter b.
3006  * The conventions are the same as in new_gates.h.
3007  */
nsat_solver_add_def2(sat_solver_t * solver,bvar_t x,uint32_t b,literal_t l1,literal_t l2)3008 void nsat_solver_add_def2(sat_solver_t *solver, bvar_t x, uint32_t b, literal_t l1, literal_t l2) {
3009   ttbl_t tt;
3010   uint32_t i;
3011 
3012   assert(0 <= x && x < solver->nvars);
3013   assert(0 <= l1 && l1 <= solver->nliterals);
3014   assert(0 <= l2 && l2 <= solver->nliterals);
3015 
3016   tt.nvars = 2;
3017   tt.label[0] = nsat_base_literal(solver, l1);
3018   tt.label[1] = nsat_base_literal(solver, l2);
3019   tt.label[2] = null_bvar;
3020   tt.mask = (uint8_t) b;
3021   normalize_truth_table2(&tt);
3022 
3023   if (tt.nvars >= 2) {
3024     i = store_bgate(&solver->gates, &tt);
3025     add_descriptor(&solver->descriptors, x, DTAG_GATE, i);
3026   }
3027 }
3028 
nsat_solver_add_def3(sat_solver_t * solver,bvar_t x,uint32_t b,literal_t l1,literal_t l2,literal_t l3)3029 void nsat_solver_add_def3(sat_solver_t *solver, bvar_t x, uint32_t b, literal_t l1, literal_t l2, literal_t l3) {
3030   ttbl_t tt;
3031   uint32_t i;
3032 
3033   assert(0 <= x && x < solver->nvars);
3034   assert(0 <= l1 && l1 <= solver->nliterals);
3035   assert(0 <= l2 && l2 <= solver->nliterals);
3036   assert(0 <= l3 && l3 <= solver->nliterals);
3037 
3038   tt.nvars = 3;
3039   tt.label[0] = nsat_base_literal(solver, l1);
3040   tt.label[1] = nsat_base_literal(solver, l2);
3041   tt.label[2] = nsat_base_literal(solver, l3);
3042   tt.mask = (uint8_t) b;
3043   normalize_truth_table3(&tt);
3044 
3045   if (tt.nvars >= 2) {
3046     i = store_ternary_gate(&solver->gates, b, l1, l2, l3);
3047     add_descriptor(&solver->descriptors, x, DTAG_GATE, i);
3048   }
3049 }
3050 
3051 
3052 /*
3053  * Check whether x is a gate and return its truth-table in tt
3054  */
gate_for_bvar(const sat_solver_t * solver,bvar_t x,ttbl_t * tt)3055 static bool gate_for_bvar(const sat_solver_t *solver, bvar_t x, ttbl_t *tt) {
3056   uint32_t i;
3057 
3058   if (bvar_is_gate(&solver->descriptors, x)) {
3059     i = bvar_get_gate(&solver->descriptors, x);
3060     get_bgate(&solver->gates, i, tt);
3061     return true;
3062   }
3063 
3064   return false;
3065 }
3066 
3067 
3068 /*******************
3069  *  WATCH VECTORS  *
3070  ******************/
3071 
3072 /*
3073  * Encode l as a watch index
3074  */
lit2idx(literal_t l)3075 static inline uint32_t lit2idx(literal_t l) {
3076   return (l << 1) | 1;
3077 }
3078 
3079 /*
3080  * Converse: extract literal from index k
3081  */
idx2lit(uint32_t k)3082 static inline literal_t idx2lit(uint32_t k) {
3083   assert((k & 1) == 1);
3084   return k >> 1;
3085 }
3086 
3087 /*
3088  * Check whether k is a clause index: low-order bit is 0
3089  */
idx_is_clause(uint32_t k)3090 static inline bool idx_is_clause(uint32_t k) {
3091   return (k & 1) == 0;
3092 }
3093 
3094 /*
3095  * Check whether k is a literal index: low-order bit is 1
3096  */
idx_is_literal(uint32_t k)3097 static inline bool idx_is_literal(uint32_t k) {
3098   return (k & 1) == 1;
3099 }
3100 
3101 /*
3102  * Add a clause index to the watch vector for literal l
3103  * - l1 = blocker
3104  */
add_clause_watch(sat_solver_t * solver,literal_t l,cidx_t cidx,literal_t l1)3105 static inline void add_clause_watch(sat_solver_t *solver, literal_t l, cidx_t cidx, literal_t l1) {
3106   assert(l < solver->nliterals && l1 < solver->nliterals);
3107   add_watch2(solver->watch + l, cidx, l1);
3108 }
3109 
3110 /*
3111  * Add literal l1 to the watch vector for l
3112  */
add_literal_watch(sat_solver_t * solver,literal_t l,literal_t l1)3113 static inline void add_literal_watch(sat_solver_t *solver, literal_t l, literal_t l1) {
3114   assert(l < solver->nliterals);
3115   add_watch(solver->watch + l, lit2idx(l1));
3116 }
3117 
3118 
3119 /*
3120  * All clause index cidx in the watch vectors of literals lit[0 ... n-1]
3121  */
add_clause_all_watch(sat_solver_t * solver,uint32_t n,const literal_t * lit,cidx_t cidx)3122 static void add_clause_all_watch(sat_solver_t *solver, uint32_t n, const literal_t *lit, cidx_t cidx) {
3123   uint32_t i;
3124   literal_t l;
3125 
3126   for (i=0; i<n; i++) {
3127     l = lit[i];
3128     assert(l < solver->nliterals);
3129     add_watch(solver->watch + l, cidx);
3130   }
3131 }
3132 
3133 
3134 /*************************
3135  *  LITERAL ASSIGNMENT   *
3136  ***********************/
3137 
3138 /*
3139  * Assign literal l at base level
3140  */
assign_literal(sat_solver_t * solver,literal_t l)3141 static void assign_literal(sat_solver_t *solver, literal_t l) {
3142   bvar_t v;
3143 
3144 #if TRACE
3145   printf("---> Assigning literal %"PRIu32"\n", l);
3146   fflush(stdout);
3147 #endif
3148 
3149   assert(l < solver->nliterals);
3150   assert(lit_is_unassigned(solver, l));
3151   assert(solver->decision_level == 0);
3152 
3153   push_literal(&solver->stack, l);
3154 
3155   solver->value[l] = VAL_TRUE;
3156   solver->value[not(l)] = VAL_FALSE;
3157 
3158   v = var_of(not(l));
3159   // value of v = VAL_TRUE if l = pos_lit(v) or VAL_FALSE if l = neg_lit(v)
3160   //  solver->value[v] = VAL_TRUE ^ sign_of_lit(l);
3161   solver->ante_tag[v] = ATAG_UNIT;
3162   solver->ante_data[v] = 0;
3163   solver->level[v] = 0;
3164 
3165   assert(lit_is_true(solver, l));
3166 }
3167 
3168 
3169 /* static inline int32_t l2dimacs(literal_t l) { */
3170 /*   int x = var_of(l) + 1; */
3171 /*   return is_pos(l) ? x : - x; */
3172 /* } */
3173 
3174 /*
3175  * Decide literal: increase decision level then
3176  * assign literal l to true and push it on the stack
3177  */
nsat_decide_literal(sat_solver_t * solver,literal_t l)3178 static void nsat_decide_literal(sat_solver_t *solver, literal_t l) {
3179   uint32_t k;
3180   bvar_t v;
3181 
3182   assert(l < solver->nliterals);
3183   assert(lit_is_unassigned(solver, l));
3184 
3185   solver->stats.decisions ++;
3186 
3187   // Increase decision level
3188   k = solver->decision_level + 1;
3189   solver->decision_level = k;
3190   if (solver->stack.nlevels <= k) {
3191     increase_stack_levels(&solver->stack);
3192   }
3193   solver->stack.level_index[k] = solver->stack.top;
3194   if (solver->stash.nlevels <= k) {
3195     increase_clause_stack_levels(&solver->stash);
3196   }
3197   solver->stash.level[k] = solver->stash.top;
3198 
3199   push_literal(&solver->stack, l);
3200 
3201   solver->value[l] = VAL_TRUE;
3202   solver->value[not(l)] = VAL_FALSE;
3203 
3204   v = var_of(not(l));
3205   solver->ante_tag[v] = ATAG_DECISION;
3206   solver->ante_data[v] = 0; // not used
3207   solver->level[v] = k;
3208 
3209   assert(lit_is_true(solver, l));
3210 
3211   //  fprintf(stderr, "decide %"PRId32"\n", l2dimacs(l));
3212 #if TRACE
3213   printf("---> DPLL:   Decision: literal %"PRIu32", decision level = %"PRIu32"\n", l, k);
3214   fflush(stdout);
3215 #endif
3216 }
3217 
3218 
3219 /*
3220  * Propagated literal: tag = antecedent tag, data = antecedent data
3221  */
implied_literal(sat_solver_t * solver,literal_t l,antecedent_tag_t tag,uint32_t data)3222 static void implied_literal(sat_solver_t *solver, literal_t l, antecedent_tag_t tag, uint32_t data) {
3223   bvar_t v;
3224 
3225   assert(l < solver->nliterals);
3226   assert(lit_is_unassigned(solver, l));
3227 
3228   solver->stats.propagations ++;
3229 
3230   push_literal(&solver->stack, l);
3231 
3232   solver->value[l] = VAL_TRUE;
3233   solver->value[not(l)] = VAL_FALSE;
3234 
3235   v = var_of(not(l));
3236   solver->ante_tag[v] = tag;
3237   solver->ante_data[v] = data;
3238   solver->level[v] = solver->decision_level;
3239 
3240   assert(lit_is_true(solver, l));
3241 }
3242 
3243 
3244 /*
3245  * Literal l implied by clause cidx
3246  */
clause_propagation(sat_solver_t * solver,literal_t l,cidx_t cidx)3247 static void clause_propagation(sat_solver_t *solver, literal_t l, cidx_t cidx) {
3248   assert(good_clause_idx(&solver->pool, cidx));
3249 
3250   implied_literal(solver, l, ATAG_CLAUSE, cidx);
3251 
3252 #if TRACE
3253   printf("\n---> DPLL:   Implied literal %"PRIu32", by clause %"PRIu32", decision level = %"PRIu32"\n", l, cidx, solver->decision_level);
3254   fflush(stdout);
3255 #endif
3256 }
3257 
3258 
3259 /*
3260  * Literal l implied by a binary clause (of the form { l, l0 }})
3261  * - l0 = other literal in the clause
3262  */
binary_clause_propagation(sat_solver_t * solver,literal_t l,literal_t l0)3263 static void binary_clause_propagation(sat_solver_t *solver, literal_t l, literal_t l0) {
3264   assert(l0 < solver->nliterals);
3265 
3266   implied_literal(solver, l, ATAG_BINARY, l0);
3267 
3268 #if TRACE
3269   printf("\n---> DPLL:   Implied literal %"PRIu32", by literal %"PRIu32", decision level = %"PRIu32"\n", l, l0, solver->decision_level);
3270   fflush(stdout);
3271 #endif
3272 }
3273 
3274 
3275 #if USE_DIVING
3276 /*
3277  * Literal l implied by stacked clause cidx
3278  */
stacked_clause_propagation(sat_solver_t * solver,literal_t l,cidx_t cidx)3279 static void stacked_clause_propagation(sat_solver_t *solver, literal_t l, cidx_t cidx) {
3280   implied_literal(solver, l, ATAG_STACKED, cidx);
3281 
3282 #if TRACE
3283   printf("\n---> DPLL:   Implied literal %"PRIu32", by stacked clause %"PRIu32", decision level = %"PRIu32"\n", l, cidx, solver->decision_level);
3284   fflush(stdout);
3285 #endif
3286 }
3287 
3288 #endif
3289 
3290 
3291 /***********************
3292  *  OCCURRENCE COUNTS  *
3293  **********************/
3294 
3295 /*
3296  * Scan clause stored in lit[0 ... n-1] and increase occurrence counts
3297  * for these literals.
3298  */
increase_occurrence_counts(sat_solver_t * solver,uint32_t n,const literal_t * lit)3299 static void increase_occurrence_counts(sat_solver_t *solver, uint32_t n, const literal_t *lit) {
3300   uint32_t i;
3301 
3302   for (i=0; i<n; i++) {
3303     solver->occ[lit[i]] ++;
3304   }
3305 }
3306 
3307 
3308 
3309 /**********************
3310  *  CLAUSE ADDITION   *
3311  *********************/
3312 
3313 /*
3314  * Add the empty clause
3315  */
add_empty_clause(sat_solver_t * solver)3316 static void add_empty_clause(sat_solver_t *solver) {
3317   solver->has_empty_clause = true;
3318   solver->status = STAT_UNSAT;
3319 }
3320 
3321 
3322 /*
3323  * Add unit clause { l }: push l on the assignment stack
3324  */
add_unit_clause(sat_solver_t * solver,literal_t l)3325 static void add_unit_clause(sat_solver_t *solver, literal_t l) {
3326   assert(lit_is_unassigned(solver, l));
3327   assign_literal(solver, l);
3328   solver->units ++;
3329 }
3330 
3331 
3332 /*
3333  * Add clause { l0, l1 }
3334  */
add_binary_clause(sat_solver_t * solver,literal_t l0,literal_t l1)3335 static void add_binary_clause(sat_solver_t *solver, literal_t l0, literal_t l1) {
3336   solver->binaries ++;
3337   add_literal_watch(solver, l0, l1);
3338   add_literal_watch(solver, l1, l0);
3339 }
3340 
3341 
3342 /*
3343  * Add an n-literal clause
3344  * - n must be at least 2
3345  * - if solver->preprocess is true, add the new clause to all occurrence lists
3346  * - otherwise, pick lit[0] and lit[1] as watch literals
3347  */
add_large_clause(sat_solver_t * solver,uint32_t n,const literal_t * lit)3348 static void add_large_clause(sat_solver_t *solver, uint32_t n, const literal_t *lit) {
3349   cidx_t cidx;
3350 
3351   assert(n >= 2);
3352 
3353 #ifndef NDEBUG
3354   // check that all literals are valid
3355   for (uint32_t i=0; i<n; i++) {
3356     assert(lit[i] < solver->nliterals);
3357   }
3358 #endif
3359 
3360   cidx = clause_pool_add_problem_clause(&solver->pool, n, lit);
3361   if (solver->preprocess) {
3362     add_clause_all_watch(solver, n, lit, cidx);
3363     set_clause_signature(&solver->pool, cidx);
3364   } else {
3365     add_clause_watch(solver, lit[0], cidx, lit[1]);
3366     add_clause_watch(solver, lit[1], cidx, lit[0]);
3367   }
3368 }
3369 
3370 
3371 /*
3372  * Simplify the clause then add it
3373  * - n = number of literals
3374  * - l = array of n literals
3375  * - the array is modified
3376  */
nsat_solver_simplify_and_add_clause(sat_solver_t * solver,uint32_t n,literal_t * lit)3377 void nsat_solver_simplify_and_add_clause(sat_solver_t *solver, uint32_t n, literal_t *lit) {
3378   uint32_t i, j;
3379   literal_t l, l_aux;
3380 
3381   if (n == 0) {
3382     add_empty_clause(solver);
3383     return;
3384   }
3385 
3386   /*
3387    * Remove duplicates and check for opposite literals l, not(l)
3388    * (sorting ensure that not(l) is just after l)
3389    */
3390   int_array_sort(lit, n);
3391   l = lit[0];
3392   j = 1;
3393   for (i=1; i<n; i++) {
3394     l_aux = lit[i];
3395     if (l_aux != l) {
3396       if (l_aux == not(l)) return; // true clause
3397       lit[j] = l_aux;
3398       l = l_aux;
3399       j ++;
3400     }
3401   }
3402   n = j; // new clause size
3403 
3404   /*
3405    * Remove false literals/check for a true literal
3406    */
3407   j = 0;
3408   for (i=0; i<n; i++) {
3409     l = lit[i];
3410     switch (lit_value(solver, l)) {
3411     case VAL_FALSE:
3412       break;
3413     case VAL_UNDEF_FALSE :
3414     case VAL_UNDEF_TRUE :
3415       lit[j] = l;
3416       j++;
3417       break;
3418     default: // true literal, so the clause is true
3419       return;
3420     }
3421   }
3422   n = j; // new clause size
3423 
3424 
3425   /*
3426    * Add the clause lit[0 ... n-1]
3427    */
3428   if (n == 0) {
3429     add_empty_clause(solver);
3430   } else if (n == 1) {
3431     add_unit_clause(solver, lit[0]);
3432   } else if (n == 2 && !solver->preprocess) {
3433     add_binary_clause(solver, lit[0], lit[1]);
3434   } else {
3435     add_large_clause(solver, n, lit);
3436   }
3437 
3438   if (solver->preprocess) {
3439     increase_occurrence_counts(solver, n, lit);
3440   }
3441 }
3442 
3443 
3444 
3445 /****************************
3446  *  VARIABLE SUBSTITUTION   *
3447  ***************************/
3448 
3449 /*
3450  * Check whether variable x is eliminated (i.e., tag = PURE or ELIM or SUBST)
3451  */
var_is_eliminated(const sat_solver_t * solver,bvar_t x)3452 static inline bool var_is_eliminated(const sat_solver_t *solver, bvar_t x) {
3453   assert(x < solver->nvars);
3454   return solver->ante_tag[x] >= ATAG_PURE;
3455 }
3456 
3457 
3458 /*
3459  * Check whether variable x is active (i.e., not assigned at level 0) and not eliminated
3460  */
var_is_active(const sat_solver_t * solver,bvar_t x)3461 static bool var_is_active(const sat_solver_t *solver, bvar_t x) {
3462   return var_is_unassigned(solver, x) & ! var_is_eliminated(solver, x);
3463 }
3464 
3465 /*
3466  * Same thing for literal l
3467  */
lit_is_eliminated(const sat_solver_t * solver,literal_t l)3468 static inline bool lit_is_eliminated(const sat_solver_t *solver, literal_t l) {
3469   return var_is_eliminated(solver, var_of(l));
3470 }
3471 
lit_is_active(const sat_solver_t * solver,literal_t l)3472 static inline bool lit_is_active(const sat_solver_t *solver, literal_t l) {
3473   return var_is_active(solver, var_of(l));
3474 }
3475 
3476 
3477 /*
3478  * Literal that replaces l.
3479  * - var_of(l) must be marked as substituted variable.
3480  * - if l is pos_lit(x) then subst(l) is ante_data[x]
3481  * - if l is neg_lit(x) then subst(l) is not(ante_data[x])
3482  * In both cases, subst(l) is ante_data[x] ^ sign_of_lit(l)
3483  */
3484 #ifndef NDEBUG
base_subst(const sat_solver_t * solver,literal_t l)3485 static inline literal_t base_subst(const sat_solver_t *solver, literal_t l) {
3486   assert(l < solver->nliterals && solver->ante_tag[var_of(l)] == ATAG_SUBST);
3487   return solver->ante_data[var_of(l)] ^ sign_of_lit(l);
3488 }
3489 #endif
3490 
3491 #if 0
3492 /*
3493  * Substitution for l:
3494  * - if l is not replaced by anything, return l
3495  * - otherwise return subst[l]
3496  */
3497 static literal_t lit_subst(const sat_solver_t *solver, literal_t l) {
3498   assert(l < solver->nliterals);
3499 
3500   if (solver->ante_tag[var_of(l)] == ATAG_SUBST) {
3501     l = solver->ante_data[var_of(l)] ^ sign_of_lit(l);
3502   }
3503   return l;
3504 }
3505 #endif
3506 
3507 /*
3508  * Full substitution: follow the substitution chain
3509  * - if l is not replaced by anything, return l
3510  * - otherwise, replace l by subst(l) and iterate
3511  */
full_lit_subst(const sat_solver_t * solver,literal_t l)3512 static literal_t full_lit_subst(const sat_solver_t *solver, literal_t l) {
3513   assert(l < solver->nliterals);
3514 
3515   while (solver->ante_tag[var_of(l)] == ATAG_SUBST) {
3516     l = solver->ante_data[var_of(l)] ^ sign_of_lit(l);
3517   }
3518   return l;
3519 }
3520 
full_var_subst(const sat_solver_t * solver,bvar_t x)3521 static literal_t full_var_subst(const sat_solver_t *solver, bvar_t x) {
3522   assert(x < solver->nvars);
3523   return full_lit_subst(solver, pos_lit(x));
3524 }
3525 
3526 
3527 /*
3528  * Store subst[l1] := l2 + store the eliminated variable (i.e., var_of(l1))
3529  * into the subst_var vector
3530  */
set_lit_subst(sat_solver_t * solver,literal_t l1,literal_t l2)3531 static void set_lit_subst(sat_solver_t *solver, literal_t l1, literal_t l2) {
3532   bvar_t x;
3533 
3534   x = var_of(l1);
3535   assert(! var_is_eliminated(solver, x));
3536 
3537   solver->stats.subst_vars ++;
3538   solver->ante_tag[x] = ATAG_SUBST;
3539   solver->ante_data[x] = l2 ^ sign_of_lit(l1);
3540 
3541   vector_push(&solver->subst_vars, x);
3542 }
3543 
3544 
3545 /**********************************
3546  *  ADDITION OF LEARNED CLAUSES   *
3547  *********************************/
3548 
3549 /*
3550  * Rescale the activity of all the learned clauses.
3551  * (divide all the activities by CLAUSE_ACTIVITY_THRESHOLD).
3552  */
rescale_clause_activities(sat_solver_t * solver)3553 static void rescale_clause_activities(sat_solver_t *solver) {
3554   cidx_t cidx, end;
3555 
3556   end = solver->pool.size;
3557   cidx = clause_pool_first_learned_clause(&solver->pool);
3558   while (cidx < end) {
3559     multiply_learned_clause_activity(&solver->pool, cidx, INV_CLAUSE_ACTIVITY_THRESHOLD);
3560     cidx = clause_pool_next_clause(&solver->pool, cidx);
3561   }
3562   solver->cla_inc *= INV_CLAUSE_ACTIVITY_THRESHOLD;
3563 }
3564 
3565 
3566 /*
3567  * Increase the activity of a learned clause.
3568  * - cidx = its index
3569  */
increase_clause_activity(sat_solver_t * solver,cidx_t cidx)3570 static void increase_clause_activity(sat_solver_t *solver, cidx_t cidx) {
3571   increase_learned_clause_activity(&solver->pool, cidx, solver->cla_inc);
3572   if (get_learned_clause_activity(&solver->pool, cidx) > CLAUSE_ACTIVITY_THRESHOLD) {
3573     rescale_clause_activities(solver);
3574   }
3575 }
3576 
3577 /*
3578  * Decay
3579  */
decay_clause_activities(sat_solver_t * solver)3580 static inline void decay_clause_activities(sat_solver_t *solver) {
3581   solver->cla_inc *= solver->params.inv_cla_decay;
3582 }
3583 
3584 /*
3585  * Add an array of literals as a new learned clause
3586  *
3587  * Preconditions:
3588  * - n must be at least 2.
3589  * - lit[0] must be the literal of highest decision level in the clause.
3590  * - lit[1] must be a literal with second highest decision level
3591  */
add_learned_clause(sat_solver_t * solver,uint32_t n,const literal_t * lit)3592 static cidx_t add_learned_clause(sat_solver_t *solver, uint32_t n, const literal_t *lit) {
3593   cidx_t cidx;
3594 
3595   assert(n > 2);
3596 
3597   cidx = clause_pool_add_learned_clause(&solver->pool, n, lit);
3598   set_learned_clause_activity(&solver->pool, cidx, solver->cla_inc);
3599   add_clause_watch(solver, lit[0], cidx, lit[1]);
3600   add_clause_watch(solver, lit[1], cidx, lit[0]);
3601 
3602   return cidx;
3603 }
3604 
3605 
3606 
3607 /****************
3608  *  CLAUSE LBD  *
3609  ***************/
3610 
3611 /*
3612  * The Literal-Block Distance is a heuristic estimate of the usefulness
3613  * of a learned clause. Clauses with low LBD are better.
3614  * The LBD is the number of distinct decision levels among the literals
3615  * in a clause.
3616  *
3617  * Since backtracking does not clear solver->level[x], we compute the
3618  * LBD of a learned clause even if some of its literals are not
3619  * currently assigned.  If a literal l in the clause is not currently
3620  * assigned, then solver->level[var_of(l)] is the decision level of l,
3621  * at the last time l was assigned.
3622  */
3623 
3624 /*
3625  * Decision level of literal l
3626  */
d_level(const sat_solver_t * solver,literal_t l)3627 static inline uint32_t d_level(const sat_solver_t *solver, literal_t l) {
3628   return solver->level[var_of(l)];
3629 }
3630 
3631 /*
3632  * The following function computes the LBD of a clause:
3633  * - n = number of literals
3634  * - lit = array of n literals
3635  */
clause_lbd(sat_solver_t * solver,uint32_t n,const literal_t * lit)3636 static uint32_t clause_lbd(sat_solver_t *solver, uint32_t n, const literal_t *lit) {
3637   tag_map_t *map;
3638   uint32_t i, r;
3639 
3640   map = &solver->map;
3641   for (i=0; i<n; i++) {
3642     tag_map_write(map, d_level(solver, lit[i]), 1);
3643   }
3644   r = tag_map_size(map);
3645   clear_tag_map(map);
3646 
3647   return r;
3648 }
3649 
3650 
3651 /*
3652  * Check whether the LBD of a clause is no more than k
3653  */
clause_lbd_le(sat_solver_t * solver,uint32_t n,const literal_t * lit,uint32_t k)3654 static bool clause_lbd_le(sat_solver_t *solver, uint32_t n, const literal_t *lit, uint32_t k) {
3655   tag_map_t *map;
3656   uint32_t i;
3657   bool result;
3658 
3659   result = true;
3660   map = &solver->map;
3661   for (i=0; i<n; i++) {
3662     tag_map_write(map, d_level(solver, lit[i]), 1);
3663     if (tag_map_size(map) > k) {
3664       result = false;
3665       break;
3666     }
3667   }
3668   clear_tag_map(map);
3669 
3670   return result;
3671 }
3672 
3673 
3674 /************************
3675  *  GARBAGE COLLECTION  *
3676  ***********************/
3677 
3678 /*
3679  * Garbage collection compacts the clause pool by removing padding
3680  * blocks. There are two variants: either compact the whole pool or
3681  * just the learned clauses. We use a base_idx as starting point for
3682  * deletion. The base_idx is either 0 (all the clauses) or
3683  * pool->learned (only the learned clauses).
3684  */
3685 
3686 /*
3687  * Remove all clause indices >= base_idx from w
3688  */
watch_vector_remove_clauses(watch_t * w,cidx_t base_idx)3689 static void watch_vector_remove_clauses(watch_t *w, cidx_t base_idx) {
3690   uint32_t i, j, k, n;
3691 
3692   assert(w != NULL);
3693   n = w->size;
3694   j = 0;
3695   i = 0;
3696   while (i<n) {
3697     k = w->data[i];
3698     if (idx_is_literal(k)) {
3699       w->data[j] = k;
3700       j ++;
3701       i ++;
3702     } else {
3703       if (k < base_idx) {
3704         w->data[j] = k;
3705         w->data[j+1] = w->data[i+1];
3706         j += 2;
3707       }
3708       i += 2;
3709     }
3710   }
3711   w->size = j;
3712 }
3713 
3714 /*
3715  * Prepare for clause deletion and compaction:
3716  * - go through all the watch vectors are remove all clause indices >= base_idx
3717  */
prepare_watch_vectors(sat_solver_t * solver,cidx_t base_idx)3718 static void prepare_watch_vectors(sat_solver_t *solver, cidx_t base_idx) {
3719   uint32_t i, n;
3720   watch_t *w;
3721 
3722   n = solver->nliterals;
3723   for (i=0; i<n; i++) {
3724     w = solver->watch[i];
3725     if (w != NULL) {
3726       watch_vector_remove_clauses(w, base_idx);
3727     }
3728   }
3729 }
3730 
3731 /*
3732  * Mark all the antecedent clauses of idx >= base_idx
3733  */
mark_antecedent_clauses(sat_solver_t * solver,cidx_t base_idx)3734 static void mark_antecedent_clauses(sat_solver_t *solver, cidx_t base_idx) {
3735   uint32_t i, n;
3736   bvar_t x;
3737   cidx_t cidx;
3738 
3739   n = solver->stack.top;
3740   for (i=0; i<n; i++) {
3741     x = var_of(solver->stack.lit[i]);
3742     assert(var_is_assigned(solver, x));
3743     if (solver->ante_tag[x] == ATAG_CLAUSE) {
3744       cidx = solver->ante_data[x];
3745       if (cidx >= base_idx) {
3746         mark_clause(&solver->pool, cidx);
3747       }
3748     }
3749   }
3750 }
3751 
3752 /*
3753  * Restore antecedent when clause cidx is moved to new_idx
3754  * - this is called before the move.
3755  */
restore_clause_antecedent(sat_solver_t * solver,cidx_t cidx,cidx_t new_idx)3756 static void restore_clause_antecedent(sat_solver_t *solver, cidx_t cidx, cidx_t new_idx) {
3757   bvar_t x;
3758 
3759   x = var_of(first_literal_of_clause(&solver->pool, cidx));
3760   assert(var_is_assigned(solver, x) && solver->ante_tag[x] == ATAG_CLAUSE &&
3761          solver->ante_data[x] == cidx);
3762   solver->ante_data[x] = new_idx;
3763 }
3764 
3765 /*
3766  * Move clause from src_idx to dst_idx
3767  * - requires dst_idx < src_idx
3768  * - this copies header + literals
3769  * - n = length of the source clause
3770  */
clause_pool_move_clause(clause_pool_t * pool,cidx_t dst_idx,cidx_t src_idx,uint32_t n)3771 static void clause_pool_move_clause(clause_pool_t *pool, cidx_t dst_idx, cidx_t src_idx, uint32_t n) {
3772   uint32_t i;
3773 
3774   assert(dst_idx < src_idx);
3775   for (i=0; i<n+2; i++) {
3776     pool->data[dst_idx + i] = pool->data[src_idx + i];
3777   }
3778 }
3779 
3780 /*
3781  * Compact the pool:
3782  * - remove all padding blocks
3783  * - cidx = where to start = base_idx
3784  *
3785  * For every clause that's marked and moved, restore the antecedent data.
3786  */
compact_clause_pool(sat_solver_t * solver,cidx_t cidx)3787 static void compact_clause_pool(sat_solver_t *solver, cidx_t cidx) {
3788   clause_pool_t *pool;
3789   uint32_t k, n, end;
3790   cidx_t i;
3791 
3792   pool = &solver->pool;
3793 
3794   assert(clause_pool_invariant(pool));
3795 
3796   i = cidx;
3797   end = pool->learned;
3798   for (k=0; k<2; k++) {
3799     /*
3800      * First iteration: deal with problem clauses (or do nothing)
3801      * Second iteration: deal with learned clauses.
3802      */
3803     while (cidx < end) {
3804       n = pool->data[cidx];
3805       if (n == 0) {
3806         // padding block: skip it
3807         n = padding_length(pool, cidx);
3808         cidx += n;
3809         assert(pool->padding >= n);
3810         pool->padding -= n;
3811       } else {
3812         // keep the clause: store it at index i
3813         assert(i <= cidx);
3814         if ((n & CLAUSE_MARK) != 0) {
3815           // marked clause: restore the antecedent data
3816           // and remove the mark
3817           n &= ~CLAUSE_MARK;
3818           pool->data[cidx] = n;
3819           restore_clause_antecedent(solver, cidx, i);
3820         }
3821         if (i < cidx) {
3822           clause_pool_move_clause(pool, i, cidx, n);
3823         }
3824         i += full_length(n);
3825         cidx += full_length(n);;
3826       }
3827     }
3828     if (k == 0) {
3829       assert(end == pool->learned);
3830       if (i < pool->learned) {
3831         pool->learned = i;
3832       }
3833       end = pool->size; // prepare for next iteration
3834     }
3835   }
3836 
3837   assert(end == pool->size);
3838   pool->size = i;
3839   pool->available = pool->capacity - i;
3840 
3841   assert(clause_pool_invariant(pool));
3842 }
3843 
3844 /*
3845  * Restore the watch vectors:
3846  * - scan the clauses starting from index cidx
3847  *   and add them to the watch vectors
3848  */
restore_watch_vectors(sat_solver_t * solver,cidx_t cidx)3849 static void restore_watch_vectors(sat_solver_t *solver, cidx_t cidx) {
3850   literal_t l0, l1;
3851   cidx_t end;
3852 
3853   end = solver->pool.size;
3854   while (cidx < end) {
3855     l0 = first_literal_of_clause(&solver->pool, cidx);
3856     l1 = second_literal_of_clause(&solver->pool, cidx);
3857     add_clause_watch(solver, l0, cidx, l1);
3858     add_clause_watch(solver, l1, cidx, l0);
3859     cidx = clause_pool_next_clause(&solver->pool, cidx);
3860   }
3861 }
3862 
3863 /*
3864  * Garbage collection:
3865  * - this removes dead clauses from the pool and from the watch vectors
3866  * - base_index = either 0 to go through all clauses
3867  *   or solver->pool.learned to cleanup only the learned clauses.
3868  *
3869  * Flag 'watches_ready' means that the watch vectors don't contain
3870  * any clause idx. So we can skip the prepare_watch_vectors step.
3871  */
collect_garbage(sat_solver_t * solver,cidx_t base_index,bool watches_ready)3872 static void collect_garbage(sat_solver_t *solver, cidx_t base_index, bool watches_ready) {
3873   check_clause_pool_counters(&solver->pool);      // DEBUG
3874   mark_antecedent_clauses(solver, base_index);
3875   if (! watches_ready) {
3876     prepare_watch_vectors(solver, base_index);
3877   }
3878   compact_clause_pool(solver, base_index);
3879   check_clause_pool_learned_index(&solver->pool); // DEBUG
3880   check_clause_pool_counters(&solver->pool);      // DEBUG
3881   restore_watch_vectors(solver, base_index);
3882 }
3883 
3884 
3885 /*************
3886  *  REPORTS  *
3887  ************/
3888 
3889 /*
3890  * Number of active variables (i.e., not assigned and not removed by
3891  * substitution).
3892  */
num_active_vars(const sat_solver_t * solver)3893 static uint32_t num_active_vars(const sat_solver_t *solver) {
3894   uint32_t c, i, n;
3895 
3896   c = 0;
3897   n = solver->nvars;
3898   for (i=0; i<n; i++) {
3899     c += var_is_active(solver, i);
3900   }
3901   return c;
3902 }
3903 
3904 
3905 /*
3906  * Statistics produced:
3907  * - a four-character string identify the operation
3908  * - number of conflicts
3909  * - number of restarts
3910  * - average level after conflict resolution (level_ema)
3911  * - number of active variables
3912  * - binary and problem clauses
3913  * - average glue score for learned clauses (slow_ema)
3914  * - average size of learned clauses
3915  * - number of learned clauses
3916  */
report(sat_solver_t * solver,const char * code)3917 static void report(sat_solver_t *solver, const char *code) {
3918   double lits_per_clause, slow, lev;
3919   uint32_t vars;
3920 
3921   if (solver->verbosity >= 2) {
3922     if (solver->reports == 0) {
3923       fprintf(stderr, "c\n");
3924       fprintf(stderr, "c                        level   max  |                    prob.  |   learned  lbd\n");
3925       fprintf(stderr, "c        confl.  starts   ema   depth |    vars     bins  clauses |   clauses  ema   lits/cls\n");
3926       fprintf(stderr, "c\n");
3927     }
3928     solver->reports ++;
3929     solver->reports &= 31;
3930 
3931     lits_per_clause = 0.0;
3932     if (solver->pool.num_learned_clauses > 0) {
3933       lits_per_clause = ((double) solver->pool.num_learned_literals) / solver->pool.num_learned_clauses;
3934     }
3935     slow = ((double) solver->slow_ema)/4.3e9;
3936     lev = ((double) solver->level_ema)/4.3e9;
3937 
3938     if (solver->decision_level == 0) {
3939       vars = num_active_vars(solver);
3940       fprintf(stderr, "c %4s %8"PRIu64" %7"PRIu32" %6.2f %6"PRIu32" | %7"PRIu32" %8"PRIu32" %8"PRIu32" | %8"PRIu32" %6.2f %6.2f\n",
3941 	      code, solver->stats.conflicts, solver->stats.starts, lev, solver->max_depth,
3942 	      vars, solver->binaries, solver->pool.num_prob_clauses,
3943 	      solver->pool.num_learned_clauses, slow, lits_per_clause);
3944     } else {
3945       fprintf(stderr, "c %4s %8"PRIu64" %7"PRIu32" %6.2f %6"PRIu32" |         %8"PRIu32" %8"PRIu32" | %8"PRIu32" %6.2f %6.2f\n",
3946 	      code, solver->stats.conflicts, solver->stats.starts, lev, solver->max_depth,
3947 	      solver->binaries, solver->pool.num_prob_clauses,
3948 	      solver->pool.num_learned_clauses, slow, lits_per_clause);
3949     }
3950     solver->max_depth = 0;
3951   }
3952 }
3953 
3954 
3955 /*********************************
3956  *  DELETION OF LEARNED CLAUSES  *
3957  ********************************/
3958 
3959 /*
3960  * Allocate the internal cidx_array for n clauses
3961  * - n must be positive
3962  */
alloc_cidx_array(sat_solver_t * solver,uint32_t n)3963 static void alloc_cidx_array(sat_solver_t *solver, uint32_t n) {
3964   assert(solver->cidx_array == NULL && n > 0);
3965   solver->cidx_array = (cidx_t *) safe_malloc(n * sizeof(cidx_t));
3966 }
3967 
3968 /*
3969  * Delete the array
3970  */
free_cidx_array(sat_solver_t * solver)3971 static void free_cidx_array(sat_solver_t *solver) {
3972   assert(solver->cidx_array != NULL);
3973   safe_free(solver->cidx_array);
3974   solver->cidx_array = NULL;
3975 }
3976 
3977 /*
3978  * Check whether clause cidx is used as an antecedent.
3979  * (This means that it can't be deleted).
3980  */
clause_is_locked(const sat_solver_t * solver,cidx_t cidx)3981 static bool clause_is_locked(const sat_solver_t *solver, cidx_t cidx) {
3982   bvar_t x0;
3983 
3984   x0 = var_of(first_literal_of_clause(&solver->pool, cidx));
3985   return solver->ante_tag[x0] == ATAG_CLAUSE &&
3986     solver->ante_data[x0] == cidx && var_is_assigned(solver, x0);
3987 }
3988 
3989 
3990 /*
3991  * Check whether clause cidx should be kept
3992  * - heuristic: the clause is considered precious if its LDB is 4 or less
3993  * - this can be changed by setting keep_lbd to something other than 4.
3994  */
clause_is_precious(sat_solver_t * solver,cidx_t cidx)3995 static bool clause_is_precious(sat_solver_t *solver, cidx_t cidx) {
3996   uint32_t n, k;
3997 
3998   k = solver->params.keep_lbd;
3999   n = clause_length(&solver->pool, cidx);
4000   return n <= k || clause_lbd_le(solver, n, clause_literals(&solver->pool, cidx), k);
4001 }
4002 
4003 /*
4004  * Collect learned clauses indices into solver->cidx_array
4005  * - initialize the array with size = number of learned clauses
4006  * - store all clauses that are not locked and not precious into the array
4007  * - return the number of clauses collected
4008  */
collect_learned_clauses(sat_solver_t * solver)4009 static uint32_t collect_learned_clauses(sat_solver_t *solver) {
4010   cidx_t *a;
4011   cidx_t cidx, end;
4012   uint32_t i;
4013 
4014   alloc_cidx_array(solver, solver->pool.num_learned_clauses);
4015 
4016   a = solver->cidx_array;
4017   i = 0;
4018 
4019   end = solver->pool.size;
4020   cidx = clause_pool_first_learned_clause(&solver->pool);
4021   while (cidx < end) {
4022     if (! clause_is_locked(solver, cidx) &&
4023         ! clause_is_precious(solver, cidx)) {
4024       assert(i < solver->pool.num_learned_clauses);
4025       a[i] = cidx;
4026       i ++;
4027     }
4028     cidx = clause_pool_next_clause(&solver->pool, cidx);
4029   }
4030 
4031   return i;
4032 }
4033 
4034 /*
4035  * Sort cidx_array in increasing activity order
4036  * - use stable sort
4037  * - n = number of clauses stored in the cidx_array
4038  */
4039 // ordering: aux = solver, c1 and c2 are the indices of two learned clauses
less_active(void * aux,cidx_t c1,cidx_t c2)4040 static bool less_active(void *aux, cidx_t c1, cidx_t c2) {
4041   sat_solver_t *solver;
4042   float act1, act2;
4043 
4044   solver = aux;
4045   act1 = get_learned_clause_activity(&solver->pool, c1);
4046   act2 = get_learned_clause_activity(&solver->pool, c2);
4047   return act1 < act2 || (act1 == act2 && c1 < c2);
4048 }
4049 
sort_learned_clauses(sat_solver_t * solver,uint32_t n)4050 static void sort_learned_clauses(sat_solver_t *solver, uint32_t n) {
4051   uint_array_sort2(solver->cidx_array, n, solver, less_active);
4052 }
4053 
4054 
4055 /*
4056  * Delete a fraction of the learned clauses (Minisat-style)
4057  */
nsat_reduce_learned_clause_set(sat_solver_t * solver)4058 static void nsat_reduce_learned_clause_set(sat_solver_t *solver) {
4059   uint32_t i, n, n0;
4060   cidx_t *a;
4061 
4062   if (solver->verbosity >= 4) {
4063     fprintf(stderr, "\nc Reduce learned clause set\n");
4064     fprintf(stderr, "c  on entry: %"PRIu32" clauses, %"PRIu32" literals\n",
4065             solver->pool.num_learned_clauses, solver->pool.num_learned_literals);
4066   }
4067   n = collect_learned_clauses(solver);
4068   sort_learned_clauses(solver, n);
4069   a = solver->cidx_array;
4070 
4071   check_candidate_clauses_to_delete(solver, a, n); // DEBUG
4072 
4073   if (solver->verbosity >= 4) {
4074     fprintf(stderr, "c  possible deletion: %"PRIu32" clauses\n", n);
4075   }
4076 
4077   // a contains the clauses that can be deleted
4078   // less useful clauses (i.e., low-activity clauses) occur first
4079   n0 = solver->params.reduce_fraction * (n/32);
4080   for (i=0; i<n0; i++) {
4081     clause_pool_delete_clause(&solver->pool, a[i]);
4082     solver->stats.learned_clauses_deleted ++;
4083   }
4084 
4085   free_cidx_array(solver);
4086 
4087   collect_garbage(solver, solver->pool.learned, false);
4088   solver->stats.reduce_calls ++;
4089 
4090   check_watch_vectors(solver);
4091 
4092   if (solver->verbosity >= 4) {
4093     fprintf(stderr, "c  on exit: %"PRIu32" clauses, %"PRIu32" literals\n",
4094             solver->pool.num_learned_clauses, solver->pool.num_learned_literals);
4095   }
4096 
4097   report(solver, "red");
4098 }
4099 
4100 
4101 
4102 /********************************************
4103  *  SIMPLIFICATION OF THE CLAUSE DATABASE   *
4104  *******************************************/
4105 
4106 /*
4107  * Cleanup watch vector w:
4108  * - remove all the assigned (true) literals from w
4109  * - also remove all the clause indices
4110  * - after clauses are deleted from the pool, we call 'collect_garbage'
4111  *   to do a full cleanup and restore the watch vectors.
4112  */
cleanup_watch_vector(sat_solver_t * solver,watch_t * w)4113 static void cleanup_watch_vector(sat_solver_t *solver, watch_t *w) {
4114   uint32_t i, j, k, n;
4115 
4116   assert(solver->decision_level == 0 &&
4117          solver->stack.top == solver->stack.prop_ptr &&
4118          w != NULL);
4119 
4120   n = w->size;
4121   j = 0;
4122   i = 0;
4123   while (i < n) {
4124     k = w->data[i];
4125     if (idx_is_clause(k)) {
4126       i += 2;
4127     } else {
4128       if (lit_is_unassigned(solver, idx2lit(k))) {
4129         w->data[j] = k;
4130         j ++;
4131       }
4132       i ++;
4133     }
4134   }
4135   w->size = j;
4136 }
4137 
4138 
4139 /*
4140  * Simplify the binary clauses:
4141  * - if l is assigned at level 0, delete its watched vector
4142  *   (this assumes that all Boolean propagations have been done).
4143  * - otherwise, remove the assigned literals from watch[l].
4144  */
simplify_binary_clauses(sat_solver_t * solver)4145 static void simplify_binary_clauses(sat_solver_t *solver) {
4146   uint32_t i, n;
4147   watch_t *w;
4148 
4149   assert(solver->decision_level == 0 &&
4150          solver->stack.top == solver->stack.prop_ptr);
4151 
4152   n = solver->nliterals;
4153   for (i=2; i<n; i++) {
4154     w = solver->watch[i];
4155     if (w != NULL) {
4156       switch (lit_value(solver, i)) {
4157       case VAL_UNDEF_TRUE:
4158       case VAL_UNDEF_FALSE:
4159         cleanup_watch_vector(solver, w);
4160         break;
4161 
4162       case VAL_TRUE:
4163       case VAL_FALSE:
4164         safe_free(w);
4165         solver->watch[i] = NULL;
4166         break;
4167       }
4168     }
4169   }
4170 }
4171 
4172 
4173 /*
4174  * After deletion: count the number of binary clauses left
4175  */
num_literals_in_watch_vector(watch_t * w)4176 static uint32_t num_literals_in_watch_vector(watch_t *w) {
4177   uint32_t i, n, count;
4178 
4179   assert(w != NULL);
4180   count = 0;
4181   n = w->size;
4182   i = 0;
4183   while (i < n) {
4184     if (idx_is_literal(w->data[i])) {
4185       count ++;
4186       i ++;
4187     } else {
4188       i += 2;
4189     }
4190   }
4191   return count;
4192 }
4193 
4194 
count_binary_clauses(sat_solver_t * solver)4195 static uint32_t count_binary_clauses(sat_solver_t *solver) {
4196   uint32_t i, n, sum;
4197   watch_t *w;
4198 
4199   sum = 0;
4200   n = solver->nliterals;
4201   for (i=2; i<n; i++) {
4202     w = solver->watch[i];
4203     if (w != NULL) {
4204       sum += num_literals_in_watch_vector(w);
4205     }
4206   }
4207   assert((sum & 1) == 0 && sum/2 <= solver->binaries);
4208 
4209   return sum >> 1;
4210 }
4211 
4212 
4213 /*
4214  * Simplify the clause that starts at cidx:
4215  * - remove all literals that are false at the base level
4216  * - delete the clause if it is true
4217  * - if the clause cidx is reduced to a binary clause { l0, l1 }
4218  *   then delete cidx and add { l0, l1 } as a binary clause
4219  *
4220  * - return true if the clause is deleted
4221  * - return false otherwise
4222  */
simplify_clause(sat_solver_t * solver,cidx_t cidx)4223 static bool simplify_clause(sat_solver_t *solver, cidx_t cidx) {
4224   uint32_t i, j, n;
4225   literal_t *a;
4226   literal_t l;
4227 
4228   assert(solver->decision_level == 0 && good_clause_idx(&solver->pool, cidx));
4229 
4230   n = clause_length(&solver->pool, cidx);
4231   a = clause_literals(&solver->pool, cidx);
4232 
4233   j = 0;
4234   for (i=0; i<n; i++) {
4235     l = a[i];
4236     switch (lit_value(solver, l)) {
4237     case VAL_FALSE:
4238       break;
4239 
4240     case VAL_UNDEF_FALSE:
4241     case VAL_UNDEF_TRUE:
4242       a[j] = l;
4243       j ++;
4244       break;
4245 
4246     case VAL_TRUE:
4247       // the clause is true
4248       clause_pool_delete_clause(&solver->pool, cidx);
4249       return true;
4250     }
4251   }
4252 
4253   assert(j >= 2);
4254 
4255   if (j == 2) {
4256     // convert to a binary clause
4257     add_binary_clause(solver, a[0], a[1]); // must be done first
4258     clause_pool_delete_clause(&solver->pool, cidx);
4259     solver->simplify_new_bins ++;
4260     return true;
4261   }
4262 
4263   if (j < n) {
4264     clause_pool_shrink_clause(&solver->pool, cidx, j);
4265   }
4266   return false;
4267 }
4268 
4269 
4270 /*
4271  * Remove dead antecedents (of literals assigned at level 0)
4272  * - if l is implied at level 0 by a clause cidx,
4273  *   then cidx will be deleted by simplify_clause_database.
4274  *   so l ends up with a dead antecedent.
4275  * - to fix this, we force the ante_tag of all variables
4276  *   assigned at level 0 to ATAG_UNIT.
4277  */
remove_dead_antecedents(sat_solver_t * solver)4278 static void remove_dead_antecedents(sat_solver_t *solver) {
4279   uint32_t i, n;
4280   literal_t l;
4281 
4282   assert(solver->decision_level == 0);
4283 
4284   n = solver->stack.top;
4285   for (i=0; i<n; i++) {
4286     l = solver->stack.lit[i];
4287     assert(solver->level[var_of(l)] == 0);
4288     solver->ante_tag[var_of(l)] = ATAG_UNIT;
4289   }
4290 }
4291 
4292 
4293 /*
4294  * Simplify all the clauses
4295  * - this does basic simplifications: remove all false literals
4296  *   and remove all true clauses.
4297  */
simplify_clause_database(sat_solver_t * solver)4298 static void simplify_clause_database(sat_solver_t *solver) {
4299   cidx_t cidx;
4300   uint32_t d;
4301 
4302   assert(solver->decision_level == 0 && solver->stack.top == solver->stack.prop_ptr);
4303 
4304   if (solver->verbosity >= 4) {
4305     fprintf(stderr, "\nc Simplify clause database\n");
4306     fprintf(stderr, "c  on entry: prob: %"PRIu32" cls/%"PRIu32" lits, learned: %"PRIu32" cls/%"PRIu32" lits\n",
4307             solver->pool.num_prob_clauses, solver->pool.num_prob_literals,
4308             solver->pool.num_learned_clauses, solver->pool.num_learned_literals);
4309   }
4310 
4311   simplify_binary_clauses(solver);
4312 
4313   d = 0; // count deleted clauses
4314   cidx = clause_pool_first_clause(&solver->pool);
4315   // Note: pool.size may change within the loop if clauses are deleted
4316   while (cidx < solver->pool.size) {
4317     d += simplify_clause(solver, cidx);
4318     cidx = clause_pool_next_clause(&solver->pool, cidx);
4319   }
4320 
4321   solver->stats.prob_clauses_deleted += d;
4322   remove_dead_antecedents(solver);
4323   collect_garbage(solver, 0, true);
4324 
4325   solver->binaries = count_binary_clauses(solver);
4326   solver->stats.simplify_calls ++;
4327 
4328   check_watch_vectors(solver);
4329 
4330   if (solver->verbosity >= 4) {
4331     fprintf(stderr, "c  on exit: prob: %"PRIu32" cls/%"PRIu32" lits, learned: %"PRIu32" cls/%"PRIu32" lits\n\n",
4332             solver->pool.num_prob_clauses, solver->pool.num_prob_literals,
4333             solver->pool.num_learned_clauses, solver->pool.num_learned_literals);
4334   }
4335 
4336   report(solver, "simp");
4337 }
4338 
4339 
4340 /*******************************
4341  *  BINARY IMPLICATION GRAPH   *
4342  ******************************/
4343 
4344 /*
4345  * The binary implication graph is defined by the binary clauses.
4346  * Its vertices are literals. A binary clause {l0, l1} defines two
4347  * edges in the graph: ~l0 --> l1 and ~l1 --> l0.
4348  *
4349  * If there's a circuit in this graph: l0 --> l1 --> .... --> l_n --> l0
4350  * then all the literals on the circuit are equivalent. We can reduce the
4351  * problem by replacing l1, ..., l_n by l0.
4352  */
4353 
4354 #if 1
4355 /*
4356  * Convert l to the original dimacs index:
4357  * - dimacs(pos_lit(x)) = x
4358  * - dimacs(neg_lit(x)) = -x
4359  */
dimacs(uint32_t l)4360 static int32_t dimacs(uint32_t l) {
4361   int32_t x;
4362   x = var_of(l);
4363   return is_pos(l) ? x : - x;
4364 }
4365 
4366 /*
4367  * Display a strongly-connected component C
4368  * - l = root of the component C
4369  * - the elements of C are stored in solver->vertex_stack, above l
4370  */
show_scc(FILE * f,const sat_solver_t * solver,literal_t l)4371 static void show_scc(FILE *f, const sat_solver_t *solver, literal_t l) {
4372   literal_t l0;
4373   uint32_t i;
4374   const vector_t *v;
4375 
4376   v = &solver->vertex_stack;
4377   assert(v->size > 0);
4378   i = v->size - 1;
4379   l0 = v->data[i];
4380   if (l0 != l) {
4381     // interesting SCC: not reduced to { l }
4382     fprintf(f, "c ");
4383     if (solver->label[not(l)] == UINT32_MAX) {
4384       fprintf(f, "dual ");
4385     }
4386     fprintf(f, "SCC: { %"PRId32" ", dimacs(l0));
4387     do {
4388       assert(i > 0);
4389       i --;
4390       l0 = v->data[i];
4391       fprintf(f, "%"PRId32" ", dimacs(l0));
4392     } while (l0 != l);
4393     fprintf(f, "}\n");
4394   }
4395 }
4396 
4397 #endif
4398 
4399 /*
4400  * Find a representative literal in a strongly-connected component
4401  * - l = root of the component C
4402  * - the elements of C are stored in solver->vertex_stack, above l
4403  *
4404  * In preprocessing mode, the representative is the smallest literal in C.
4405  * In search mode, the representative is the most active literal in C.
4406  */
scc_representative(sat_solver_t * solver,literal_t l)4407 static literal_t scc_representative(sat_solver_t *solver, literal_t l) {
4408   uint32_t i;
4409   literal_t rep, l0;
4410   uint32_t max_rank, rank;
4411 
4412   i = solver->vertex_stack.size;
4413   rep = l;
4414   if (solver->preprocess) {
4415     do {
4416       assert(i > 0);
4417       i --;
4418       l0 = solver->vertex_stack.data[i];
4419       if (l0 < rep) rep = l0;
4420     } while (l0 != l);
4421 
4422   } else {
4423     max_rank = lit_rank(solver, rep);
4424     do {
4425       assert(i > 0);
4426       i --;
4427       l0 = solver->vertex_stack.data[i];
4428       rank = lit_rank(solver, l0);
4429       if (rank > max_rank || (rank == max_rank && l0 < rep)) {
4430 	max_rank = rank;
4431 	rep = l0;
4432       }
4433     } while (l0 != l);
4434   }
4435 
4436   return rep;
4437 }
4438 
4439 /*
4440  * Process a strongly-connected component
4441  * - l = root of the component C
4442  * - the elements of C are stored in solver->vertex_stack, above l
4443  *
4444  * If the complementary component has been processed before, we just
4445  * mark that literals of C have been fully explored.
4446  *
4447  * Otherwise, we select a representative 'rep' in C. For every other
4448  * literal l0 in C, we record subst[l0] := rep.
4449  * - the antecedent tag for var_of(l0) is set to ATAG_SUBST
4450  * - the antecedent data for var_of(l0) is set to rep or not(rep)
4451  *   depending on l0's polarity.
4452  *
4453  * If we detect that C contains complementary literals l0 and not(l0),
4454  * we add the empty clause and exit.
4455  */
process_scc(sat_solver_t * solver,literal_t l)4456 static void process_scc(sat_solver_t *solver, literal_t l) {
4457   literal_t l0, rep;
4458   bool unsat;
4459 
4460   assert(solver->label[l] < UINT32_MAX);
4461 
4462   if (solver->verbosity >= 400) {
4463     show_scc(stderr, solver, l);
4464   }
4465 
4466   if (solver->label[not(l)] == UINT32_MAX) {
4467     /*
4468      * This SCC is of the form { l_0 ..., l }. The complementary SCC {
4469      * not(l_0) ... not(l) } has been processed before.  We mark l0,
4470      * ..., l as fully explored and remove C from the
4471      * vertex_stack.
4472      */
4473     do {
4474       l0 = vector_pop(&solver->vertex_stack);
4475       solver->label[l0] = UINT32_MAX; // fully explored mark
4476     } while (l0 != l);
4477 
4478   } else {
4479     /*
4480      * We check for inconsistency and store the substitution
4481      */
4482     unsat = false;
4483     rep = scc_representative(solver, l);
4484 
4485     do {
4486       l0 = vector_pop(&solver->vertex_stack);
4487       solver->label[l0] = UINT32_MAX; // mark l0 as fully explored/SCC known
4488       if (lit_is_eliminated(solver, l0)) {
4489 	// both l0 and not(l0) are in the SCC
4490 	assert(base_subst(solver, l0) == not(rep));
4491 	unsat = true;
4492 	add_empty_clause(solver);
4493 	break;
4494       }
4495       // record substitution: subst[l0] := rep
4496       if (l0 != rep) {
4497 	set_lit_subst(solver, l0, rep);
4498       }
4499     } while (l0 != l);
4500 
4501     if (unsat) {
4502       fprintf(stderr, "c inconsistent SCC\n");
4503     }
4504   }
4505 }
4506 
4507 /*
4508  * Get the next successor of l0 in the implication graph:
4509  * - i = index in the watch vector of ~l0 to scan from
4510  * - if there's a binary clause {~l0, l1} at some index k >= i, then
4511  *   we return true, store l1 in *successor,  and store k+1 in *i.
4512  * - otherwise, the function returns false.
4513  */
next_successor(const sat_solver_t * solver,literal_t l0,uint32_t * i,literal_t * successor)4514 static bool next_successor(const sat_solver_t *solver, literal_t l0, uint32_t *i, literal_t *successor) {
4515   uint32_t k, idx, n;
4516   watch_t *w;
4517 
4518   w = solver->watch[not(l0)];
4519   if (w != NULL) {
4520     n = w->size;
4521     k = *i;
4522     assert(k <= n);
4523 
4524     if (solver->preprocess) {
4525       /*
4526        * in preprocessing mode:
4527        * all elements in w->data are clause indices
4528        */
4529       while (k < n) {
4530 	idx = w->data[k];
4531 	if (clause_is_live(&solver->pool, idx) && clause_length(&solver->pool, idx) == 2) {
4532 	  *i = k+1;
4533 	  *successor = other_watched_literal_of_clause(&solver->pool, idx, not(l0));
4534 	  return true;
4535 	}
4536 	k ++;
4537       }
4538 
4539     } else {
4540       /*
4541        * in search mode:
4542        * elements in w->data encode either a single literal
4543        * or a pair clause index + blocker
4544        */
4545       while (k < n) {
4546 	idx = w->data[k];
4547 	if (idx_is_literal(idx)) {
4548 	  *i = k+1;
4549 	  *successor = idx2lit(idx);
4550 	  return true;
4551 	} else if (clause_is_live(&solver->pool, idx) && clause_length(&solver->pool, idx) == 2) {
4552 	  *i = k+2;
4553 	  *successor = other_watched_literal_of_clause(&solver->pool, idx, not(l0));
4554 	  return true;
4555 	}
4556 	k += 2;
4557       }
4558     }
4559   }
4560 
4561   return false;
4562 }
4563 
4564 /*
4565  * Compute strongly-connected components. Explore the graph starting from literal l.
4566  * - visit stores the visit index of a literal: visit[l1] = k means that l1 is reachable
4567  *   from l and is the k-th vertex visited (where k>=1).
4568  * - label stores the smallest index of a reachable literal: label[l1] = index of a
4569  *   vertex l2 reachable from l1 and with visit[l2] <= visit[l1]
4570  * - for vertices that have been fully explored, we set label[l] = UINT32_MAX (cf.
4571  *   process_scc).
4572  */
dfs_explore(sat_solver_t * solver,literal_t l)4573 static void dfs_explore(sat_solver_t *solver, literal_t l) {
4574   gstack_elem_t *e;
4575   uint32_t k;
4576   literal_t x, y;
4577 
4578   //  fprintf(stderr, "dfs: root = %"PRId32"\n", dimacs(l));
4579 
4580   assert(solver->visit[l] == 0 &&
4581          gstack_is_empty(&solver->dfs_stack) &&
4582          solver->vertex_stack.size == 0);
4583 
4584   k = 1;
4585   solver->visit[l] = k;
4586   solver->label[l] = k;
4587   gstack_push_vertex(&solver->dfs_stack, l, 0);
4588   vector_push(&solver->vertex_stack, l);
4589 
4590   for (;;) {
4591     e = gstack_top(&solver->dfs_stack);
4592     x = e->vertex;
4593     if (next_successor(solver, x, &e->index, &y)) {
4594       // skip y if it's assigned at level0
4595       if (lit_is_active(solver, y)) {
4596 	// x --> y in the implication graph
4597 	if (solver->visit[y] == 0) {
4598 	  // y not visited yet
4599 	  k ++;
4600 	  solver->visit[y] = k;
4601 	  solver->label[y] = k;
4602 	  gstack_push_vertex(&solver->dfs_stack, y, 0);
4603 	  vector_push(&solver->vertex_stack, y);
4604 	} else if (solver->label[y] < solver->label[x]) {
4605 	  // y has a successor visited before x on the dfs stack
4606 	  solver->label[x] = solver->label[y];
4607 	}
4608       }
4609 
4610     } else {
4611       // all successors of x have been explored
4612       assert(solver->label[x] <= solver->visit[x]);
4613       if (solver->label[x] == solver->visit[x]) {
4614         // x is the root of its SCC
4615         process_scc(solver, x);
4616 	if (solver->has_empty_clause) {
4617 	  // unsat detected
4618 	  reset_gstack(&solver->dfs_stack);
4619 	  break;
4620 	}
4621       }
4622       // pop x
4623       gstack_pop(&solver->dfs_stack);
4624       if (gstack_is_empty(&solver->dfs_stack)) {
4625         break; // all done
4626       }
4627       // update the label of x's predecessor
4628       y = gstack_top(&solver->dfs_stack)->vertex;
4629       if (solver->label[x] < solver->label[y]) {
4630         solver->label[y] = solver->label[x];
4631       }
4632     }
4633   }
4634 }
4635 
4636 
4637 /*
4638  * Compute all SCCs and build/extend the variable substitution.
4639  * - sets solver->has_empty_clause to true if an SCC
4640  *   contains complementary literals.
4641  * - store the eliminated variables in solver->subst_vars
4642  */
compute_sccs(sat_solver_t * solver)4643 static void compute_sccs(sat_solver_t *solver) {
4644   uint32_t i, n;
4645 
4646   assert(solver->label == NULL && solver->visit == NULL);
4647 
4648   reset_vector(&solver->subst_vars);
4649 
4650   n = solver->nliterals;
4651   solver->label = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
4652   solver->visit = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
4653   for (i=0; i<n; i++) {
4654     solver->visit[i] = 0;
4655     solver->label[i] = 0;
4656   }
4657   for (i=2; i<n; i++) {
4658     if (lit_is_active(solver, i) && solver->label[i] == 0) {
4659       dfs_explore(solver, i);
4660       if (solver->has_empty_clause) break; // UNSAT detected
4661     }
4662   }
4663 
4664   safe_free(solver->label);
4665   safe_free(solver->visit);
4666   solver->label = NULL;
4667   solver->visit = NULL;
4668 }
4669 
4670 
4671 
4672 /*************************************
4673  *  APPLY THE VARIABLE SUBSTITUTION  *
4674  ************************************/
4675 
4676 /*
4677  * Trick to detect duplicates and complementary literals in a clause:
4678  * - when literal l is added to a clause, we temporarily set its
4679  *   truth value to false.
4680  * - so the next occurrence of l is ignored and an occurrence of not(l)
4681  *   makes the clause true.
4682  */
4683 // make l false and not l true (temporarily)
4684 // preserve the preferred polarity in bits 3-2 of solver->value[l]
mark_false_lit(sat_solver_t * solver,literal_t l)4685 static void mark_false_lit(sat_solver_t *solver, literal_t l) {
4686   uint8_t v;
4687 
4688   assert(l < solver->nliterals);
4689   assert(lit_is_unassigned(solver, l));
4690 
4691   v = solver->value[l];
4692   solver->value[l] = (v<<2) | VAL_FALSE;
4693   v = solver->value[not(l)];
4694   solver->value[not(l)] = (v<<2) | VAL_TRUE;
4695 }
4696 
4697 // remove the mark on l and restore the preferred polarity
clear_false_lit(sat_solver_t * solver,literal_t l)4698 static void clear_false_lit(sat_solver_t *solver, literal_t l) {
4699   bvar_t x;
4700   uint8_t v;
4701 
4702   assert(l < solver->nliterals);
4703   assert((solver->value[l] & 3) == VAL_FALSE);
4704 
4705   x = var_of(l);
4706   v = solver->value[pos_lit(x)];
4707   solver->value[pos_lit(x)] = v >> 2;
4708   v  = solver->value[neg_lit(x)];
4709   solver->value[neg_lit(x)] = v >> 2;
4710 
4711   assert(solver->value[pos_lit(x)] < 2 &&
4712 	 solver->value[neg_lit(x)] < 2 &&
4713 	 (solver->value[pos_lit(x)] ^ solver->value[neg_lit(x)]) == 1);
4714 }
4715 
4716 // remove the marks on a[0 ... n-1]
clear_false_lits(sat_solver_t * solver,uint32_t n,const literal_t * a)4717 static void clear_false_lits(sat_solver_t *solver, uint32_t n, const literal_t *a) {
4718   uint32_t i;
4719 
4720   for (i=0; i<n; i++) {
4721     clear_false_lit(solver, a[i]);
4722   }
4723 }
4724 
4725 /*
4726  * Simplify the clause that starts at cidx and apply the substitution.
4727  * - if the clause becomes empty: set solver->has_empty_clause to true
4728  * - if the clause simplifies to a unit clause: add a unit literal
4729  *
4730  * - delete the clause if it is true or if it reduces to a clause
4731  *   of length <= 2.
4732  */
subst_and_simplify_clause(sat_solver_t * solver,cidx_t cidx)4733 static bool subst_and_simplify_clause(sat_solver_t *solver, cidx_t cidx) {
4734   uint32_t i, j, n;
4735   literal_t *a;
4736   literal_t l;
4737 
4738   assert(solver->decision_level == 0 && good_clause_idx(&solver->pool, cidx));
4739 
4740   n = clause_length(&solver->pool, cidx);
4741   a = clause_literals(&solver->pool, cidx);
4742 
4743   j = 0;
4744   for (i=0; i<n; i++) {
4745     l = full_lit_subst(solver, a[i]);
4746     switch (solver->value[l] & 3) {
4747     case VAL_FALSE:
4748       break;
4749 
4750     case VAL_UNDEF_FALSE:
4751     case VAL_UNDEF_TRUE:
4752       a[j] = l;
4753       j ++;
4754       mark_false_lit(solver, l);
4755       break;
4756 
4757     case VAL_TRUE:
4758       // the clause is true
4759       goto done;
4760     }
4761   }
4762 
4763  done:
4764   /*
4765    * a[0 ... j-1]: literals after substitution.
4766    * If i < n, the clause is true and must be deleted.
4767    * Otherwise, we keep the clause a[0 ... j-1].
4768    * We change representation if j <= 2.
4769    */
4770   clear_false_lits(solver, j, a);
4771 
4772   if (i < n) { // true clause
4773     clause_pool_delete_clause(&solver->pool, cidx);
4774     return true;
4775   }
4776 
4777   if (j <= 2) {
4778     // reduced to a small clause
4779     if (j == 0) {
4780       add_empty_clause(solver);
4781     } else if (j == 1) {
4782       add_unit_clause(solver, a[0]);
4783       solver->simplify_new_units ++;
4784     } else {
4785       add_binary_clause(solver, a[0], a[1]);
4786       solver->simplify_new_bins ++;
4787     }
4788     clause_pool_delete_clause(&solver->pool, cidx);
4789     return true;
4790   }
4791 
4792   if (j < n) {
4793     clause_pool_shrink_clause(&solver->pool, cidx, j);
4794   }
4795   return false;
4796 }
4797 
4798 
4799 /*
4800  * Apply the substitution to binary clause { l0, l1 }
4801  */
subst_and_simplify_binary_clause(sat_solver_t * solver,literal_t l0,literal_t l1)4802 static void subst_and_simplify_binary_clause(sat_solver_t *solver, literal_t l0, literal_t l1) {
4803   literal_t a[2];
4804   literal_t l;
4805   uint32_t i, j;
4806 
4807   a[0] = l0;
4808   a[1] = l1;
4809 
4810   j = 0;
4811   for (i=0; i<2; i++) {
4812     l = full_lit_subst(solver, a[i]);
4813     switch(lit_value(solver, l)) {
4814     case VAL_FALSE:
4815       break;
4816 
4817     case VAL_UNDEF_TRUE:
4818     case VAL_UNDEF_FALSE:
4819       a[j] = l;
4820       j ++;
4821       break;
4822 
4823     case VAL_TRUE:
4824       return;
4825     }
4826   }
4827 
4828   if (j == 0) {
4829     add_empty_clause(solver);
4830 
4831   } else if (j == 1) {
4832     assert(lit_is_unassigned(solver, a[0]));
4833     add_unit_clause(solver, a[0]);
4834 
4835   } else {
4836     assert(lit_is_unassigned(solver, a[0]));
4837     assert(lit_is_unassigned(solver, a[1]));
4838 
4839     if (a[0] == a[1]) {
4840       add_unit_clause(solver, a[0]);
4841     } else if (a[0] != not(a[1])) {
4842       add_binary_clause(solver, a[0], a[1]);
4843     }
4844   }
4845 }
4846 
4847 /*
4848  * Scan vector w = watch[l0] where l0 is unassigned
4849  * - collect the binary clauses implicitly stored in w and add them to v
4850  *   then reset w
4851  * - to avoid duplicate clauses in v, we collect only the clauses of the
4852  *   form {l0 , l} with l > l0. We also ignore { l0, l} if l is true.
4853  */
collect_binary_clauses_of_watch(sat_solver_t * solver,watch_t * w,literal_t l0,vector_t * v)4854 static void collect_binary_clauses_of_watch(sat_solver_t *solver, watch_t *w, literal_t l0, vector_t *v) {
4855   uint32_t i, k, n;
4856   literal_t l;
4857 
4858   assert(lit_is_unassigned(solver, l0) && solver->watch[l0] == w);
4859 
4860   n = w->size;
4861   i = 0;
4862   while (i<n) {
4863     k = w->data[i];
4864     if (idx_is_literal(k)) {
4865       i ++;
4866       l = idx2lit(k);
4867       assert(! lit_is_false(solver, l));
4868       if (l > l0 && lit_is_unassigned(solver, l)) {
4869 	vector_push(v, l0);
4870 	vector_push(v, l);
4871       }
4872     } else {
4873       i += 2;
4874     }
4875   }
4876 
4877   w->size = 0;
4878 }
4879 
4880 /*
4881  * Scan all the watch vectors:
4882  * - add all the binary clauses to vector v
4883  * - reset all watch vectors
4884  */
collect_binary_clauses_and_reset_watches(sat_solver_t * solver,vector_t * v)4885 static void collect_binary_clauses_and_reset_watches(sat_solver_t *solver, vector_t *v) {
4886   uint32_t i, n;
4887   watch_t *w;
4888 
4889   assert(solver->decision_level == 0 && solver->stack.top == solver->stack.prop_ptr);
4890 
4891   n = solver->nliterals;
4892   for (i=2; i<n; i++) {
4893     w = solver->watch[i];
4894     if (w != NULL) {
4895       if (lit_is_assigned(solver, i)) {
4896 	/*
4897 	 * Since boolean propagation is done, all binary
4898 	 * clauses of w are true at level 0.
4899 	 */
4900 	safe_free(w);
4901 	solver->watch[i] = NULL;
4902       } else {
4903 	collect_binary_clauses_of_watch(solver, w, i, v);
4904       }
4905     }
4906   }
4907 }
4908 
4909 /*
4910  * Apply the substitution to all the binary clauses
4911  * - first, collect all binary clauses in an vector v and
4912  *   empty the watch vectors.
4913  * - then process all the clauses of v
4914  */
apply_subst_to_binary_clauses(sat_solver_t * solver)4915 static void apply_subst_to_binary_clauses(sat_solver_t *solver) {
4916   vector_t aux;
4917   uint32_t i, n;
4918 
4919   init_vector(&aux);
4920   collect_binary_clauses_and_reset_watches(solver, &aux);
4921   n = aux.size;
4922   for (i=0; i<n; i += 2) {
4923     subst_and_simplify_binary_clause(solver, aux.data[i], aux.data[i+1]);
4924     if (solver->has_empty_clause) break;
4925   }
4926   delete_vector(&aux);
4927 }
4928 
4929 
4930 /*
4931  * Apply the substitution to all clauses
4932  */
apply_substitution(sat_solver_t * solver)4933 static void apply_substitution(sat_solver_t *solver) {
4934   cidx_t cidx;
4935   uint32_t d;
4936 
4937   assert(solver->decision_level == 0 && solver->stack.top == solver->stack.prop_ptr);
4938 
4939   apply_subst_to_binary_clauses(solver);
4940   if (solver->has_empty_clause) return;
4941 
4942   d = 0; // count deleted clauses
4943   cidx = clause_pool_first_clause(&solver->pool);
4944   while (cidx < solver->pool.size) {
4945     d += subst_and_simplify_clause(solver, cidx);
4946     if (solver->has_empty_clause) return;
4947     cidx = clause_pool_next_clause(&solver->pool, cidx);
4948   }
4949 
4950   solver->stats.prob_clauses_deleted += d;
4951   remove_dead_antecedents(solver);
4952   collect_garbage(solver, 0, true);
4953 
4954   solver->binaries = count_binary_clauses(solver);
4955   solver->stats.subst_calls ++;
4956 
4957   check_watch_vectors(solver);
4958 }
4959 
4960 
4961 
4962 
4963 /*******************
4964  *  PREPROCESSING  *
4965  ******************/
4966 
4967 /*
4968  * Statistics after preprocessing
4969  */
show_preprocessing_stats(sat_solver_t * solver,double time)4970 static void show_preprocessing_stats(sat_solver_t *solver, double time) {
4971   fprintf(stderr, "c\n"
4972 	          "c After preprocessing\n");
4973   fprintf(stderr, "c  unit literals        : %"PRIu32"\n", solver->stats.pp_unit_lits);
4974   fprintf(stderr, "c  pure literals        : %"PRIu32"\n", solver->stats.pp_pure_lits);
4975   fprintf(stderr, "c  substitutions        : %"PRIu32"\n", solver->stats.pp_subst_vars);
4976   fprintf(stderr, "c  unit equiv           : %"PRIu32"\n", solver->stats.pp_subst_units);
4977   fprintf(stderr, "c  literal equiv        : %"PRIu32"\n", solver->stats.pp_equivs);
4978   fprintf(stderr, "c  cheap var elims      : %"PRIu32"\n", solver->stats.pp_cheap_elims);
4979   fprintf(stderr, "c  less cheap var elims : %"PRIu32"\n", solver->stats.pp_var_elims);
4980   fprintf(stderr, "c  active vars          : %"PRIu32"\n", num_active_vars(solver));
4981   fprintf(stderr, "c  deleted clauses      : %"PRIu32"\n", solver->stats.pp_clauses_deleted);
4982   fprintf(stderr, "c  subsumed clauses     : %"PRIu32"\n", solver->stats.pp_subsumptions);
4983   fprintf(stderr, "c  strengthenings       : %"PRIu32"\n", solver->stats.pp_strengthenings);
4984   fprintf(stderr, "c  unit strengthenings  : %"PRIu32"\n", solver->stats.pp_unit_strengthenings);
4985   fprintf(stderr, "c  unit clauses         : %"PRIu32"\n", solver->units);           // should be zero
4986   fprintf(stderr, "c  bin clauses          : %"PRIu32"\n", solver->binaries);
4987   fprintf(stderr, "c  big clauses          : %"PRIu32"\n", solver->pool.num_prob_clauses);
4988   fprintf(stderr, "c\n"
4989 	          "c Preprocessing time    : %.4f\nc\n", time);
4990   if (solver->has_empty_clause) {
4991     fprintf(stderr, "c\nc  unsat by preprocessing\nc\n");
4992   }
4993 }
4994 
4995 
4996 /*
4997  * QUEUE OF CLAUSES/SCAN INDEX
4998  */
4999 
5000 /*
5001  * The queue cqueue + the scan index define a set of clauses to visit:
5002  * - cqueue contains clause idx that are smaller (strictly) than scan index.
5003  * - every clause in cqueue is marked.
5004  * - the set of clauses to visit is the union of the clauses in cqueue and
5005  *   the clauses of index >= scan_index.
5006  */
5007 
5008 /*
5009  * Reset: empty the queue and remove marks
5010  */
reset_clause_queue(sat_solver_t * solver)5011 static void reset_clause_queue(sat_solver_t *solver) {
5012   cidx_t cidx;
5013 
5014   solver->scan_index = 0;
5015   while (! queue_is_empty(&solver->cqueue)) {
5016     cidx = queue_pop(&solver->cqueue);
5017     if (clause_is_live(&solver->pool, cidx)) {
5018       unmark_clause(&solver->pool, cidx);
5019     }
5020   }
5021 }
5022 
5023 
5024 /*
5025  * Add cidx to the queue:
5026  * - cidx is the index of a clause that shrunk (so it may subsume more clauses)
5027  * - do nothing if cidx is marked (i.e., already in cqueue) or if cidx >= scan_index
5028  */
clause_queue_push(sat_solver_t * solver,cidx_t cidx)5029 static void clause_queue_push(sat_solver_t *solver, cidx_t cidx) {
5030   if (cidx < solver->scan_index && clause_is_unmarked(&solver->pool, cidx)) {
5031     mark_clause(&solver->pool, cidx);
5032     queue_push(&solver->cqueue, cidx);
5033   }
5034 }
5035 
5036 
5037 /*
5038  * Next clause from scan index: return solver->pool.size if
5039  * all clauses have been scanned
5040  */
clause_scan_next(sat_solver_t * solver)5041 static cidx_t clause_scan_next(sat_solver_t *solver) {
5042   cidx_t i;
5043 
5044   i = solver->scan_index;
5045   if (i < solver->pool.size) {
5046     solver->scan_index = clause_pool_next_clause(&solver->pool, i);
5047   }
5048   return i;
5049 }
5050 
5051 /*
5052  * Get the next element in the queue
5053  * - return solver->pool.size if the queue is empty
5054  */
clause_queue_pop(sat_solver_t * solver)5055 static cidx_t clause_queue_pop(sat_solver_t *solver) {
5056   cidx_t i;
5057 
5058   while(! queue_is_empty(&solver->cqueue)) {
5059     i = queue_pop(&solver->cqueue);
5060     if (clause_is_live(&solver->pool, i)) {
5061       unmark_clause(&solver->pool, i);
5062       goto done;
5063     }
5064   }
5065   i = solver->pool.size; // all done
5066  done:
5067   return i;
5068 }
5069 
5070 
5071 
5072 /*
5073  * HEURISTIC/HEAP FOR VARIABLE ELIMINATION
5074  */
5075 
5076 /*
5077  * Check whether we should consider x for elimination:
5078  * - we skip x if it's marked as "TO_KEEP" or if it has many positive and
5079  *   negative occurrences.
5080  * - the cutoff is solver->val_elim_skip (10 by default).
5081  */
pp_elim_candidate(const sat_solver_t * solver,bvar_t x)5082 static bool pp_elim_candidate(const sat_solver_t *solver, bvar_t x) {
5083   assert(x < solver->nvars);
5084 
5085   return (solver->occ[pos_lit(x)] < solver->params.var_elim_skip
5086 	  || solver->occ[neg_lit(x)] < solver->params.var_elim_skip)
5087     && !bvar_to_keep(&solver->descriptors, x);
5088 }
5089 
5090 /*
5091  * Cost of eliminating x (heuristic estimate)
5092  */
pp_elim_cost(const sat_solver_t * solver,bvar_t x)5093 static uint64_t pp_elim_cost(const sat_solver_t *solver, bvar_t x) {
5094   assert(pp_elim_candidate(solver, x));
5095   return ((uint64_t) solver->occ[pos_lit(x)]) * solver->occ[neg_lit(x)];
5096 }
5097 
5098 
5099 /*
5100  * Number of occurrences of x
5101  */
var_occs(const sat_solver_t * solver,bvar_t x)5102 static inline uint32_t var_occs(const sat_solver_t *solver, bvar_t x) {
5103   assert(x < solver->nvars);
5104   return solver->occ[pos_lit(x)] + solver->occ[neg_lit(x)];
5105 }
5106 
5107 /*
5108  * Ordering for elimination:
5109  * - elim_lt(solver, x, y) returns true if x < y for our heuristic ordering.
5110  * - we want to do cheap eliminations first (i.e., variables with one positive or
5111  *   one negative occurrences).
5112  * - for other variables, we use occ[pos_lit(x)] * occ[neg_lit(x)] as an estimate of the cost
5113  *   of eliminating x
5114  */
elim_lt(const sat_solver_t * solver,bvar_t x,bvar_t y)5115 static bool elim_lt(const sat_solver_t *solver, bvar_t x, bvar_t y) {
5116   uint32_t cx, cy, ox, oy;
5117 
5118   cx = pp_elim_cost(solver, x);
5119   ox = var_occs(solver, x);
5120   cy = pp_elim_cost(solver, y);
5121   oy = var_occs(solver, y);
5122 
5123   if (cx < ox && cy >= oy) return true;     // x cheap, y not cheap
5124   if (cy < oy && cx >= ox) return false;    // y cheap, x not cheap
5125   return cx < cy;
5126 }
5127 
5128 
5129 /*
5130  * Simpler heuristic: not used
5131  */
5132 /*
5133  * static bool elim_lt(const sat_solver_t *solver, bvar_t x, bvar_t y) {
5134  *   return pp_elim_cost(solver, x) < pp_elim_cost(solver, y);
5135  * }
5136  */
5137 
5138 
5139 /*
5140  * Move the variable at position i up the tree
5141  */
elim_heap_move_up(sat_solver_t * solver,uint32_t i)5142 static void elim_heap_move_up(sat_solver_t *solver, uint32_t i) {
5143   elim_heap_t *heap;
5144   bvar_t x, y;
5145   uint32_t j;
5146 
5147   heap = &solver->elim;
5148 
5149   assert(0 < i && i < heap->size);
5150 
5151   x = heap->data[i];
5152   for (;;) {
5153     j = i >> 1;        // parent of i
5154     if (j == 0) break; // top of the heap
5155 
5156     y = heap->data[j];
5157     if (!elim_lt(solver, x, y)) break; // x >= y: stop here
5158 
5159     // move y down into i
5160     heap->data[i] = y;
5161     heap->elim_idx[y] = i;
5162     i = j;
5163   }
5164 
5165   heap->data[i] = x;
5166   heap->elim_idx[x] = i;
5167 }
5168 
5169 
5170 /*
5171  * Move the variable at position i down the tree
5172  */
elim_heap_move_down(sat_solver_t * solver,uint32_t i)5173 static void elim_heap_move_down(sat_solver_t *solver, uint32_t i) {
5174   elim_heap_t *heap;
5175   uint32_t j;
5176   bvar_t x, y, z;
5177 
5178   heap = &solver->elim;
5179 
5180   assert(0 < i && i < heap->size);
5181 
5182   x = heap->data[i];
5183 
5184   j = i<<1; // j = left child of i. (this can't overflow since heap->size < 2^32/4)
5185 
5186   while (j < heap->size) {
5187     // y = smallest of the two children of i
5188     y = heap->data[j];
5189     if (j + 1 < heap->size) {
5190       z = heap->data[j+1];
5191       if (elim_lt(solver, z, y)) {
5192         y = z;
5193         j ++;
5194       }
5195     }
5196 
5197     // if x < y then x goes into i
5198     if (elim_lt(solver, x, y)) break;
5199 
5200     // move y up into i
5201     heap->data[i] = y;
5202     heap->elim_idx[y] = i;
5203     i = j;
5204     j <<= 1;
5205   }
5206 
5207   heap->data[i] = x;
5208   heap->elim_idx[x] = i;
5209 }
5210 
5211 
5212 /*
5213  * Move variable at position i either up or down
5214  */
elim_heap_update(sat_solver_t * solver,uint32_t i)5215 static void elim_heap_update(sat_solver_t *solver, uint32_t i) {
5216   elim_heap_move_up(solver, i);
5217   elim_heap_move_down(solver, i);
5218   check_elim_heap(solver);
5219 }
5220 
5221 
5222 /*
5223  * Check whether the heap is empty
5224  */
elim_heap_is_empty(const sat_solver_t * solver)5225 static inline bool elim_heap_is_empty(const sat_solver_t *solver) {
5226   return solver->elim.size == 1;
5227 }
5228 
5229 
5230 /*
5231  * Check whether x is in the heap
5232  */
5233 #ifndef NDEBUG
var_is_in_elim_heap(const sat_solver_t * solver,bvar_t x)5234 static inline bool var_is_in_elim_heap(const sat_solver_t *solver, bvar_t x) {
5235   assert(x < solver->nvars);
5236   return solver->elim.elim_idx[x] >= 0;
5237 }
5238 #endif
5239 
5240 
5241 /*
5242  * Remove the top variable from the heap
5243  */
elim_heap_get_top(sat_solver_t * solver)5244 static bvar_t elim_heap_get_top(sat_solver_t *solver) {
5245   elim_heap_t *heap;
5246   bvar_t x, y;
5247 
5248   heap = &solver->elim;
5249 
5250   assert(heap->size > 1);
5251 
5252   x = heap->data[1];
5253   heap->elim_idx[x] = -1;
5254   heap->size --;
5255 
5256   if (heap->size > 1) {
5257     y = heap->data[heap->size];
5258     heap->data[1] = y;
5259     heap->elim_idx[y] = 1;
5260     elim_heap_move_down(solver, 1);
5261   }
5262 
5263   check_elim_heap(solver);
5264 
5265   return x;
5266 }
5267 
5268 
5269 /*
5270  * Add variable x to the heap:
5271  * - x must not be present in the heap
5272  */
elim_heap_insert_var(sat_solver_t * solver,bvar_t x)5273 static void elim_heap_insert_var(sat_solver_t *solver, bvar_t x) {
5274   elim_heap_t *heap;
5275   uint32_t i;
5276 
5277   assert(pp_elim_candidate(solver, x));
5278 
5279   heap = &solver->elim;
5280 
5281   assert(heap->elim_idx[x] < 0); // x must not be in the heap
5282 
5283   i = heap->size;
5284   if (i == heap->capacity) {
5285     extend_elim_heap(heap);
5286   }
5287   assert(i < heap->capacity);
5288   heap->size ++;
5289   heap->data[i] = x;
5290   heap->elim_idx[x] = i;
5291   elim_heap_move_up(solver, i);
5292 
5293   check_elim_heap(solver);
5294 }
5295 
5296 
5297 /*
5298  * Remove x from the heap if it's there
5299  */
elim_heap_remove_var(sat_solver_t * solver,bvar_t x)5300 static void elim_heap_remove_var(sat_solver_t *solver, bvar_t x) {
5301   elim_heap_t *heap;
5302   int32_t i;
5303   bvar_t y;
5304 
5305   assert(x < solver->nvars);
5306 
5307   heap = &solver->elim;
5308   i = heap->elim_idx[x];
5309   if (i >= 0) {
5310     heap->elim_idx[x] = -1;
5311     heap->size --;
5312     if (heap->size > i) {
5313       y = heap->data[heap->size];
5314       heap->data[i] = y;
5315       heap->elim_idx[y] = i;
5316       elim_heap_update(solver, i);
5317     }
5318     check_elim_heap(solver);
5319   }
5320 }
5321 
5322 
5323 /*
5324  * Update: move/add x when its occurrence counts have changed
5325  */
elim_heap_update_var(sat_solver_t * solver,bvar_t x)5326 static void elim_heap_update_var(sat_solver_t *solver, bvar_t x) {
5327   int32_t i;
5328 
5329   assert(x < solver->nvars);
5330 
5331   if (var_is_unassigned(solver, x) && pp_elim_candidate(solver, x)) {
5332     i = solver->elim.elim_idx[x];
5333     if (i < 0) {
5334       elim_heap_insert_var(solver, x);
5335     } else {
5336       elim_heap_update(solver, i);
5337     }
5338   } else {
5339     elim_heap_remove_var(solver, x);
5340   }
5341 }
5342 
5343 
5344 /*
5345  * GARBAGE COLLECTION DURING PREPROCESSING
5346  */
5347 
5348 /*
5349  * Go through the pool and remove all the padding blocks
5350  * - if a clause is marked, add it to the clause queue (after the move)
5351  * - also restore the scan index
5352  */
pp_compact_clause_pool(sat_solver_t * solver)5353 static void pp_compact_clause_pool(sat_solver_t *solver) {
5354   clause_pool_t *pool;
5355   uint32_t k, n, len, end;
5356   cidx_t i, j;
5357 
5358   pool = &solver->pool;
5359 
5360   assert(clause_pool_invariant(pool) && pool->learned == pool->size);
5361 
5362   i = 0;
5363   j = 0;
5364   end = solver->scan_index;
5365   for (k=0; k<2; k++) {
5366     /*
5367      * First iteration, move the clauses that are before the scan index
5368      * Second iteration, clauses after the scan index.
5369      */
5370     while (i < end) {
5371       assert(good_clause_idx(pool, i));
5372       n = pool->data[i];
5373       if (n == 0) {
5374         // padding block, skip it
5375         i += padding_length(pool, i);
5376       } else {
5377         assert(j <= i);
5378         len = n;
5379         if ((n & CLAUSE_MARK) != 0) {
5380           // marked clause: store it in the clause queue
5381           queue_push(&solver->cqueue, j);
5382           len &= ~CLAUSE_MARK;
5383         }
5384         if (j < i) {
5385           clause_pool_move_clause(pool, j, i, len);
5386         }
5387         i += full_length(len);
5388         j += full_length(len);
5389       }
5390     }
5391     if (k == 0) {
5392       solver->scan_index = j;
5393       end = pool->size;
5394     }
5395   }
5396 
5397   assert(end == pool->size);
5398   pool->size = j;
5399   pool->learned = j;
5400   pool->available = pool->capacity - j;
5401   pool->padding = 0;
5402 
5403   assert(clause_pool_invariant(pool));
5404 }
5405 
5406 
5407 /*
5408  * Reconstruct the watch vectors after compaction
5409  */
pp_restore_watch_vectors(sat_solver_t * solver)5410 static void pp_restore_watch_vectors(sat_solver_t *solver) {
5411   uint32_t i, n;
5412   cidx_t cidx;
5413   watch_t *w;
5414 
5415   n = solver->nliterals;
5416   for (i=0; i<n; i++) {
5417     w = solver->watch[i];
5418     if (w != NULL) {
5419       reset_watch(w);
5420     }
5421   }
5422 
5423   cidx = clause_pool_first_clause(&solver->pool);
5424   while (cidx < solver->pool.size) {
5425     assert(clause_is_live(&solver->pool, cidx));
5426     n = clause_length(&solver->pool, cidx);
5427     add_clause_all_watch(solver, n, clause_literals(&solver->pool, cidx), cidx);
5428     cidx += full_length(n);
5429   }
5430 }
5431 
5432 
5433 /*
5434  * Garbage collection
5435  */
pp_collect_garbage(sat_solver_t * solver)5436 static void pp_collect_garbage(sat_solver_t *solver) {
5437 #if TRACE
5438   fprintf(stderr, "gc: pool size = %"PRIu32", literals = %"PRIu32", padding = %"PRIu32"\n",
5439           solver->pool.size, solver->pool.num_prob_literals, solver->pool.padding);
5440 #endif
5441   check_clause_pool_counters(&solver->pool);
5442   reset_queue(&solver->cqueue);
5443   pp_compact_clause_pool(solver);
5444   pp_restore_watch_vectors(solver);
5445   check_clause_pool_counters(&solver->pool);
5446 #if TRACE
5447   fprintf(stderr, "done: pool size = %"PRIu32", literals = %"PRIu32", padding = %"PRIu32"\n",
5448           solver->pool.size, solver->pool.num_prob_literals, solver->pool.padding);
5449 #endif
5450 }
5451 
5452 
5453 /*
5454  * Heuristic for garbage collection:
5455  * - at least 10000 cells wasted in the clause database
5456  * - at least 12.5% of wasted cells
5457  */
pp_try_gc(sat_solver_t * solver)5458 static void pp_try_gc(sat_solver_t *solver) {
5459   if (solver->pool.padding > 10000 && solver->pool.padding > solver->pool.size >> 3) {
5460     pp_collect_garbage(solver);
5461   }
5462 }
5463 
5464 
5465 /*
5466  * REMOVE PURE AND UNIT LITERALS
5467  */
5468 
5469 /*
5470  * Push pure or unit literal l into the queue
5471  * - l must not be assigned
5472  * - the function assigns l to true
5473  * - tag = either ATAG_UNIT or ATAG_PURE
5474  */
pp_push_literal(sat_solver_t * solver,literal_t l,antecedent_tag_t tag)5475 static void pp_push_literal(sat_solver_t *solver, literal_t l, antecedent_tag_t tag) {
5476   bvar_t v;
5477 
5478   assert(l < solver->nliterals);
5479   assert(lit_is_unassigned(solver, l));
5480   assert(solver->decision_level == 0);
5481   assert(tag == ATAG_UNIT || tag == ATAG_PURE);
5482 
5483   queue_push(&solver->lqueue, l);
5484 
5485   solver->value[l] = VAL_TRUE;
5486   solver->value[not(l)] = VAL_FALSE;
5487 
5488   v = var_of(not(l));
5489   solver->ante_tag[v] = tag;
5490   solver->ante_data[v] = 0;
5491   solver->level[v] = 0;
5492 
5493   if (solver->elim.data != NULL) {
5494     elim_heap_remove_var(solver, v);
5495   }
5496 }
5497 
pp_push_pure_literal(sat_solver_t * solver,literal_t l)5498 static inline void pp_push_pure_literal(sat_solver_t *solver, literal_t l) {
5499   pp_push_literal(solver, l, ATAG_PURE);
5500   solver->stats.pp_pure_lits ++;
5501 }
5502 
pp_push_unit_literal(sat_solver_t * solver,literal_t l)5503 static inline void pp_push_unit_literal(sat_solver_t *solver, literal_t l) {
5504   pp_push_literal(solver, l, ATAG_UNIT);
5505   solver->stats.pp_unit_lits ++;
5506 }
5507 
5508 
5509 /*
5510  * Decrement the occurrence counter of l.
5511  * - if occ[l] goes to zero, add not(l) to the queue as a pure literal (unless
5512  *   l is already assigned or eliminated).
5513  */
pp_decrement_occ(sat_solver_t * solver,literal_t l)5514 static void pp_decrement_occ(sat_solver_t *solver, literal_t l) {
5515   assert(solver->occ[l] > 0);
5516   solver->occ[l] --;
5517   if (solver->occ[l] == 0 && solver->occ[not(l)] > 0 && !lit_is_assigned(solver, l)) {
5518     pp_push_pure_literal(solver, not(l));
5519   }
5520 }
5521 
5522 /*
5523  * Decrement occ counts for all literals in a[0 ... n-1]
5524  */
pp_decrement_occ_counts(sat_solver_t * solver,literal_t * a,uint32_t n)5525 static void pp_decrement_occ_counts(sat_solver_t *solver, literal_t *a, uint32_t n) {
5526   uint32_t i;
5527 
5528   if (solver->elim.data == NULL) {
5529     // no elimination heap: update only the occurrence counters
5530     for (i=0; i<n; i++) {
5531       pp_decrement_occ(solver, a[i]);
5532     }
5533   } else {
5534     // update the occurrence counters and the elimination heap
5535     for (i=0; i<n; i++) {
5536       pp_decrement_occ(solver, a[i]);
5537       elim_heap_update_var(solver, var_of(a[i]));
5538     }
5539   }
5540 }
5541 
5542 /*
5543  * Increment occ counts for all literals in a[0 ... n-1]
5544  */
pp_increment_occ_counts(sat_solver_t * solver,literal_t * a,uint32_t n)5545 static void pp_increment_occ_counts(sat_solver_t *solver, literal_t *a, uint32_t n) {
5546   uint32_t i;
5547 
5548   if (solver->elim.data == NULL) {
5549     // no elimination heap: update only the occurrence counters
5550     for (i=0; i<n; i++) {
5551       solver->occ[a[i]] ++;
5552     }
5553   } else {
5554     // update the occurrence counters and the elimination heap
5555     for (i=0; i<n; i++) {
5556       solver->occ[a[i]] ++;
5557       elim_heap_update_var(solver, var_of(a[i]));
5558     }
5559   }
5560 }
5561 
5562 /*
5563  * Delete clause cidx and update occ counts
5564  */
pp_remove_clause(sat_solver_t * solver,cidx_t cidx)5565 static void pp_remove_clause(sat_solver_t *solver, cidx_t cidx) {
5566   literal_t *a;
5567   uint32_t n;
5568 
5569   assert(clause_is_live(&solver->pool, cidx));
5570 
5571   n = clause_length(&solver->pool, cidx);
5572   a = clause_literals(&solver->pool, cidx);
5573   pp_decrement_occ_counts(solver, a, n);
5574   clause_pool_delete_clause(&solver->pool, cidx);
5575   solver->stats.pp_clauses_deleted ++;
5576 }
5577 
5578 /*
5579  * Visit clause at cidx and remove all assigned literals
5580  * - if the clause is true remove it
5581  * - otherwise remove all false literals from the clause
5582  * - if the result is empty, record this (solver->has_empty_clause := true)
5583  * - if the result is a unit clause, push the corresponding literal into the queue
5584  */
pp_visit_clause(sat_solver_t * solver,cidx_t cidx)5585 static void pp_visit_clause(sat_solver_t *solver, cidx_t cidx) {
5586   uint32_t i, j, n;
5587   literal_t *a;
5588   literal_t l;
5589   bool true_clause;
5590 
5591   assert(clause_is_live(&solver->pool, cidx));
5592 
5593   n = clause_length(&solver->pool, cidx);
5594   a = clause_literals(&solver->pool, cidx);
5595   true_clause = false;
5596 
5597   j = 0;
5598   for (i=0; i<n; i++) {
5599     l = a[i];
5600     switch (lit_value(solver, l)) {
5601     case VAL_TRUE:
5602       true_clause = true; // fall-through intended to keep the occ counts accurate
5603     case VAL_FALSE:
5604       assert(solver->occ[l] > 0);
5605       solver->occ[l] --;
5606       break;
5607 
5608     default:
5609       a[j] = l;
5610       j ++;
5611       break;
5612     }
5613   }
5614 
5615   if (true_clause) {
5616     pp_decrement_occ_counts(solver, a, j);
5617     clause_pool_delete_clause(&solver->pool, cidx);
5618     solver->stats.pp_clauses_deleted ++;
5619   } else if (j == 0) {
5620     add_empty_clause(solver);
5621     clause_pool_delete_clause(&solver->pool, cidx);
5622   } else if (j == 1) {
5623     pp_push_unit_literal(solver, a[0]);
5624     clause_pool_delete_clause(&solver->pool, cidx);
5625   } else {
5626     clause_pool_shrink_clause(&solver->pool, cidx, j);
5627     set_clause_signature(&solver->pool, cidx);
5628     clause_queue_push(solver, cidx);
5629   }
5630 }
5631 
5632 
5633 
5634 /*
5635  * Delete all the clauses that contain l (because l is true)
5636  */
pp_remove_true_clauses(sat_solver_t * solver,literal_t l)5637 static void pp_remove_true_clauses(sat_solver_t *solver, literal_t l) {
5638   watch_t *w;
5639   uint32_t i, n, k;
5640 
5641   assert(lit_is_true(solver, l));
5642 
5643   w = solver->watch[l];
5644   if (w != NULL) {
5645     n = w->size;
5646     for (i=0; i<n; i++) {
5647       k = w->data[i];
5648       if (clause_is_live(&solver->pool, k)) {
5649         pp_remove_clause(solver, k);
5650       }
5651     }
5652     // delete w
5653     safe_free(w);
5654     solver->watch[l] = NULL;
5655   }
5656 }
5657 
5658 
5659 /*
5660  * Visit all the clauses that contain l (because l is false)
5661  */
pp_visit_clauses_of_lit(sat_solver_t * solver,literal_t l)5662 static void pp_visit_clauses_of_lit(sat_solver_t *solver, literal_t l) {
5663   watch_t *w;
5664   uint32_t i, n, k;
5665 
5666   assert(lit_is_false(solver, l));
5667 
5668   w = solver->watch[l];
5669   if (w != NULL) {
5670     n = w->size;
5671     for (i=0; i<n; i++) {
5672       k = w->data[i];
5673       if (clause_is_live(&solver->pool, k)) {
5674         pp_visit_clause(solver, k);
5675         if (solver->has_empty_clause) break;
5676       }
5677     }
5678     // delete w
5679     safe_free(w);
5680     solver->watch[l] = NULL;
5681   }
5682 }
5683 
5684 
5685 
5686 /*
5687  * Initialize the queue: store all unit and pure literals.
5688  */
collect_unit_and_pure_literals(sat_solver_t * solver)5689 static void collect_unit_and_pure_literals(sat_solver_t *solver) {
5690   uint32_t i, n;
5691   uint32_t pos_occ, neg_occ;
5692 
5693   assert(queue_is_empty(&solver->lqueue));
5694 
5695   n = solver->nvars;
5696   for (i=1; i<n; i++) {
5697     switch (var_value(solver, i)) {
5698     case VAL_TRUE:
5699       assert(solver->ante_tag[i] == ATAG_UNIT);
5700       queue_push(&solver->lqueue, pos_lit(i));
5701       solver->stats.pp_unit_lits ++;
5702       break;
5703 
5704     case VAL_FALSE:
5705       assert(solver->ante_tag[i] == ATAG_UNIT);
5706       queue_push(&solver->lqueue, neg_lit(i));
5707       solver->stats.pp_unit_lits ++;
5708       break;
5709 
5710     default:
5711       pos_occ = solver->occ[pos_lit(i)];
5712       neg_occ = solver->occ[neg_lit(i)];
5713       /*
5714        * if i doesn't occur at all then both pos_occ/neg_occ are zero.
5715        * we still record neg_lit(i) as a pure literal in this case to force
5716        * i to be assigned.
5717        */
5718       if (pos_occ == 0) {
5719         pp_push_pure_literal(solver, neg_lit(i));
5720       } else if (neg_occ == 0) {
5721         pp_push_pure_literal(solver, pos_lit(i));
5722       }
5723       break;
5724     }
5725   }
5726 }
5727 
5728 
5729 /*
5730  * Process the queue:
5731  * - return false if a conflict is detected
5732  * - return true otherwise
5733  */
pp_empty_queue(sat_solver_t * solver)5734 static bool pp_empty_queue(sat_solver_t *solver) {
5735   literal_t l;
5736 
5737   while (! queue_is_empty(&solver->lqueue)) {
5738     l = queue_pop(&solver->lqueue);
5739     assert(lit_is_true(solver, l));
5740     assert(solver->ante_tag[var_of(l)] == ATAG_UNIT ||
5741            solver->ante_tag[var_of(l)] == ATAG_PURE);
5742     pp_remove_true_clauses(solver, l);
5743     if (solver->ante_tag[var_of(l)] == ATAG_UNIT) {
5744       pp_visit_clauses_of_lit(solver, not(l));
5745       if (solver->has_empty_clause) {
5746         reset_queue(&solver->lqueue);
5747         return false;
5748       }
5749     }
5750   }
5751 
5752   return true;
5753 }
5754 
5755 
5756 /*
5757  * EQUIVALENT DEFINITIONS
5758  */
5759 
5760 /*
5761  * Process l1 == l2 (when l1 < l2)
5762  */
process_lit_equiv(sat_solver_t * solver,literal_t l1,literal_t l2)5763 static void process_lit_equiv(sat_solver_t *solver, literal_t l1, literal_t l2) {
5764   uint32_t rank;
5765 
5766   assert(l1 < l2);
5767 
5768   if (var_of(l1) == const_bvar) {
5769     assert(l1 == true_literal || l1 == false_literal);
5770     // either l2 := true or l2 := false
5771     if (l1 == false_literal) l2 = not(l2);
5772     if (solver->verbosity >= 3) fprintf(stderr, "c   lit equiv: unit literal %"PRId32"\n", l2);
5773     vector_push(&solver->subst_units, l2);
5774   } else if (l1 == not(l2)) {
5775     add_empty_clause(solver);
5776   } else {
5777     // subst[l2] := l1
5778     set_lit_subst(solver, l2, l1);
5779     rank = lit_rank(solver, l2);
5780     if (rank > lit_rank(solver, l1)) {
5781       update_lit_rank(solver, l1, rank);
5782     }
5783     if (solver->verbosity >= 6) {
5784       fprintf(stderr, "c   lit equiv: subst[%"PRId32"] := %"PRId32"\n", l2, l1);
5785     }
5786   }
5787 }
5788 
5789 /*
5790  * Process equivalence: l1 == l2
5791  * - if l1 == not(l2): mark the whole thing unsat (empty clause)
5792  * - if l1 or l2 is true or false literal, store an entry in solver->subst_units
5793  * - otherwise add subst[l1] := l2 or subst[l2] := l1
5794  */
literal_equiv(sat_solver_t * solver,literal_t l1,literal_t l2)5795 static void literal_equiv(sat_solver_t *solver, literal_t l1, literal_t l2) {
5796   // provisional: we apply substitutions first
5797   l1 = full_lit_subst(solver, l1);
5798   l2 = full_lit_subst(solver, l2);
5799   if (l1 == l2) return;
5800 
5801   solver->stats.equivs ++;
5802   if (l1 == not(l2)) {
5803     add_empty_clause(solver);
5804     fprintf(stderr, "c   lit equiv: empty clause\n");
5805   } else if (l1 < l2) {
5806     process_lit_equiv(solver, l1, l2);
5807   } else {
5808     process_lit_equiv(solver, l2, l1);
5809   }
5810 }
5811 
5812 
5813 /*
5814  * Apply literal substitution to a truth table
5815  */
apply_subst_to_ttbl(const sat_solver_t * solver,ttbl_t * tt)5816 static void apply_subst_to_ttbl(const sat_solver_t *solver, ttbl_t *tt) {
5817   uint32_t i;
5818   literal_t l;
5819 
5820   for (i=0; i<tt->nvars; i++) {
5821     l = full_var_subst(solver, tt->label[i]);
5822     tt->label[i] = nsat_base_literal(solver, l);
5823   }
5824   normalize_truth_table(tt);
5825 }
5826 
5827 
5828 
5829 /*
5830  * Get x's definition and apply the substitution
5831  * - return true if x is defined by a gate and if the result is a binary gate
5832  * - store the truth table for x (after substitution) in tt
5833  */
bvar_has_binary_def(const sat_solver_t * solver,bvar_t x,ttbl_t * tt)5834 static bool bvar_has_binary_def(const sat_solver_t *solver, bvar_t x, ttbl_t *tt) {
5835   uint32_t i;
5836 
5837   if (bvar_is_gate(&solver->descriptors, x)) {
5838     i = bvar_get_gate(&solver->descriptors, x);
5839     get_bgate(&solver->gates, i, tt);
5840     apply_subst_to_ttbl(solver, tt);
5841     return tt->nvars == 2;
5842   }
5843 
5844   return false;
5845 }
5846 
5847 
5848 /*
5849  * If we have  x = f(y, z) and y = g(t, u)  rewrite x to f(g(t, u), z)
5850  * - tt1 is the truth table for f(y, z)
5851  * - return true if the rewrite succeeds, false otherwise
5852  * - store the truth table for f(g(t, u), z) into *tt
5853  */
bvar_rewrites1(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5854 static bool bvar_rewrites1(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5855   ttbl_t tt2;
5856 
5857   if (bvar_has_binary_def(solver, tt1->label[0], &tt2)) {
5858     // tt2 = truth table for g(t, u)
5859     compose_ttbl_left(tt1, &tt2, tt);
5860     return true;
5861   }
5862 
5863   return false;
5864 }
5865 
5866 /*
5867  * Variant: x = f(y, z) and z = g(t, u) --> x = f(y, g(t, u))
5868  */
bvar_rewrites2(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5869 static bool bvar_rewrites2(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5870   ttbl_t tt2;
5871 
5872   if (bvar_has_binary_def(solver, tt1->label[1], &tt2)) {
5873     // tt2 = truth table for g(t, u)
5874     compose_ttbl_right(tt1, &tt2, tt);
5875     return true;
5876   }
5877 
5878   return false;
5879 }
5880 
5881 
5882 /*
5883  * Rewrite 3:
5884  *   x = f(y, z)
5885  *   y = g(a, b)
5886  *   z = h(c, d)
5887  *   a = c or b = c or a = d or b = d.
5888  */
bvar_rewrites3(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5889 static bool bvar_rewrites3(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5890   ttbl_t tt2;
5891   ttbl_t tt3;
5892 
5893   if (bvar_has_binary_def(solver, tt1->label[0], &tt2) &&
5894       bvar_has_binary_def(solver, tt1->label[1], &tt3)) {
5895     // tt2 stores g(a, b) and tt3 stores h(c, d)
5896     return compose_ttbl_left_right(tt1, &tt2, &tt3, tt);
5897   }
5898   return false;
5899 }
5900 
5901 
5902 /*
5903  * Rewrite 4:
5904  *   x = f(y, z)
5905  *   y = g(a, b)
5906  *   z rewrites to h(c, d, e) by rewrite3
5907  *   { a, b } is a subset of { c, d, e }
5908  */
bvar_rewrites4(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5909 static bool bvar_rewrites4(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5910   ttbl_t tt2;
5911   ttbl_t tt3;
5912   ttbl_t tt4;
5913 
5914   if (bvar_has_binary_def(solver, tt1->label[0], &tt2) &&
5915       bvar_has_binary_def(solver, tt1->label[1], &tt3) &&
5916       bvar_rewrites3(solver, &tt3, &tt4) && tt4.nvars >= 2) {
5917     return compose_ttbl_left_right(tt1, &tt2, &tt4, tt);
5918   }
5919   return false;
5920 }
5921 
5922 /*
5923  * Symmetric case:
5924  *    x = f(y, z)
5925  *    y rewrites to g(a, b, c) by rewrite3
5926  *    z = h(d, e)
5927  *    { d, e } is a subset of { a, b, c}
5928  */
bvar_rewrites5(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5929 static bool bvar_rewrites5(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5930   ttbl_t tt2;
5931   ttbl_t tt3;
5932   ttbl_t tt4;
5933 
5934   if (bvar_has_binary_def(solver, tt1->label[0], &tt2) &&
5935       bvar_has_binary_def(solver, tt1->label[1], &tt3) &&
5936       bvar_rewrites3(solver, &tt2, &tt4) && tt4.nvars >= 2) {
5937     return compose_ttbl_left_right(tt1, &tt4, &tt3, tt);
5938   }
5939   return false;
5940 }
5941 
5942 
5943 /*
5944  * Last rewrite:
5945  *    x = f(y, z)
5946  *    y rewrites to g(a, b, c)
5947  *    z rewrites to h(a, b, c)
5948  */
bvar_rewrites6(const sat_solver_t * solver,const ttbl_t * tt1,ttbl_t * tt)5949 static bool bvar_rewrites6(const sat_solver_t *solver, const ttbl_t *tt1, ttbl_t *tt) {
5950   ttbl_t tt2;
5951   ttbl_t tt3;
5952   ttbl_t tt4;
5953   ttbl_t tt5;
5954 
5955   if (bvar_has_binary_def(solver, tt1->label[0], &tt2) &&
5956       bvar_has_binary_def(solver, tt1->label[1], &tt3) &&
5957       bvar_rewrites3(solver, &tt2, &tt4) && tt4.nvars >= 2 &&
5958       bvar_rewrites3(solver, &tt3, &tt5) && tt5.nvars >= 2) {
5959     return compose_ttbl_left_right(tt1, &tt4, &tt5, tt);
5960   }
5961 
5962   return false;
5963 }
5964 
5965 /*
5966  * Process equality l0 = tt
5967  * - if tt is mapped to some literal l, merge l and l0
5968  * - otherwise if test_only is false, add the mapping tt -> l0 to map
5969  * - w is a string used to report message
5970  */
process_lit_eq_ttbl(sat_solver_t * solver,gate_hmap_t * map,literal_t l0,const ttbl_t * tt,bool test_only,const char * w)5971 static void process_lit_eq_ttbl(sat_solver_t *solver, gate_hmap_t *map, literal_t l0,
5972 				const ttbl_t *tt, bool test_only, const char *w) {
5973   literal_t l;
5974 
5975   if (solver->verbosity >= 6) {
5976     fprintf(stderr, "c   %s: %c%"PRId32" == ", w, pol(l0), var_of(l0));
5977     show_tt(tt);
5978   }
5979 
5980   l = gate_hmap_find_ttbl(map, tt);
5981   if (l != null_literal) {
5982     if (l != l0) {
5983       if (solver->verbosity >= 4) {
5984 	fprintf(stderr, "c   %s: %"PRId32" == %"PRId32"\n", w, l, l0);
5985       }
5986       literal_equiv(solver, l, l0);
5987     }
5988   } else if (! test_only) {
5989     gate_hmap_add_ttbl(map, tt, l0);
5990   }
5991 }
5992 
5993 /*
5994  * Apply rewriting:
5995  * - l0 literal equal to the truth table tx
5996  * - tx must be normalized and binary
5997  */
try_rewrite_binary_gate(sat_solver_t * solver,literal_t l0,const ttbl_t * tx,gate_hmap_t * map)5998 static void try_rewrite_binary_gate(sat_solver_t *solver, literal_t l0, const ttbl_t *tx, gate_hmap_t *map) {
5999   ttbl_t r;
6000 
6001   assert(tx->nvars == 2);
6002 
6003   if (bvar_rewrites6(solver, tx, &r)) {
6004     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite6");
6005     return;
6006   }
6007 
6008   if (bvar_rewrites5(solver, tx, &r)) {
6009     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite5");
6010     return;
6011   }
6012 
6013   if (bvar_rewrites4(solver, tx, &r)) {
6014     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite4");
6015     return;
6016   }
6017 
6018   if (bvar_rewrites3(solver, tx, &r)) {
6019     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite3");
6020     return;
6021   }
6022 
6023   if (bvar_rewrites2(solver, tx, &r)) {
6024     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite2");
6025     return;
6026   }
6027 
6028   if (bvar_rewrites1(solver, tx, &r)) {
6029     process_lit_eq_ttbl(solver, map, l0, &r, false, "rewrite1");
6030     return;
6031   }
6032 }
6033 
6034 /*
6035  * Search for equivalent definitions
6036  * - level 0: check only for gate equivalence
6037  * - level 1: gate equivalence & equivalence with true/false literal
6038  * - level 2: also check for equality between literals
6039  */
try_equivalent_vars(sat_solver_t * solver,uint32_t level)6040 static void try_equivalent_vars(sat_solver_t *solver, uint32_t level) {
6041   gate_hmap_t test;
6042   ttbl_t tt;
6043   uint32_t i, n;
6044   literal_t l0, l1;
6045 
6046   if (solver->verbosity >= 10) {
6047     show_subst(solver);
6048   }
6049 
6050   init_gate_hmap(&test, 0);
6051 
6052   n = solver->descriptors.size;
6053   for (i=0; i<n; i++) {
6054     l0 = full_var_subst(solver, i);
6055     l0 = nsat_base_literal(solver, l0);
6056     if (lit_is_active(solver, l0) && gate_for_bvar(solver, i, &tt)) {
6057       apply_subst_to_ttbl(solver, &tt);
6058       switch (tt.nvars) {
6059       case 0:
6060 	if (level >= 1) {
6061 	  l1 = literal_of_ttbl0(&tt);
6062 	  if (solver->verbosity >= 3) {
6063 	    fprintf(stderr, "c  var %"PRId32" simplifies to constant: %"PRId32" == %"PRId32"\n", i, l0, l1);
6064 	  }
6065 	  literal_equiv(solver, l0, l1);
6066 	}
6067 	break;
6068 
6069       case 1:
6070 	if (level >= 2) {
6071 	  l1 = literal_of_ttbl1(&tt);
6072 	  if (l0 != l1 && !lit_is_eliminated(solver, l1)) {
6073 	    if (solver->verbosity >= 3) {
6074 	      fprintf(stderr, "c  var %"PRId32" simplifies to literal: %"PRId32" == %"PRId32"\n", i, l0, l1);
6075 	    }
6076 	    literal_equiv(solver, l0, l1);
6077 	  }
6078 	}
6079 	break;
6080 
6081       default:
6082 	process_lit_eq_ttbl(solver, &test, l0, &tt, false, "gate equiv");
6083 	if (tt.nvars == 2) {
6084 	  try_rewrite_binary_gate(solver, l0, &tt, &test);
6085 	}
6086 	break;
6087       }
6088 
6089       if (solver->has_empty_clause) break;
6090     }
6091   }
6092 
6093   delete_gate_hmap(&test);
6094 }
6095 
6096 
6097 
6098 /*
6099  * VARIABLE SUBSTITUTION
6100  */
6101 
6102 /*
6103  * Decrement occ counts of a[0 ... n-1]
6104  * This is like pp_decrement_occ_counts but doesn't try to detect
6105  * pure literals.
6106  */
pp_simple_decrement_occ_counts(sat_solver_t * solver,literal_t * a,uint32_t n)6107 static void pp_simple_decrement_occ_counts(sat_solver_t *solver, literal_t *a, uint32_t n) {
6108   uint32_t i;
6109 
6110   for (i=0; i<n; i++) {
6111     assert(solver->occ[a[i]] > 0);
6112     solver->occ[a[i]] --;
6113   }
6114 }
6115 
6116 /*
6117  * Apply the scc-based substitution to the clause that starts at cidx
6118  * - if the clause simplifies to a unit clause, add the literal to
6119  *   the unit-literal queue
6120  */
pp_apply_subst_to_clause(sat_solver_t * solver,cidx_t cidx)6121 static void pp_apply_subst_to_clause(sat_solver_t *solver, cidx_t cidx) {
6122   literal_t *a;
6123   vector_t *b;
6124   uint32_t i, n;
6125   literal_t l;
6126 
6127   assert(clause_is_live(&solver->pool, cidx));
6128 
6129   n = clause_length(&solver->pool, cidx);
6130   a = clause_literals(&solver->pool, cidx);
6131 
6132   // apply substitution to all literals in a[0 ... n-1]
6133   // store the result in vector b
6134   b = &solver->buffer;
6135   reset_vector(b);
6136 
6137   for (i=0; i<n; i++) {
6138     l = full_lit_subst(solver, a[i]);
6139     assert(! lit_is_eliminated(solver, l));
6140     switch (solver->value[l] & 3) {
6141     case VAL_FALSE:
6142       break;
6143 
6144     case VAL_UNDEF_TRUE:
6145     case VAL_UNDEF_FALSE:
6146       vector_push(b, l);
6147       mark_false_lit(solver, l);
6148       break;
6149 
6150     case VAL_TRUE:
6151       goto done; // the clause is true
6152     }
6153   }
6154 
6155  done:
6156   clear_false_lits(solver, b->size, (literal_t *) b->data);
6157 
6158   /*
6159    * Decrement occ counts and delete the clause.
6160    * We don't want to use pp_remove_clauses because it has side effects
6161    * that are not correct here (i.e., finding pure literals).
6162    */
6163   pp_simple_decrement_occ_counts(solver, a, n);
6164   clause_pool_delete_clause(&solver->pool, cidx);
6165 
6166   /*
6167    * b = new clause after substitution.
6168    * if i < n, the clause is true.
6169    */
6170   if (i < n) {
6171     solver->stats.pp_clauses_deleted ++;
6172     return; // clause b is true. Nothing more to do
6173   }
6174 
6175   /*
6176    * Store b as a new problem clause
6177    */
6178   n = b->size;
6179   if (n == 0) {
6180     add_empty_clause(solver);
6181   } else if (n == 1) {
6182     // unit clause
6183     pp_push_unit_literal(solver, b->data[0]);
6184   } else {
6185     // regular clause
6186     assert(n >= 2);
6187 
6188     uint_array_sort(b->data, n); // keep the clause sorted
6189     cidx = clause_pool_add_problem_clause(&solver->pool, n, (literal_t *) b->data);
6190     add_clause_all_watch(solver, n, (literal_t *) b->data, cidx);
6191     set_clause_signature(&solver->pool, cidx);
6192   }
6193   pp_increment_occ_counts(solver, (literal_t *) b->data, n);
6194 }
6195 
6196 
6197 /*
6198  * Apply the substitution to all the clauses in vector w
6199  */
pp_apply_subst_to_watch_vector(sat_solver_t * solver,watch_t * w)6200 static void pp_apply_subst_to_watch_vector(sat_solver_t *solver, watch_t *w) {
6201   uint32_t i, n, k;
6202 
6203   n = w->size;
6204   for (i=0; i<n; i++) {
6205     k = w->data[i];
6206     if (clause_is_live(&solver->pool, k)) {
6207       pp_apply_subst_to_clause(solver, k);
6208       if (solver->has_empty_clause) return;
6209     }
6210   }
6211 }
6212 
6213 /*
6214  * Apply the substitution to all clauses that contain variable x
6215  * - then delete the watch vectors for x
6216  */
pp_apply_subst_to_variable(sat_solver_t * solver,bvar_t x)6217 static void pp_apply_subst_to_variable(sat_solver_t *solver, bvar_t x) {
6218   watch_t *w;
6219 
6220   assert(solver->ante_tag[x] == ATAG_SUBST);
6221 
6222   w = solver->watch[pos_lit(x)];
6223   if (w != NULL) {
6224     pp_apply_subst_to_watch_vector(solver, w);
6225     safe_free(w);
6226     solver->watch[pos_lit(x)] = NULL;
6227   }
6228 
6229   w = solver->watch[neg_lit(x)];
6230   if (w != NULL) {
6231     pp_apply_subst_to_watch_vector(solver, w);
6232     safe_free(w);
6233     solver->watch[neg_lit(x)] = NULL;
6234   }
6235 
6236   //  pp_try_gc(solver);
6237 }
6238 
6239 /*
6240  * Process unit literals found by equivalence checks
6241  * - set solver->has_empty_clause to true if a conflict is detected
6242  */
pp_process_subst_units(sat_solver_t * solver)6243 static void pp_process_subst_units(sat_solver_t *solver) {
6244   vector_t *v;
6245   uint32_t i, n;
6246   literal_t l;
6247 
6248   v = &solver->subst_units;
6249   n = v->size;
6250   for (i=0; i<n; i++) {
6251     l = full_lit_subst(solver, v->data[i]);
6252     if (lit_is_unassigned(solver, l)) {
6253       pp_push_unit_literal(solver, l);
6254     }
6255   }
6256   pp_empty_queue(solver);
6257   reset_vector(v);
6258 }
6259 
6260 
6261 /*
6262  * Compute the SCCs from the binary clauses
6263  * - return false if a conflict is detected
6264  * - return true otherwise
6265  */
pp_scc_simplification(sat_solver_t * solver)6266 static bool pp_scc_simplification(sat_solver_t *solver) {
6267   vector_t *v;
6268   uint32_t i, n, n0;
6269   bvar_t x;
6270 
6271   compute_sccs(solver);
6272   if (solver->has_empty_clause) {
6273     reset_vector(&solver->subst_vars);
6274     return false;
6275   }
6276 
6277   assert(solver->subst_units.size == 0);
6278 
6279   v = &solver->subst_vars;
6280   n = v->size;
6281   if (n > 0) {
6282     n0 = n;
6283     if (solver->verbosity >= 3) {
6284       fprintf(stderr, "c  scc %"PRIu32" variable substitutions\n", n);
6285     }
6286     for (;;) {
6287       try_equivalent_vars(solver, 2);
6288       if (n == v->size || solver->has_empty_clause) break;
6289       n = v->size;
6290     }
6291 
6292     // equivalent_vars may add more variables to vector v
6293     if (solver->verbosity >= 3 && n > n0) {
6294       fprintf(stderr, "c  eq  %"PRIu32" substitutions\n", n - n0);
6295     }
6296 
6297     // process the substitutions
6298     n = v->size;
6299     for (i=0; i<n; i++) {
6300       x = v->data[i];
6301       assert(solver->ante_tag[x] == ATAG_SUBST);
6302       // force a value for x so that it doesn't get considered in
6303       // other simplification procedures
6304       solver->value[pos_lit(x)] = VAL_TRUE;
6305       solver->value[neg_lit(x)] = VAL_FALSE;
6306 
6307       // save clause l := l0 to reconstruct the model: l0 = ante_data[x], l = pos_lit(x)
6308       clause_vector_save_subst_clause(&solver->saved_clauses, solver->ante_data[x], pos_lit(x));
6309 
6310       pp_apply_subst_to_variable(solver, x);
6311     }
6312     reset_vector(v);
6313 
6314     // process the unit literals
6315     solver->stats.pp_subst_units += solver->subst_units.size;
6316     pp_process_subst_units(solver);
6317   }
6318 
6319   // substitution may reduce a clause to empty
6320   return !solver->has_empty_clause;
6321 }
6322 
6323 
6324 
6325 /*
6326  * SUBSUMPTION/STRENGTHENING
6327  */
6328 
6329 #ifndef NDEBUG
6330 /*
6331  * In preprocessing, all clauses and watch vectors should be sorted
6332  */
clause_is_sorted(const sat_solver_t * solver,cidx_t cidx)6333 static bool clause_is_sorted(const sat_solver_t *solver, cidx_t cidx) {
6334   uint32_t i, n;
6335   literal_t *a;
6336 
6337   n = clause_length(&solver->pool, cidx);
6338   a = clause_literals(&solver->pool, cidx);
6339   for (i=1; i<n; i++) {
6340     if (a[i-1] >= a[i]) {
6341       return false;
6342     }
6343   }
6344   return true;
6345 }
6346 
watch_vector_is_sorted(const watch_t * w)6347 static bool watch_vector_is_sorted(const watch_t *w) {
6348   uint32_t i, n;
6349 
6350   if (w != NULL) {
6351     n = w->size;
6352     for (i=1; i<n; i++) {
6353       if (w->data[i-1] >= w->data[i]) {
6354         return false;
6355       }
6356     }
6357   }
6358 
6359   return true;
6360 }
6361 
6362 #endif
6363 
6364 
6365 
6366 /*
6367  * Search for variable x in array a[l, ..., m-1]
6368  * - a must be sorted in increasing order
6369  * - must have l <= m (also m <= MAX_CLAUSE_SIZE)
6370  * - returns m is there's no literal in a with variable x
6371  * - returns an index i such that a[i] is pos_lit(x) or neg_lit(x) otherwise
6372  */
pp_search_for_var(bvar_t x,uint32_t l,uint32_t m,const literal_t * a)6373 static uint32_t pp_search_for_var(bvar_t x, uint32_t l, uint32_t m, const literal_t *a) {
6374   uint32_t i, h;
6375   bvar_t y;
6376 
6377   assert(l <= m);
6378 
6379   h = m;
6380   while (l < h) {
6381     i = (l + h) >> 1; // can't overflow since h <= MAX_CLAUSE_SIZE
6382     assert(l <= i && i < h);
6383     y = var_of(a[i]);
6384     if (x == y) return i;
6385     if (x < y) {
6386       h = i;
6387     } else {
6388       l = i+1;
6389     }
6390   }
6391 
6392   // not found
6393   return m;
6394 }
6395 
6396 /*
6397  * Remove the k-th literal from a[0... n-1]
6398  */
pp_remove_literal(uint32_t n,uint32_t k,literal_t * a)6399 static void pp_remove_literal(uint32_t n, uint32_t k, literal_t *a) {
6400   assert(k < n);
6401   n --;
6402   while (k < n) {
6403     a[k] = a[k+1];
6404     k ++;
6405   }
6406 }
6407 
6408 /*
6409  * Remove clause cidx from watch[l]
6410  * - cidx must occur in the watch vector
6411  * - we mark cidx as a dead clause by replacing it with cidx + 2
6412  */
pp_remove_clause_from_watch(sat_solver_t * solver,literal_t l,cidx_t cidx)6413 static void pp_remove_clause_from_watch(sat_solver_t *solver, literal_t l, cidx_t cidx) {
6414   watch_t *w;
6415   uint32_t i, j, n;
6416 
6417   w = solver->watch[l];
6418   assert(w != NULL && watch_vector_is_sorted(w));
6419 
6420   n = w->size;
6421   i = 0;
6422   assert(i < n);
6423   for (;;) {
6424     j = (i + n) >> 1;
6425     assert(i <= j && j < n);
6426     if (w->data[j] == cidx) break;
6427     if (w->data[j] < cidx) {
6428       i = j;
6429     } else {
6430       n = j;
6431     }
6432   }
6433   // replace cidx by cidx + 2 to keep the watch vector sorted and
6434   // make sure all elements are multiple of 2
6435   w->data[j] = cidx + 2;
6436 }
6437 
6438 /*
6439  * Check whether clause a[0 ... n-1] subsumes or strengthens clause cidx:
6440  * - subsumes means that all literals a[0] ... a[n-1] occur in clause cidx
6441  * - strengthens means that all literals a[0] .. a[n-1] but one occur
6442  *   in cidx and that (not a[i]) occurs in cidx.
6443  *
6444  * In the first case, we can remove clause cidx.
6445  *
6446  * In the second case, we can remove (not a[i]) from clause cidx. This is
6447  * subsumption/resolution:
6448  * - clause cidx is of the from (A, not a[i], B)
6449  * - clause a[0 ... n-1] is of the from (A, a[i])
6450  * - resolving these two clauses produces (A, B) which subsumes cidx
6451  *
6452  * - s is the signature of a[0 ... n-1]
6453  * - clause cidx may be marked.
6454  *
6455  * Return true if there's no conflict, false otherwise.
6456  */
try_subsumption(sat_solver_t * solver,uint32_t n,const literal_t * a,uint32_t s,cidx_t cidx)6457 static bool try_subsumption(sat_solver_t *solver, uint32_t n, const literal_t *a, uint32_t s, cidx_t cidx) {
6458   uint32_t i, j, k, m, q;
6459   literal_t *b;
6460   literal_t l;
6461 
6462   assert(clause_is_live(&solver->pool, cidx));
6463   assert(clause_is_sorted(solver, cidx));
6464 
6465   m = clause_length(&solver->pool, cidx);
6466   q = clause_signature(&solver->pool, cidx);
6467   b = clause_literals(&solver->pool, cidx);
6468 
6469   assert(m >= 2);
6470 
6471   if (m < n || ((~q & s) != 0)) return true;
6472 
6473   k = m;
6474   j = 0;
6475 
6476   /*
6477    * in this loop:
6478    * - k < m => b[k] = not(a[i0]) for some 0 <= i0 < i
6479    * - all literals in of a[0 ... i-1] occur in b,
6480    *   except possibly a[i0] which occurs negated.
6481    * - all elements of b[0 .. j-1] are < a[i]
6482    */
6483   for (i=0; i<n; i++) {
6484     // search for a[i] or not(a[i]) in array b[j ... m-1]
6485     j = pp_search_for_var(var_of(a[i]), j, m, b);
6486     if (j == m) return true;  // a[i] not in cidx
6487     assert(b[j] == a[i] || b[j] == not(a[i]));
6488     if (a[i] != b[j]) {
6489       if (k < m) return true;
6490       k = j;
6491     }
6492     j ++;
6493   }
6494 
6495   if (k < m) {
6496     // strengthening: remove literal b[k] form clause cidx
6497     l = b[k];
6498     pp_decrement_occ(solver, l);
6499     pp_remove_literal(m, k, b);
6500     pp_remove_clause_from_watch(solver, l, cidx);
6501     elim_heap_update_var(solver, var_of(l));
6502     m --;
6503     if (m == 1) {
6504       pp_push_unit_literal(solver, b[0]);
6505       clause_pool_delete_clause(&solver->pool, cidx);
6506       solver->stats.pp_unit_strengthenings ++;
6507     } else {
6508       clause_pool_shrink_clause(&solver->pool, cidx, m);
6509       set_clause_signature(&solver->pool, cidx);
6510       clause_queue_push(solver, cidx);
6511       solver->stats.pp_strengthenings ++;
6512     }
6513   } else {
6514     // subsumption: remove clause cidx
6515     pp_decrement_occ_counts(solver, b, m);
6516     clause_pool_delete_clause(&solver->pool, cidx);
6517     solver->stats.pp_subsumptions ++;
6518   }
6519 
6520   // deal with unit or pure literals
6521   return pp_empty_queue(solver);
6522 }
6523 
6524 
6525 /*
6526  * Variable in a[0 ... n-1] with smallest number of total occurrences
6527  */
pp_key_literal(sat_solver_t * solver,const literal_t * a,uint32_t n)6528 static literal_t pp_key_literal(sat_solver_t *solver, const literal_t *a, uint32_t n) {
6529   literal_t k, l;
6530   uint32_t i, c;
6531 
6532   assert(n >= 2);
6533 
6534   k = a[0];
6535   c = solver->occ[k] + solver->occ[not(k)];
6536 
6537   for (i=1; i<n; i++) {
6538     l = a[i];
6539     if (solver->occ[l] + solver->occ[not(l)] < c) {
6540       c = solver->occ[l] + solver->occ[not(l)];
6541       k = l;
6542     }
6543   }
6544 
6545   return k;
6546 }
6547 
6548 
6549 #if TRACE
w_len(sat_solver_t * solver,literal_t l)6550 static uint32_t w_len(sat_solver_t *solver, literal_t l) {
6551   watch_t *w;
6552   uint32_t len;
6553 
6554   len = 0;
6555   w = solver->watch[l];
6556   if (w != NULL) len += w->size;
6557   w = solver->watch[not(l)];
6558   if (w != NULL) len += w->size;
6559 
6560   return len;
6561 }
6562 #endif
6563 
6564 /*
6565  * Check backward subsumption from clause cidx:
6566  * - checks whether cidx subsumes or strengthen any clause of index >= start
6567  * - remove all such clauses subsumed by cidx
6568  * - add strengthened clauses to the clause queue.
6569  *
6570  * Return false if there's a conflict, true otherwise.
6571  */
pp_clause_subsumption(sat_solver_t * solver,uint32_t cidx,uint32_t start)6572 static bool pp_clause_subsumption(sat_solver_t *solver, uint32_t cidx, uint32_t start) {
6573   literal_t *a;
6574   uint32_t i, n, m, k, s;
6575   literal_t key;
6576   watch_t *w;
6577 
6578   assert(clause_is_live(&solver->pool, cidx));
6579   assert(clause_is_sorted(solver, cidx));
6580 
6581   n = clause_length(&solver->pool, cidx);
6582   s = clause_signature(&solver->pool, cidx);
6583   a = clause_literals(&solver->pool, cidx);
6584   key = pp_key_literal(solver, a, n);
6585 
6586 #if TRACE
6587   fprintf(stderr, "subsumption check: cidx = %"PRIu32", len = %"PRIu32", key = %"PRIu32", occs = %"PRIu32", watch size = %"PRIu32"\n",
6588           cidx, n, key, solver->occ[key] + solver->occ[not(key)], w_len(solver, key));
6589 #endif
6590 
6591   w = solver->watch[key];
6592   if (w != NULL) {
6593     m = w->size;
6594     if (m < solver->params.subsume_skip) {
6595       for (i=0; i<m; i++) {
6596         k = w->data[i];
6597         if (k >= start && k != cidx && clause_is_live(&solver->pool, k)) {
6598           if (!try_subsumption(solver, n, a, s, k)) {
6599             return false;
6600           }
6601           if (!clause_is_live(&solver->pool, cidx)) {
6602             goto done;
6603           }
6604         }
6605       }
6606     }
6607   }
6608 
6609   w = solver->watch[not(key)];
6610   if (w != NULL) {
6611     m = w->size;
6612     if (m < solver->params.subsume_skip) {
6613       for (i=0; i<m; i++) {
6614         k = w->data[i];
6615         if (k >= start && clause_is_live(&solver->pool, k)) {
6616           assert(k != cidx);
6617           if (!try_subsumption(solver, n, a, s, k)) {
6618             return false;
6619           }
6620           if (!clause_is_live(&solver->pool, cidx)) {
6621             goto done;
6622           }
6623         }
6624       }
6625     }
6626   }
6627 
6628  done:
6629   return true;
6630 }
6631 
6632 
6633 /*
6634  * Collect and mark all variables in clause cidx
6635  * - the variables are added to solver->aux
6636  */
pp_collect_vars_of_clause(sat_solver_t * solver,cidx_t cidx)6637 static void pp_collect_vars_of_clause(sat_solver_t *solver, cidx_t cidx) {
6638   literal_t *a;
6639   uint32_t i, n;
6640   bvar_t x;
6641 
6642   assert(clause_is_live(&solver->pool, cidx));
6643 
6644   n = clause_length(&solver->pool, cidx);
6645   a = clause_literals(&solver->pool, cidx);
6646   for (i=0; i<n; i++) {
6647     x = var_of(a[i]);
6648     if (! variable_is_marked(solver, x)) {
6649       mark_variable(solver, x);
6650       vector_push(&solver->aux, x);
6651     }
6652   }
6653 }
6654 
6655 
6656 /*
6657  * Collect clauses of index < s from w
6658  * - if a clause is marked we skip it
6659  * - otherwise we mark it and add it to cvector
6660  */
pp_collect_subsume_candidates_in_watch(sat_solver_t * solver,watch_t * w,uint32_t s)6661 static void pp_collect_subsume_candidates_in_watch(sat_solver_t *solver, watch_t *w, uint32_t s) {
6662   uint32_t i, n, cidx;
6663 
6664   if (w != NULL) {
6665     n = w->size;
6666     for (i=0; i<n; i++) {
6667       cidx = w->data[i];
6668       if (cidx < s && clause_is_live(&solver->pool, cidx) && clause_is_unmarked(&solver->pool, cidx)) {
6669         mark_clause(&solver->pool, cidx);
6670         vector_push(&solver->cvector, cidx);
6671       }
6672     }
6673   }
6674 }
6675 
6676 /*
6677  * Collect clauses that may subsume a clause of index >= s
6678  * - solver->aux contains variables of clauses >= s
6679  * - all variables in solver->aux are marked.
6680  * - the relevant clauses are stored in solver->cvector
6681  * - all variable marks are cleared
6682  *
6683  * To avoid duplication, we mark clauses as we add them to cvector.
6684  * If a clause is already marked, it's in the clause queue so don't
6685  * need to add it to cvector.
6686  */
pp_collect_subsume_candidates(sat_solver_t * solver,uint32_t s)6687 static void pp_collect_subsume_candidates(sat_solver_t *solver, uint32_t s) {
6688   vector_t *v;
6689   uint32_t i, n;
6690   bvar_t x;
6691 
6692   reset_vector(&solver->cvector);
6693 
6694   v = &solver->aux;
6695   n = v->size;
6696   for (i=0; i<n; i++) {
6697     x = v->data[i];
6698     assert(variable_is_marked(solver, x));
6699     unmark_variable(solver, x);
6700     pp_collect_subsume_candidates_in_watch(solver, solver->watch[pos_lit(x)], s);
6701     pp_collect_subsume_candidates_in_watch(solver, solver->watch[neg_lit(x)], s);
6702   }
6703   reset_vector(v); // cleanup
6704 
6705   // cleanup: remove the marks of all clauses in cvector
6706   v = &solver->cvector;
6707   n = v->size;
6708   for (i=0; i<n; i++) {
6709     assert(clause_is_marked(&solver->pool, v->data[i]));
6710     unmark_clause(&solver->pool, v->data[i]);
6711   }
6712 }
6713 
6714 
6715 
6716 /*
6717  * One round of subsumption starting from solver->scan_index
6718  *
6719  * The set of clauses is split in two:
6720  * - S1: clauses of index < scan_index
6721  * - S2: clauses of index >= scan_index
6722  * We know that the clauses in S1 don't subsume each other.
6723  *
6724  * We first scan clauses of S2 and we check whether they subsume or
6725  * strengthen anything. Then we compute the set of variables that
6726  * occur in clauses of S2 and we construct the set of clauses from S1
6727  * that contain any such variable. We check for subsumption from theses
6728  * clauses. Finally, we process the queue of clauses.
6729  */
pp_subsumption(sat_solver_t * solver)6730 static bool pp_subsumption(sat_solver_t *solver) {
6731   uint32_t i, n, s;
6732   cidx_t cidx;
6733 
6734   // save the scan index in s
6735   s = solver->scan_index;
6736 
6737   // First pass: scan clauses of S2
6738   for (;;) {
6739     cidx = clause_scan_next(solver);
6740     if (cidx >= solver->pool.size) break;
6741     if (clause_is_live(&solver->pool, cidx) &&
6742         !pp_clause_subsumption(solver, cidx, 0)) {
6743       return false;
6744     }
6745   }
6746 
6747   if (s > 0) {
6748     // collect variables of S2 into solver->aux
6749     reset_vector(&solver->aux);
6750     cidx = next_clause_index(&solver->pool, s);
6751     while (cidx < solver->pool.size) {
6752       if (clause_is_live(&solver->pool, cidx)) {
6753         pp_collect_vars_of_clause(solver, cidx);
6754       }
6755       cidx = clause_pool_next_clause(&solver->pool, cidx);
6756     }
6757 
6758     // clauses of S1 that may subsume/strengthen a clause of S2
6759     pp_collect_subsume_candidates(solver, s);
6760     n = solver->cvector.size;
6761     for (i=0; i<n; i++) {
6762       cidx = solver->cvector.data[i];
6763       // cidx was live when it was added but it can
6764       // be deleted within this loop in pp_empty_queue
6765       if (clause_is_live(&solver->pool, cidx) &&
6766           !pp_clause_subsumption(solver, cidx, s)) {
6767         return false;
6768       }
6769     }
6770   }
6771 
6772 
6773   // Final step: empty the queue
6774   for (;;) {
6775     cidx = clause_queue_pop(solver);
6776     if (cidx >= solver->pool.size) break;
6777     assert(clause_is_live(&solver->pool, cidx));
6778     if (!pp_clause_subsumption(solver, cidx, 0)) {
6779       return false;
6780     }
6781   }
6782 
6783   return true;
6784 }
6785 
6786 /*
6787  * RESOLUTION/VARIABLE ELIMINATION
6788  */
6789 
6790 /*
6791  * Total size of all live clauses in vector w
6792  */
live_clauses_size(const clause_pool_t * pool,const watch_t * w)6793 static uint32_t live_clauses_size(const clause_pool_t *pool, const watch_t *w) {
6794   uint32_t s, i, n, cidx;
6795 
6796   assert(w != NULL);
6797 
6798   s = 0;
6799   n = w->size;
6800   for (i=0; i<n; i++) {
6801     cidx = w->data[i];
6802     if (clause_is_live(pool, cidx)) {
6803       s += clause_length(pool, cidx);
6804     }
6805   }
6806 
6807   return s;
6808 }
6809 
6810 /*
6811  * Save clause of given idx
6812  */
pp_save_clause(sat_solver_t * solver,uint32_t cidx,literal_t l)6813 static void pp_save_clause(sat_solver_t *solver, uint32_t cidx, literal_t l) {
6814   assert(clause_is_live(&solver->pool, cidx));
6815   clause_vector_save_clause(&solver->saved_clauses, clause_length(&solver->pool, cidx),
6816                             clause_literals(&solver->pool, cidx), l);
6817 
6818 }
6819 
6820 
6821 /*
6822  * Save half the clauses that contain x so that we can later extend the truth-assignment to x.
6823  */
pp_save_elim_clauses_for_var(sat_solver_t * solver,bvar_t x)6824 static void pp_save_elim_clauses_for_var(sat_solver_t *solver, bvar_t x) {
6825   watch_t *w;
6826   literal_t l;
6827   uint32_t s, n, i, cidx;
6828 
6829   l = pos_lit(x);
6830   w = solver->watch[pos_lit(x)];
6831   s = live_clauses_size(&solver->pool, solver->watch[pos_lit(x)]);
6832 
6833   n = live_clauses_size(&solver->pool, solver->watch[neg_lit(x)]);
6834   if (n < s) {
6835     l = neg_lit(x);
6836     w = solver->watch[neg_lit(x)];
6837     s = n;
6838   }
6839 
6840   resize_clause_vector(&solver->saved_clauses, s);
6841   n = w->size;
6842   for (i=0; i<n; i++) {
6843     cidx = w->data[i];
6844     if (clause_is_live(&solver->pool, cidx)) {
6845       pp_save_clause(solver, cidx, l);
6846     }
6847   }
6848   clause_vector_add_block_length(&solver->saved_clauses, s);
6849 }
6850 
6851 
6852 /*
6853  * Check whether the resolvent of clauses c1 and c2 is not trivial
6854  * - l = pivot literal
6855  * - both clauses must be sorted
6856  * - c1 must contain l and c2 must contain (not l)
6857  * - return true if the resolvent is not trivial, and store its length in *length
6858  */
non_trivial_resolvent(const sat_solver_t * solver,uint32_t c1,uint32_t c2,literal_t l,uint32_t * length)6859 static bool non_trivial_resolvent(const sat_solver_t *solver, uint32_t c1, uint32_t c2, literal_t l, uint32_t *length) {
6860   literal_t *a1, *a2;
6861   uint32_t i1, i2, n1, n2, len;
6862 
6863   assert(clause_is_live(&solver->pool, c1) && clause_is_sorted(solver, c1));
6864   assert(clause_is_live(&solver->pool, c2) && clause_is_sorted(solver, c2));
6865 
6866   n1 = clause_length(&solver->pool, c1);
6867   a1 = clause_literals(&solver->pool, c1);
6868   n2 = clause_length(&solver->pool, c2);
6869   a2 = clause_literals(&solver->pool, c2);
6870 
6871   len = n1 + n2;
6872   i1 = 0;
6873   i2 = 0;
6874   do {
6875     if (var_of(a1[i1]) < var_of(a2[i2])) {
6876       i1 ++;
6877     } else if (var_of(a1[i1]) > var_of(a2[i2])) {
6878       i2 ++;
6879     } else if (a1[i1] != a2[i2] && a1[i1] != l) {
6880       assert(a1[i1] == not(a2[i2])); // trivial resolvent
6881       return false;
6882     } else {
6883       i1 ++;
6884       i2 ++;
6885       len --;
6886     }
6887   } while (i1 < n1 && i2 < n2);
6888 
6889   *length = len;
6890 
6891   return true;
6892 }
6893 
6894 /*
6895  * Construct the resolvent of clauses c1 and c2
6896  * - l = literal
6897  * - both clauses must be sorted
6898  * - c1 must contain l and c2 must contain (not l)
6899  * - store it in solver->buffer
6900  * - return true if the resolvent is not trivial/false if it is
6901  */
pp_build_resolvent(sat_solver_t * solver,uint32_t c1,uint32_t c2,literal_t l)6902 static bool pp_build_resolvent(sat_solver_t *solver, uint32_t c1, uint32_t c2, literal_t l) {
6903   literal_t *a1, *a2;
6904   uint32_t i1, i2, n1, n2;
6905 
6906   assert(clause_is_live(&solver->pool, c1) && clause_is_sorted(solver, c1));
6907   assert(clause_is_live(&solver->pool, c2) && clause_is_sorted(solver, c2));
6908 
6909   reset_vector(&solver->buffer);
6910   n1 = clause_length(&solver->pool, c1);
6911   a1 = clause_literals(&solver->pool, c1);
6912   n2 = clause_length(&solver->pool, c2);
6913   a2 = clause_literals(&solver->pool, c2);
6914 
6915   i1 = 0;
6916   i2 = 0;
6917   do {
6918     if (var_of(a1[i1]) < var_of(a2[i2])) {
6919       vector_push(&solver->buffer, a1[i1]);
6920       i1 ++;
6921     } else if (var_of(a1[i1]) > var_of(a2[i2])) {
6922       vector_push(&solver->buffer, a2[i2]);
6923       i2 ++;
6924     } else if (a1[i1] == a2[i2]) {
6925       vector_push(&solver->buffer, a1[i1]);
6926       i1 ++;
6927       i2 ++;
6928     } else {
6929       assert(a1[i1] == not(a2[i2]));
6930       if (a1[i1] != l) return false;
6931       i1 ++;
6932       i2 ++;
6933     }
6934   } while (i1 < n1 && i2 < n2);
6935 
6936   while (i1 < n1) {
6937     vector_push(&solver->buffer, a1[i1]);
6938     i1 ++;
6939   }
6940   while (i2 < n2) {
6941     vector_push(&solver->buffer, a2[i2]);
6942     i2 ++;
6943   }
6944   return true;
6945 }
6946 
6947 
6948 /*
6949  * Add l as a new clause (unit resolvent)
6950  * - do nothing if l is already true
6951  * - add the empty clause if l is already false
6952  */
pp_add_unit_resolvent(sat_solver_t * solver,literal_t l)6953 static void pp_add_unit_resolvent(sat_solver_t *solver, literal_t l) {
6954   switch (lit_value(solver, l)) {
6955   case VAL_TRUE:
6956     break;
6957 
6958   case VAL_FALSE:
6959     add_empty_clause(solver);
6960     break;
6961 
6962   default:
6963     pp_push_unit_literal(solver, l);
6964     break;
6965   }
6966 }
6967 
6968 /*
6969  * Construct the resolvent of c1 and c2 and add it if it's not trivial.
6970  * - if the resolvent is a unit clause, add its literal to the unit queue
6971  * - return false if there's a conflict, true otherwise.
6972  */
pp_add_resolvent(sat_solver_t * solver,uint32_t c1,uint32_t c2,literal_t l)6973 static void pp_add_resolvent(sat_solver_t *solver, uint32_t c1, uint32_t c2, literal_t l) {
6974   vector_t *b;
6975   uint32_t n, cidx;
6976 
6977   if (pp_build_resolvent(solver, c1, c2, l)) {
6978     b = &solver->buffer;
6979     n = b->size;
6980     assert(n > 0);
6981     if (n == 1) {
6982       pp_add_unit_resolvent(solver, b->data[0]);
6983     } else {
6984       cidx = clause_pool_add_problem_clause(&solver->pool, n, (literal_t *) b->data);
6985       add_clause_all_watch(solver, n, (literal_t *) b->data, cidx);
6986       set_clause_signature(&solver->pool, cidx);
6987     }
6988     pp_increment_occ_counts(solver, (literal_t *) b->data, n);
6989   }
6990 }
6991 
6992 
6993 /*
6994  * Mark x as an eliminated variable:
6995  * - we also give it a value to make sure pos_lit(x) and neg_lit(x) don't get
6996  *   added to the queue of pure_literals.
6997  */
pp_mark_eliminated_variable(sat_solver_t * solver,bvar_t x)6998 static void pp_mark_eliminated_variable(sat_solver_t *solver, bvar_t x) {
6999   assert(var_is_unassigned(solver, x));
7000   assert(solver->decision_level == 0);
7001 
7002   solver->value[pos_lit(x)] = VAL_TRUE;
7003   solver->value[neg_lit(x)] = VAL_FALSE;
7004   solver->ante_tag[x] = ATAG_ELIM;
7005   solver->ante_data[x] = 0;
7006   solver->level[x] = 0;
7007 }
7008 
7009 /*
7010  * Eliminate variable x:
7011  * - get all the clauses that contain pos_lit(x) and neg_lit(x) and construct
7012  *   their resolvents
7013  * - any pure or unit literals created as a result are added to solver->lqueue
7014  * - may also set solver->has_empty_clause to true
7015  */
pp_eliminate_variable(sat_solver_t * solver,bvar_t x)7016 static void pp_eliminate_variable(sat_solver_t *solver, bvar_t x) {
7017   watch_t *w1, *w2;
7018   uint32_t i1, i2, n1, n2;
7019   cidx_t c1, c2;
7020 
7021   assert(x < solver->nvars);
7022 
7023   w1 = solver->watch[pos_lit(x)];
7024   w2 = solver->watch[neg_lit(x)];
7025 
7026   if (w1 == NULL || w2 == NULL) return;
7027 
7028   n1 = w1->size;
7029   n2 = w2->size;
7030   for (i1=0; i1<n1; i1++) {
7031     c1 = w1->data[i1];
7032     assert(idx_is_clause(c1));
7033     if (clause_is_live(&solver->pool, c1)) {
7034       for (i2=0; i2<n2; i2++) {
7035         c2 = w2->data[i2];
7036         assert(idx_is_clause(c2));
7037         if (clause_is_live(&solver->pool, c2)) {
7038           pp_add_resolvent(solver, c1, c2, pos_lit(x));
7039           if (solver->has_empty_clause) return;
7040         }
7041       }
7042     }
7043   }
7044   // save enough clauses to extend the model to x
7045   pp_save_elim_clauses_for_var(solver, x);
7046 
7047   /*
7048    * We must mark x as an eliminated variable before deleting the clauses
7049    * that contain x.
7050    */
7051   pp_mark_eliminated_variable(solver, x);
7052 
7053   // Delete the clauses that contain x
7054   for (i1=0; i1<n1; i1++) {
7055     c1 = w1->data[i1];
7056     assert(idx_is_clause(c1));
7057     if (clause_is_live(&solver->pool, c1)) {
7058       pp_remove_clause(solver, c1);
7059     }
7060   }
7061   for (i2=0; i2<n2; i2++) {
7062     c2 = w2->data[i2];
7063     assert(idx_is_clause(c2));
7064     if (clause_is_live(&solver->pool, c2)) {
7065       pp_remove_clause(solver, c2);
7066     }
7067   }
7068   safe_free(w1);
7069   safe_free(w2);
7070   solver->watch[pos_lit(x)] = NULL;
7071   solver->watch[neg_lit(x)] = NULL;
7072 
7073   pp_try_gc(solver);
7074 }
7075 
7076 
7077 
7078 
7079 /*
7080  * Check whether eliminating variable x creates too many clauses.
7081  * - return true if the number of non-trivial resolvent is less than
7082  *   the number of clauses that contain x
7083  */
pp_variable_worth_eliminating(const sat_solver_t * solver,bvar_t x)7084 static bool pp_variable_worth_eliminating(const sat_solver_t *solver, bvar_t x) {
7085   watch_t *w1, *w2;
7086   uint32_t i1, i2, n1, n2;
7087   cidx_t c1, c2;
7088   uint32_t n, new_n, len;
7089 
7090   assert(x < solver->nvars);
7091 
7092   w1 = solver->watch[pos_lit(x)];
7093   w2 = solver->watch[neg_lit(x)];
7094 
7095   if (w1 == NULL || w2 == NULL) return true;
7096 
7097   n1 = w1->size;
7098   n2 = w2->size;
7099   if (n1 >= 10 && n2 >= 10) return false;
7100 
7101   // number of clauses that contain x
7102   n = solver->occ[pos_lit(x)] + solver->occ[neg_lit(x)];
7103   new_n = 0;
7104   len = 0; // Prevents a GCC warning
7105 
7106   for (i1=0; i1<n1; i1++) {
7107     c1 = w1->data[i1];
7108     assert(idx_is_clause(c1));
7109     if (clause_is_live(&solver->pool, c1)) {
7110       for (i2=0; i2<n2; i2++) {
7111         c2 = w2->data[i2];
7112         assert(idx_is_clause(c2));
7113         if (clause_is_live(&solver->pool, c2)) {
7114           new_n += non_trivial_resolvent(solver, c1, c2, pos_lit(x), &len);
7115           if (new_n > n || len > solver->params.res_clause_limit) return false;
7116         }
7117       }
7118     }
7119   }
7120   assert(new_n <= n);
7121 
7122   return true;
7123 }
7124 
7125 
7126 /*
7127  * Add variables to the elimination heap.
7128  */
collect_elimination_candidates(sat_solver_t * solver)7129 static void collect_elimination_candidates(sat_solver_t *solver) {
7130   uint32_t i, n;
7131 
7132   n = solver->nvars;
7133   for (i=1; i<n; i++) {
7134     if (var_is_active(solver, i) && pp_elim_candidate(solver, i)) {
7135       assert(!var_is_in_elim_heap(solver, i));
7136       elim_heap_insert_var(solver, i);
7137     }
7138   }
7139 }
7140 
7141 
7142 /*
7143  * Eliminate variables: iterate over all variables in the elimination
7144  * heap.
7145  */
process_elimination_candidates(sat_solver_t * solver)7146 static void process_elimination_candidates(sat_solver_t *solver) {
7147   uint32_t pp, nn;
7148   bvar_t x;
7149   bool cheap;
7150 
7151   while (! elim_heap_is_empty(solver)) {
7152     x = elim_heap_get_top(solver);
7153 
7154     if (var_is_assigned(solver, x)) {
7155       assert(solver->ante_tag[x] == ATAG_PURE ||
7156              solver->ante_tag[x] == ATAG_UNIT ||
7157              solver->ante_tag[x] == ATAG_ELIM ||
7158 	     solver->ante_tag[x] == ATAG_SUBST);
7159       continue;
7160     }
7161     assert(!var_is_eliminated(solver, x));
7162 
7163     pp = solver->occ[pos_lit(x)];
7164     nn = solver->occ[neg_lit(x)];
7165     if (pp == 0 || nn == 0) {
7166       continue;
7167     }
7168     if (pp_variable_worth_eliminating(solver, x)) {
7169       pp_eliminate_variable(solver, x);
7170       cheap = (pp == 1 || nn == 1 || (pp == 2 && nn == 2));
7171       solver->stats.pp_cheap_elims += cheap;
7172       solver->stats.pp_var_elims += (1 - cheap);
7173       // check for conflicts + process unit/pure literals
7174       if (solver->has_empty_clause || !pp_empty_queue(solver)) return;
7175     }
7176   }
7177 }
7178 
7179 
7180 /*
7181  * END OF PREPROCESSING
7182  */
7183 
7184 /*
7185  * Cleanup all the watch vectors
7186  */
pp_reset_watch_vectors(sat_solver_t * solver)7187 static void pp_reset_watch_vectors(sat_solver_t *solver) {
7188   uint32_t i, n;
7189   watch_t *w;
7190 
7191   n = solver->nliterals;
7192   for (i=2; i<n; i++) {
7193     w = solver->watch[i];
7194     if (w != NULL) {
7195       w->size = 0;
7196     }
7197   }
7198 }
7199 
7200 #ifndef NDEBUG
7201 /*
7202  * Check that clause at index cidx has no assigned literals.
7203  */
clause_is_clean(const sat_solver_t * solver,cidx_t cidx)7204 static bool clause_is_clean(const sat_solver_t *solver, cidx_t cidx) {
7205   uint32_t i, n;
7206   literal_t *a;
7207 
7208   n = clause_length(&solver->pool, cidx);
7209   a = clause_literals(&solver->pool, cidx);
7210   for (i=0; i<n; i++) {
7211     if (lit_is_assigned(solver, a[i])) {
7212       return false;
7213     }
7214   }
7215   return true;
7216 }
7217 #endif
7218 
7219 /*
7220  * Scan all live clauses in the pool
7221  * - remove binary clauses from the pool and move them to the watch vectors
7222  * - also compact the pool
7223  */
pp_rebuild_watch_vectors(sat_solver_t * solver)7224 static void pp_rebuild_watch_vectors(sat_solver_t *solver) {
7225   clause_pool_t *pool;
7226   uint32_t n;
7227   cidx_t i, j;
7228   literal_t l1, l2;
7229 
7230   pool = &solver->pool;
7231 
7232   assert(clause_pool_invariant(pool));
7233   assert(pool->learned == pool->size &&
7234          pool->num_learned_clauses == 0 &&
7235          pool->num_learned_literals == 0);
7236 
7237   pool->num_prob_clauses = 0;
7238   pool->num_prob_literals = 0;
7239 
7240   i = 0;
7241   j = 0;
7242   while (i < pool->size) {
7243     n = pool->data[i];
7244     if (n == 0) {
7245       // padding block: skip it
7246       i += padding_length(pool, i);
7247     } else {
7248       assert(n >= 2 && (n & CLAUSE_MARK) == 0);
7249       assert(clause_is_clean(solver, i));
7250       l1 = first_literal_of_clause(pool, i);
7251       l2 = second_literal_of_clause(pool, i);
7252       if (n == 2) {
7253         // binary clause
7254         add_binary_clause(solver, l1, l2);
7255         i += full_length(2);
7256       } else {
7257         // regular clause at index j
7258         if (j < i) {
7259           clause_pool_move_clause(pool, j, i, n);
7260         }
7261         pool->num_prob_clauses ++;
7262         pool->num_prob_literals += n;
7263         add_clause_watch(solver, l1, j, l2);
7264         add_clause_watch(solver, l2, j, l1);
7265         i += full_length(n);
7266         j += full_length(n);
7267       }
7268     }
7269   }
7270   pool->learned = j;
7271   pool->size = j;
7272   pool->available = pool->capacity - j;
7273   pool->padding = 0;
7274 
7275   assert(clause_pool_invariant(pool));
7276 }
7277 
7278 /*
7279  * Shrink watch vectors that are less than 25% full
7280  */
shrink_watch_vectors(sat_solver_t * solver)7281 static void shrink_watch_vectors(sat_solver_t *solver) {
7282   uint32_t i, n;
7283   watch_t *w;
7284 
7285   n = solver->nliterals;
7286   for (i=2; i<n; i++) {
7287     w = solver->watch[i];
7288     if (w != NULL && w->capacity >= 100 && w->size < (w->capacity >> 2)) {
7289       solver->watch[i] = shrink_watch(w);
7290     }
7291   }
7292 }
7293 
7294 
prepare_for_search(sat_solver_t * solver)7295 static void prepare_for_search(sat_solver_t *solver) {
7296   check_clause_pool_counters(&solver->pool);      // DEBUG
7297   solver->units = 0;
7298   solver->binaries = 0;
7299   reset_stack(&solver->stack);
7300   pp_reset_watch_vectors(solver);
7301   pp_rebuild_watch_vectors(solver);
7302   shrink_watch_vectors(solver);
7303   safe_free(solver->occ);
7304   solver->occ = NULL;
7305   check_clause_pool_counters(&solver->pool);      // DEBUG
7306   check_watch_vectors(solver);                    // DEBUG
7307 }
7308 
7309 
7310 
7311 /*
7312  * EXPERIMENTAL
7313  */
7314 
7315 #if 0
7316 
7317 /*
7318  * For testing: show the definition of a variable i as truth-table w
7319  */
7320 static void show_expanded_ttbl(bvar_t x, wide_ttbl_t *w) {
7321   uint32_t i, n;
7322 
7323   fprintf(stderr, "c W(");
7324   for (i=0; i<w->nvars; i++) {
7325     fprintf(stderr, "%"PRId32", ", w->var[i]);
7326   }
7327   n = ((uint32_t) 1) << w->nvars;
7328   for (i=0; i<n; i++) {
7329     fputc((int)('0' + w->val[i]), stderr);
7330   }
7331   fprintf(stderr, ") == %"PRId32"\n", x);
7332 }
7333 
7334 static void try_expand_all(const sat_solver_t *solver, bvar_t x, wide_ttbl_t *w) {
7335   uint32_t i;
7336   ttbl_t sub;
7337   wide_ttbl_t expand, normal;
7338   bvar_t y;
7339 
7340   init_wide_ttbl(&normal, 6);
7341   wide_ttbl_normalize(&normal, w);
7342   show_expanded_ttbl(x, &normal);
7343 
7344   init_wide_ttbl(&expand, 6);
7345   i = 0;
7346   while (i < normal.nvars) {
7347     y = normal.var[i];
7348     if (gate_for_bvar(solver, y, &sub)) {
7349       apply_subst_to_ttbl(solver, &sub);
7350       if (wide_ttbl_compose(&expand, &normal, &sub, i)) {
7351 	wide_ttbl_normalize(&normal, &expand);
7352 	i = 0;
7353 	continue;
7354       }
7355     }
7356     i ++;
7357   }
7358   show_expanded_ttbl(x, &normal);
7359 
7360   delete_wide_ttbl(&expand);
7361   delete_wide_ttbl(&normal);
7362 }
7363 
7364 static void show_expanded_var_defs(const sat_solver_t *solver) {
7365   uint32_t i, n;
7366   ttbl_t base;
7367   wide_ttbl_t w;
7368 
7369   init_wide_ttbl(&w, 4);
7370 
7371   n = solver->descriptors.size;
7372   for (i=0; i<n; i++) {
7373     if (gate_for_bvar(solver, i, &base)) {
7374       fprintf(stderr, "c cuts for %"PRIu32"\n", i);
7375       apply_subst_to_ttbl(solver, &base);
7376       wide_ttbl_import(&w, &base);
7377       try_expand_all(solver, i, &w);
7378       fprintf(stderr, "c\n");
7379     }
7380   }
7381 
7382   delete_wide_ttbl(&w);
7383 }
7384 
7385 #endif
7386 
7387 /*
7388  * PREPROCESSING
7389  */
7390 
7391 /*
7392  * On entry to preprocess:
7393  * - watch[l] contains all the clauses in which l occurs
7394  * - occ[l] = number of occurrences of l
7395  * Unit clauses are stored implicitly in the propagation queue.
7396  * Binary clauses are stored in the pool.
7397  *
7398  * On exit:
7399  * - either solver->has_empty_clause is true or the clauses and watch
7400  *   vectors are ready for search: binary clauses are stored directly
7401  *   in the watch vectors; other clauses have two watch literals.
7402  */
nsat_preprocess(sat_solver_t * solver)7403 static void nsat_preprocess(sat_solver_t *solver) {
7404   if (solver->verbosity >= 2) fprintf(stderr, "c Preprocessing\n");
7405 
7406 #if 0
7407   fprintf(stderr, "\n\n*** INPUT ***\n");
7408   show_subst(solver);
7409   fprintf(stderr, "\n\n");
7410   show_state(stderr, solver);
7411   fprintf(stderr, "\n\n*** DONE INPUT ***\n");
7412 #endif
7413 
7414   collect_unit_and_pure_literals(solver);
7415   do {
7416     if (! pp_empty_queue(solver)) goto done;
7417     pp_try_gc(solver);
7418     if (! pp_scc_simplification(solver)) goto done;
7419   } while (! queue_is_empty(&solver->lqueue));
7420 
7421 #if 0
7422   fprintf(stderr, "\n\n*** STEP1 ***\n");
7423   show_all_var_defs(solver);
7424   show_subst(solver);
7425   fprintf(stderr, "\n");
7426   show_state(stderr, solver);
7427   fprintf(stderr, "\n\n*** DONE STEP1 ***\n");
7428 #endif
7429 
7430   prepare_elim_heap(&solver->elim, solver->nvars);
7431   collect_elimination_candidates(solver);
7432   assert(solver->scan_index == 0);
7433   do {
7434     if (solver->verbosity >= 4) fprintf(stderr, "c Elimination\n");
7435     process_elimination_candidates(solver);
7436     if (solver->verbosity >= 4) fprintf(stderr, "c Subsumption\n");
7437     if (solver->has_empty_clause || !pp_subsumption(solver)) break;
7438   } while (!elim_heap_is_empty(solver));
7439 
7440 #if 0
7441   fprintf(stderr, "\n\n*** STEP2 ***\n");
7442   show_subst(solver);
7443   fprintf(stderr, "\n\n");
7444   show_state(stderr, solver);
7445   fprintf(stderr, "\n\n*** DONE STEP2 ***\n");
7446 #endif
7447 
7448   do {
7449     if (! pp_empty_queue(solver)) goto done;
7450     pp_try_gc(solver);
7451     if (! pp_scc_simplification(solver)) goto done;
7452   } while (! queue_is_empty(&solver->lqueue));
7453 
7454  done:
7455   solver->stats.pp_subst_vars = solver->stats.subst_vars;
7456   solver->stats.pp_equivs = solver->stats.equivs;
7457 
7458   if (solver->verbosity >= 4) fprintf(stderr, "c Done\nc\n");
7459 
7460   reset_clause_queue(solver);
7461   reset_elim_heap(&solver->elim);
7462   if (!solver->has_empty_clause) {
7463     prepare_for_search(solver);
7464   }
7465 
7466 #if 0
7467   // test
7468   show_all_var_defs(solver);
7469   show_subst(solver);
7470   show_expanded_var_defs(solver);
7471 #endif
7472 }
7473 
7474 
7475 
7476 /**************************
7477  *  BOOLEAN PROPAGATION   *
7478  *************************/
7479 
7480 /*
7481  * Conflict: binary clause {l0, l1} is false
7482  */
record_binary_conflict(sat_solver_t * solver,literal_t l0,literal_t l1)7483 static void record_binary_conflict(sat_solver_t *solver, literal_t l0, literal_t l1) {
7484   assert(lit_is_false(solver, l0) && lit_is_false(solver, l1));
7485 
7486 #if TRACE
7487   printf("\n---> DPLL:   Binary conflict: %"PRIu32" %"PRIu32"\n", l0, l1);
7488   fflush(stdout);
7489 #endif
7490 
7491   solver->conflict_tag = CTAG_BINARY;
7492   solver->conflict_buffer[0] = l0;
7493   solver->conflict_buffer[1] = l1;
7494   solver->stats.conflicts ++;
7495 }
7496 
7497 /*
7498  * For debugging: check that clause cidx is false
7499  */
7500 #ifndef NDEBUG
clause_is_false(const sat_solver_t * solver,cidx_t cidx)7501 static bool clause_is_false(const sat_solver_t *solver, cidx_t cidx) {
7502   literal_t *l;
7503   uint32_t i, n;
7504 
7505   assert(good_clause_idx(&solver->pool, cidx));
7506   n = clause_length(&solver->pool, cidx);
7507   l = clause_literals(&solver->pool, cidx);
7508   for (i=0; i<n; i++) {
7509     if (!lit_is_false(solver, l[i])) {
7510       return false;
7511     }
7512   }
7513   return true;
7514 }
7515 #endif
7516 
7517 /*
7518  * Conflict: clause cidx is false
7519  */
record_clause_conflict(sat_solver_t * solver,cidx_t cidx)7520 static void record_clause_conflict(sat_solver_t *solver, cidx_t cidx) {
7521   assert(clause_is_false(solver, cidx));
7522 
7523 #if TRACE
7524   printf("\n---> DPLL:   Clause conflict: cidx = %"PRIu32"\n");
7525   fflush(stdout);
7526 #endif
7527 
7528   solver->conflict_tag = CTAG_CLAUSE;
7529   solver->conflict_index = cidx;
7530   solver->stats.conflicts ++;
7531 }
7532 
7533 
7534 /*
7535  * Propagation from literal l0
7536  * - l0 must be false in the current assignment
7537  * - sets solver->conflict_tag if there's a conflict
7538  */
propagate_from_literal(sat_solver_t * solver,literal_t l0)7539 static void propagate_from_literal(sat_solver_t *solver, literal_t l0) {
7540   watch_t *w;
7541   literal_t *lit;
7542   uint32_t i, j, n, k, len, t;
7543   literal_t l, l1;
7544   bval_t vl;
7545 
7546   assert(lit_is_false(solver, l0));
7547 
7548   w = solver->watch[l0];
7549   if (w == NULL || w->size == 0) return; // nothing to do
7550 
7551   n = w->size;
7552   j = 0;
7553   i = 0;
7554   while (i < n) {
7555     k = w->data[i];
7556     w->data[j] = k; // Keep k in w. We'll undo this later if needed.
7557     i ++;
7558     j ++;
7559     if (idx_is_literal(k)) {
7560       /*
7561        * Binary clause
7562        */
7563       l = idx2lit(k);
7564       vl = lit_value(solver, l);
7565       if (vl == VAL_TRUE) continue;
7566       if (vl == VAL_FALSE) {
7567         record_binary_conflict(solver, l0, l);
7568         goto conflict;
7569       }
7570       assert(bval_is_undef(vl));
7571       binary_clause_propagation(solver, l, l0);
7572       continue;
7573 
7574     } else {
7575       /*
7576        * Clause in the pool
7577        */
7578       // get the blocker
7579       l = w->data[i];
7580       w->data[j] = l;
7581       i ++;
7582       j ++;
7583       if (lit_is_true(solver, l)) {
7584         continue;
7585       }
7586 
7587       // read len directly (the clause should not be marked)
7588       len = solver->pool.data[k];
7589       assert(len == clause_length(&solver->pool, k));
7590 
7591       lit = clause_literals(&solver->pool, k);
7592       assert(lit[0] == l0 || lit[1] == l0);
7593       // Get the other watched literal in clause k
7594       l = lit[0] ^ lit[1] ^ l0;
7595       // If l is true, nothing to do
7596       vl = lit_value(solver, l);
7597       if (vl == VAL_TRUE) {
7598         w->data[j-1] = l; // change blocker
7599         continue;
7600       }
7601 
7602       // Force l to go into lit[0] and l0 into lit[1]
7603       lit[0] = l;
7604       lit[1]  = l0;
7605 
7606       // Search for an unassigned or true literal in lit[2 ... len-1]
7607       for (t=2; t<len; t++) {
7608         if (! lit_is_false(solver, lit[t])) {
7609           // lit[t] is either true or not assigned.
7610           // It can replace l0 as watched literal
7611           l1 = lit[t];
7612           lit[1] = l1;
7613           lit[t] = l0;
7614           add_clause_watch(solver, l1, k, l);
7615           j -= 2; // remove [k, blocker] from l0's watch vector
7616           goto done;
7617         }
7618       }
7619 
7620       // All literals in lit[1 ... len-1] are false
7621       assert(t == len);
7622       if (vl == VAL_FALSE) {
7623         record_clause_conflict(solver, k);
7624         goto conflict;
7625       }
7626       assert(bval_is_undef(vl));
7627       clause_propagation(solver, l, k);
7628     done:
7629       continue;
7630     }
7631   }
7632   w->size = j;
7633   return;
7634 
7635  conflict:
7636   while (i<n) {
7637     w->data[j] = w->data[i];
7638     j ++;
7639     i ++;
7640   }
7641   w->size = j;
7642 }
7643 
7644 
7645 /*
7646  * Boolean propagation
7647  * - on entry, solver->conflict_tag must be CTAG_NONE
7648  * - on exit, it's set to CTAG_BINARY or CTAG_CLAUSE if there's a conflict
7649  */
nsat_boolean_propagation(sat_solver_t * solver)7650 static void nsat_boolean_propagation(sat_solver_t *solver) {
7651   literal_t l;
7652   uint32_t i;
7653 
7654   assert(solver->conflict_tag == CTAG_NONE);
7655 
7656   for (i = solver->stack.prop_ptr; i< solver->stack.top; i++) {
7657     l = not(solver->stack.lit[i]);
7658     propagate_from_literal(solver, l);
7659     if (solver->conflict_tag != CTAG_NONE) {
7660       return;
7661     }
7662   }
7663   solver->stack.prop_ptr = i;
7664 
7665   check_propagation(solver);
7666 }
7667 
7668 
7669 /*
7670  * Level-0 propagation: boolean propagation + set status to UNSAT
7671  * and add the empty clause if a conflict is detected.
7672  */
level0_propagation(sat_solver_t * solver)7673 static void level0_propagation(sat_solver_t *solver) {
7674   assert(solver->decision_level == 0);
7675   nsat_boolean_propagation(solver);
7676   if (solver->conflict_tag != CTAG_NONE) {
7677     add_empty_clause(solver);
7678   }
7679 }
7680 
7681 
7682 /******************
7683  *  BACKTRACKING  *
7684  *****************/
7685 
7686 /*
7687  * Backtrack to back_level
7688  * - undo all assignments at levels >= back_level + 1
7689  * - solver->decision_level must be larger than back_level
7690  *   (otherwise level_index[back_level + 1] may not be set properly).
7691  */
backtrack(sat_solver_t * solver,uint32_t back_level)7692 static void backtrack(sat_solver_t *solver, uint32_t back_level) {
7693   uint32_t i, d;
7694   literal_t l;
7695   bvar_t x;
7696 
7697   assert(back_level < solver->decision_level);
7698 
7699   d = solver->stack.level_index[back_level + 1];
7700   i = solver->stack.top;
7701   while (i > d) {
7702     i --;
7703     l = solver->stack.lit[i];
7704     x = var_of(l);
7705     assert(lit_is_true(solver, l) && solver->level[x] > back_level);
7706     solver->value[pos_lit(x)] ^= (uint8_t) 0x2;   // clear assign bit
7707     solver->value[neg_lit(x)] ^= (uint8_t) 0x2;   // clear assign bit
7708     assert(var_is_unassigned(solver, x));
7709     heap_insert(&solver->heap, x);
7710   }
7711   solver->stack.top = i;
7712   solver->stack.prop_ptr = i;
7713 
7714   // same thing for the clause stack
7715   solver->stash.top = solver->stash.level[back_level + 1];
7716 
7717   solver->decision_level = back_level;
7718 }
7719 
7720 
7721 
7722 /*
7723  * Check whether all variables assigned at level k have rank less than rx
7724  */
level_has_lower_rank(sat_solver_t * solver,uint32_t rx,uint32_t k)7725 static bool level_has_lower_rank(sat_solver_t *solver, uint32_t rx, uint32_t k) {
7726   sol_stack_t *stack;
7727   uint32_t i, n;
7728   bvar_t x;
7729 
7730   assert(k <= solver->decision_level);
7731   stack = &solver->stack;
7732 
7733   // i := start of level k
7734   // n := end of level k
7735   i = stack->level_index[k];
7736   n = stack->top;
7737   if (k < solver->decision_level) {
7738     n = stack->level_index[k+1];
7739   }
7740 
7741   while (i < n) {
7742     x = var_of(stack->lit[i]);
7743     assert(var_is_assigned(solver, x) && solver->level[x] == k);
7744     if (solver->heap.rank[x] >= rx) {
7745       return false;
7746     }
7747     i ++;
7748   }
7749 
7750   return true;
7751 }
7752 
7753 /*
7754  * Partial restart:
7755  * - find the unassigned variable of highest rank
7756  * - keep all the decision levels that have at least one variable
7757  *   with rank higher than that.
7758  * - do nothing if the decision_level is 0
7759  */
partial_restart(sat_solver_t * solver)7760 static void partial_restart(sat_solver_t *solver) {
7761   uint32_t rx;
7762   bvar_t x;
7763   uint32_t i, n;
7764 
7765   solver->stats.starts ++;
7766   if (solver->decision_level > 0) {
7767     cleanup_heap(solver);
7768 
7769     if (heap_is_empty(&solver->heap)) {
7770       // full restart
7771       backtrack(solver, 0);
7772     } else {
7773       x = solver->heap.heap[1];
7774       assert(var_is_unassigned(solver, x));
7775       rx = solver->heap.rank[x];
7776 
7777       n = solver->decision_level;
7778       for (i=1; i<=n; i++) {
7779 	if (level_has_lower_rank(solver, rx, i)) {
7780 	  backtrack(solver, i-1);
7781 	  break;
7782 	}
7783       }
7784     }
7785   }
7786 }
7787 
7788 /*
7789  * Full restart: backtrack to level 0
7790  */
full_restart(sat_solver_t * solver)7791 static void full_restart(sat_solver_t *solver) {
7792   solver->stats.starts ++;
7793   if (solver->decision_level > 0) {
7794     backtrack(solver, 0);
7795   }
7796 }
7797 
7798 
7799 /*******************************************************
7800  *  CONFLICT ANALYSIS AND CREATION OF LEARNED CLAUSES  *
7801  ******************************************************/
7802 
7803 /*
7804  * During conflict resolution, we build a clause in solver->buffer.
7805  * Except at the very end, all literals in this buffer have decision
7806  * level < conflict level. To prevent duplicates, we mark all of them.
7807  *
7808  * In addition, we also mark the literals that must be resolved.
7809  * These literals have decision level equal to the conflict level.
7810  */
7811 
7812 /*
7813  * Process literal l during conflict resolution.
7814  * - l is either a part of the learned clause or a literal to resolve
7815  * - if l is marked do nothing (already seen)
7816  * - if l has decision level 0, ignore it
7817  * - otherwise:
7818  *     mark l
7819  *     increase variable activity
7820  *     if l's decision_level < conflict level then add l to the buffer
7821  *
7822  * - return 1 if l is to be resolved
7823  * - return 0 otherwise
7824  */
process_literal(sat_solver_t * solver,literal_t l)7825 static uint32_t process_literal(sat_solver_t *solver, literal_t l) {
7826   bvar_t x;
7827 
7828   x = var_of(l);
7829 
7830   assert(solver->level[x] <= solver->decision_level);
7831   assert(lit_is_false(solver, l));
7832 
7833   if (! variable_is_marked(solver, x) && solver->level[x] > 0) {
7834     mark_variable(solver, x);
7835 #if USE_DIVING
7836     if (! solver->diving) {
7837       // in diving mode, we don't touch activities.
7838       move_var_to_front(&solver->heap, x);
7839     }
7840 #else
7841     move_var_to_front(&solver->heap, x);
7842 #endif
7843     if (solver->level[x] == solver->decision_level) {
7844       return 1;
7845     }
7846     vector_push(&solver->buffer, l);
7847   }
7848 
7849   return 0;
7850 }
7851 
7852 /*
7853  * Process clause cidx:
7854  * - process literals starting from i0
7855  * - i0 is either 0 or 1
7856  * - increase the clause activity if it's a learned clause
7857  * - return the number of literals to resolved
7858  */
process_clause(sat_solver_t * solver,cidx_t cidx,uint32_t i0)7859 static uint32_t process_clause(sat_solver_t *solver, cidx_t cidx, uint32_t i0) {
7860   literal_t *lit;
7861   uint32_t i, n, toresolve;
7862 
7863   assert(i0 <= 1);
7864 
7865   if (is_learned_clause_idx(&solver->pool, cidx)) {
7866     increase_clause_activity(solver, cidx);
7867   }
7868 
7869   toresolve = 0;
7870   n = clause_length(&solver->pool, cidx);
7871   lit = clause_literals(&solver->pool, cidx);
7872   for (i=i0; i<n; i++) {
7873     toresolve += process_literal(solver, lit[i]);
7874   }
7875   return toresolve;
7876 }
7877 
7878 /*
7879  * Stacked clause cidx
7880  * - process literals at indexes 1 to n
7881  * - the first literal is the implied literal
7882  * - return the number of literals to resolve.
7883  */
process_stacked_clause(sat_solver_t * solver,cidx_t cidx)7884 static uint32_t process_stacked_clause(sat_solver_t *solver, cidx_t cidx) {
7885   literal_t *lit;
7886   uint32_t i, n, toresolve;
7887 
7888   toresolve = 0;
7889   n = stacked_clause_length(&solver->stash, cidx);
7890   lit = stacked_clause_literals(&solver->stash, cidx);
7891   assert(n >= 2);
7892   for (i=1; i<n; i++) {
7893     toresolve += process_literal(solver, lit[i]);
7894   }
7895   return toresolve;
7896 }
7897 
7898 
7899 /*
7900  * Build learned clause and find UIP
7901  *
7902  * Result:
7903  * - the learned clause is stored in solver->buffer
7904  * - the implied literal is in solver->buffer.data[0]
7905  * - all literals in the learned clause are marked
7906  */
analyze_conflict(sat_solver_t * solver)7907 static void analyze_conflict(sat_solver_t *solver) {
7908   literal_t *stack;
7909   literal_t b;
7910   bvar_t x;
7911   uint32_t j, unresolved;
7912 
7913   assert(solver->decision_level > 0);
7914 
7915   unresolved = 0;
7916   vector_reset_and_reserve(&solver->buffer); // make room for one literal
7917 
7918   /*
7919    * Scan the conflict clause
7920    */
7921   if (solver->conflict_tag == CTAG_BINARY) {
7922     unresolved += process_literal(solver, solver->conflict_buffer[0]);
7923     unresolved += process_literal(solver, solver->conflict_buffer[1]);
7924   } else {
7925     assert(solver->conflict_tag == CTAG_CLAUSE);
7926     unresolved += process_clause(solver, solver->conflict_index, 0);
7927   }
7928 
7929   /*
7930    * Scan the assignment stack from top to bottom and process
7931    * the antecedent of all literals to resolve.
7932    */
7933   stack = solver->stack.lit;
7934   j = solver->stack.top;
7935   for (;;) {
7936     j --;
7937     b = stack[j];
7938     assert(d_level(solver, b) == solver->decision_level);
7939     if (literal_is_marked(solver, b)) {
7940       if (unresolved == 1) {
7941         // found UIP
7942         solver->buffer.data[0] = not(b);
7943         break;
7944       } else {
7945         unresolved --;
7946         x = var_of(b);
7947         unmark_variable(solver, x);
7948         switch (solver->ante_tag[x]) {
7949         case ATAG_BINARY:
7950           // solver->ante_data[x] = antecedent literal
7951           unresolved += process_literal(solver, solver->ante_data[x]);
7952           break;
7953 
7954         case ATAG_CLAUSE:
7955           assert(first_literal_of_clause(&solver->pool, solver->ante_data[x]) == b);
7956           // solver->ante_data[x] = antecedent clause
7957           unresolved += process_clause(solver, solver->ante_data[x], 1);
7958           break;
7959 
7960         default:
7961           assert(solver->ante_tag[x] == ATAG_STACKED);
7962           assert(first_literal_of_stacked_clause(&solver->stash, solver->ante_data[x]) == b);
7963           // solver->ante_data[x] = antecedent stacked clause
7964           unresolved += process_stacked_clause(solver, solver->ante_data[x]);
7965           break;
7966         }
7967       }
7968     }
7969   }
7970 
7971   check_marks(solver);
7972 }
7973 
7974 
7975 /*
7976  * CLAUSE SIMPLIFICATION
7977  */
7978 
7979 /*
7980  * Check whether literal l is redundant (can be removed from the learned clause)
7981  * - l must be a literal in the learned clause
7982  * - it's redundant if it's implied by other literals in the learned clause
7983  * - we assume that all these literals are marked.
7984  *
7985  * To check this, we explore the implication graph recursively from l.
7986  * Variables already visited are marked in solver->map:
7987  * - solver->map[x] == NOT_SEEN means x has not been seen yet
7988  * - solver->map[x] == IMPLIED means x is 'implied by marked literals'
7989  * - solver->map[x] == NOT_IMPLIED means x is 'not implied by marked literals'
7990  *
7991  * We use the following rules:
7992  * - a decision literal is not removable
7993  * - if l all immediate predecessors of l are marked or are are removable
7994  *   then l is removable.
7995  * - if one of l's predecessor is not marked and not removable then l
7996  *   is not removable.
7997  */
7998 enum {
7999   NOT_SEEN = 0,
8000   IMPLIED = 1,
8001   NOT_IMPLIED = 2
8002 };
8003 
8004 // number of predecessors of x in the implication graph
num_predecessors(sat_solver_t * solver,bvar_t x)8005 static uint32_t num_predecessors(sat_solver_t *solver, bvar_t x) {
8006   uint32_t n;
8007 
8008   switch (solver->ante_tag[x]) {
8009   case ATAG_BINARY:
8010     n = 1;
8011     break;
8012 
8013   case ATAG_CLAUSE:
8014     n = clause_length(&solver->pool, solver->ante_data[x]) - 1;
8015     break;
8016 
8017   default:
8018     assert(solver->ante_tag[x] == ATAG_STACKED);
8019     n = stacked_clause_length(&solver->stash, solver->ante_data[x]) - 1;
8020     break;
8021   }
8022   return n;
8023 }
8024 
8025 // get the i-th predecessor of x
predecessor(sat_solver_t * solver,bvar_t x,uint32_t i)8026 static bvar_t predecessor(sat_solver_t *solver, bvar_t x, uint32_t i) {
8027   literal_t *lit;
8028   literal_t l;
8029 
8030   switch (solver->ante_tag[x]) {
8031   case ATAG_BINARY:
8032     assert(i == 0);
8033     l = solver->ante_data[x];
8034     break;
8035 
8036   case ATAG_CLAUSE:
8037     assert(i < clause_length(&solver->pool, solver->ante_data[x]) - 1);
8038     lit = clause_literals(&solver->pool, solver->ante_data[x]);
8039     l = lit[i + 1];
8040     break;
8041 
8042   default:
8043     assert(solver->ante_tag[x] == ATAG_STACKED);
8044     assert(i < stacked_clause_length(&solver->stash, solver->ante_data[x]) - 1);
8045     lit = stacked_clause_literals(&solver->stash, solver->ante_data[x]);
8046     l = lit[i + 1];
8047     break;
8048   }
8049 
8050   return var_of(l);
8051 }
8052 
8053 // auxiliary function: check whether x is already explored and IMPLIED or
8054 // trivially implied by marked literals
var_is_implied(const sat_solver_t * solver,bvar_t x)8055 static inline bool var_is_implied(const sat_solver_t *solver, bvar_t x) {
8056   return variable_is_marked(solver, x) ||
8057     solver->ante_tag[x] == ATAG_UNIT ||
8058     tag_map_read(&solver->map, x) == IMPLIED;
8059 }
8060 
8061 // check whether x is already explored and NOT_IMPLIED
8062 // or whether x is a decision variable (can't be implied by marked literals)
var_is_not_implied(const sat_solver_t * solver,bvar_t x)8063 static inline bool var_is_not_implied(const sat_solver_t *solver, bvar_t x) {
8064   assert(!variable_is_marked(solver, x));
8065   return solver->ante_tag[x] == ATAG_DECISION || tag_map_read(&solver->map, x) == NOT_IMPLIED;
8066 }
8067 
8068 
implied_by_marked_literals(sat_solver_t * solver,literal_t l)8069 static bool implied_by_marked_literals(sat_solver_t *solver, literal_t l) {
8070   gstack_t *gstack;
8071   tag_map_t *map;
8072   gstack_elem_t *top;
8073   bvar_t x, y;
8074   uint32_t i;
8075 
8076   x = var_of(l);
8077   map = &solver->map;
8078 
8079   if (var_is_implied(solver, x)) {
8080     return true;
8081   }
8082   if (var_is_not_implied(solver, x)) {
8083     return false;
8084   }
8085 
8086   gstack = &solver->gstack;
8087   assert(gstack_is_empty(gstack));
8088   gstack_push_vertex(gstack, x, 0);
8089 
8090   do {
8091     top = gstack_top(gstack);
8092     x = top->vertex;
8093     if (top->index == num_predecessors(solver, x)) {
8094       tag_map_write(map, x, IMPLIED);
8095       gstack_pop(gstack);
8096     } else {
8097       y = predecessor(solver, x, top->index);
8098       top->index ++;
8099       if (var_is_implied(solver, y)) {
8100         continue;
8101       }
8102       if (var_is_not_implied(solver, y)) {
8103         goto not_implied;
8104       }
8105       gstack_push_vertex(gstack, y, 0);
8106     }
8107   } while (! gstack_is_empty(gstack));
8108 
8109   return true;
8110 
8111  not_implied:
8112   for (i=0; i<gstack->top; i++) {
8113     tag_map_write(map, gstack->data[i].vertex, NOT_IMPLIED);
8114   }
8115   reset_gstack(gstack);
8116   return false;
8117 }
8118 
8119 // check whether literals a[1 ... n-1] are all implied by marked literals
array_implied_by_marked_literals(sat_solver_t * solver,literal_t * a,uint32_t n)8120 static bool array_implied_by_marked_literals(sat_solver_t *solver, literal_t *a, uint32_t n) {
8121   uint32_t i;
8122 
8123   for (i=1; i<n; i++) {
8124     if (! implied_by_marked_literals(solver, a[i])) {
8125       return false;
8126     }
8127   }
8128   return true;
8129 }
8130 
8131 // check whether l is implied by other literals in the learned clause
8132 // (l is in the learned clause, so it is marked).
literal_is_redundant(sat_solver_t * solver,literal_t l)8133 static bool literal_is_redundant(sat_solver_t *solver, literal_t l) {
8134   literal_t *lit;
8135   bvar_t x;
8136   antecedent_tag_t atag;
8137   cidx_t cidx;
8138   uint32_t n;
8139 
8140   x = var_of(l);
8141   assert(var_is_assigned(solver, x) && variable_is_marked(solver, x));
8142 
8143   atag = solver->ante_tag[x] & 0x7F; // remove mark bit
8144   switch (atag) {
8145   case ATAG_BINARY:
8146     // ante_data[x] = literal that implies not(l)
8147     return implied_by_marked_literals(solver, solver->ante_data[x]);
8148 
8149   case ATAG_CLAUSE:
8150     // ante_data[x] = clause that implies not(l)
8151     cidx = solver->ante_data[x];
8152     n = clause_length(&solver->pool, cidx);
8153     lit = clause_literals(&solver->pool, cidx);
8154     assert(lit[0] == not(l));
8155     return array_implied_by_marked_literals(solver, lit, n);
8156 
8157   case ATAG_STACKED:
8158     // ante_data[x] = stacked clause that implies not(l)
8159     cidx = solver->ante_data[x];
8160     n = stacked_clause_length(&solver->stash, cidx);
8161     lit = stacked_clause_literals(&solver->stash, cidx);
8162     assert(lit[0] == not(l));
8163     return array_implied_by_marked_literals(solver, lit, n);
8164 
8165   default:
8166     assert(atag == ATAG_DECISION);
8167     return false;
8168   }
8169 }
8170 
8171 
8172 /*
8173  * Simplify the learned clause:
8174  * - it's in solver->buffer
8175  * - all literals in solver->buffer are marked
8176  * - solver->buffer.data[0] is the implied literal
8177  * - all other literals have a decision level < solver->decision_level
8178  *
8179  * On exit:
8180  * - the simplified learned clause is in solver->buffer.
8181  * - all marks are removed.
8182  */
simplify_learned_clause(sat_solver_t * solver)8183 static void simplify_learned_clause(sat_solver_t *solver) {
8184   vector_t *buffer;
8185   uint32_t i, j, n;
8186   literal_t l;
8187 
8188   assert(solver->aux.size == 0);
8189 
8190   buffer = &solver->buffer;
8191   n = buffer->size;
8192   j = 1;
8193   for (i=1; i<n; i++) { // The first literal is not redundant
8194     l = buffer->data[i];
8195     if (literal_is_redundant(solver, l)) {
8196       // move l to the aux buffer to clean the marks later
8197       vector_push(&solver->aux, l);
8198       solver->stats.subsumed_literals ++;
8199     } else {
8200       // keep l into buffer
8201       buffer->data[j] = l;
8202       j ++;
8203     }
8204   }
8205   buffer->size = j;
8206 
8207   // cleanup: remove marks and reset the map
8208   clear_tag_map(&solver->map);
8209   for (i=0; i<j; i++) {
8210     unmark_variable(solver, var_of(buffer->data[i]));
8211   }
8212   n = solver->aux.size;
8213   for (i=0; i<n; i++) {
8214     unmark_variable(solver, var_of(solver->aux.data[i]));
8215   }
8216   reset_vector(&solver->aux);
8217 
8218   check_all_unmarked(solver);
8219 }
8220 
8221 
8222 /*
8223  * Prepare for backtracking:
8224  * - search for a literal of second highest decision level in
8225  *   the learned clause.
8226  * - solver->buffer contains the learned clause.
8227  * - the implied literal is in solver->buffer.data[0]
8228  */
prepare_to_backtrack(sat_solver_t * solver)8229 static void prepare_to_backtrack(sat_solver_t *solver) {
8230   uint32_t i, j, d, x, n;
8231   literal_t l, *b;
8232 
8233   b = (literal_t *) solver->buffer.data;
8234   n = solver->buffer.size;
8235 
8236   if (n == 1) {
8237     solver->backtrack_level = 0;
8238     return;
8239   }
8240 
8241   j = 1;
8242   l = b[1];
8243   d = d_level(solver, l);
8244   for (i=2; i<n; i++) {
8245     x = d_level(solver, b[i]);
8246     if (x > d) {
8247       d = x;
8248       j = i;
8249     }
8250   }
8251 
8252   // swap b[1] and b[j]
8253   b[1] = b[j];
8254   b[j] = l;
8255 
8256   // record backtrack level
8257   solver->backtrack_level = d;
8258 }
8259 
8260 
8261 /*
8262  * Update the exponential moving averages used by the restart heuristics
8263  *
8264  * We have
8265  *     ema_0 = 0
8266  *     ema_t+1 = 2^(32 - k) x + (1 - 2^k) ema_t
8267  * where k is less than 32 and x is the lbd of the learned clause
8268  * - as in the paper by Biere & Froehlich, we use
8269  *    k = 5  for the 'fast' ema
8270  *    k = 14 for the 'slow' ema
8271  *
8272  * Update: experimental change (07/28/2017): use k=16 for the slow ema
8273  * (same as cadical).
8274  *
8275  * NOTE: these updates can't overflow: the LDB is bounded by U < 2^30
8276  * then we have ema <= 2^32*U. Same thing for the number of assigned
8277  * variables.
8278  */
update_emas(sat_solver_t * solver,uint32_t x)8279 static void update_emas(sat_solver_t *solver, uint32_t x) {
8280 #if USE_DIVING
8281   if (! solver->diving) {
8282     solver->slow_ema -= solver->slow_ema >> 16;
8283     solver->slow_ema += ((uint64_t) x) << 16;
8284     solver->fast_ema -= solver->fast_ema >> 5;
8285     solver->fast_ema += ((uint64_t) x) << 27;
8286     solver->fast_count ++;
8287   }
8288 #else
8289   solver->slow_ema -= solver->slow_ema >> 16;
8290   solver->slow_ema += ((uint64_t) x) << 16;
8291   solver->fast_ema -= solver->fast_ema >> 5;
8292   solver->fast_ema += ((uint64_t) x) << 27;
8293   solver->fast_count ++;
8294 #endif
8295 }
8296 
8297 // update the search depth = number of assigned literals at the time
8298 // of a conflict
update_max_depth(sat_solver_t * solver)8299 static void update_max_depth(sat_solver_t *solver) {
8300   if (solver->stack.top > solver->max_depth) {
8301     solver->max_depth = solver->stack.top;
8302     solver->max_depth_conflicts = solver->stats.conflicts;
8303   }
8304 }
8305 
8306 // update the conflict level EMA
update_level(sat_solver_t * solver)8307 static void update_level(sat_solver_t *solver) {
8308   solver->level_ema -= solver->level_ema >> 16;solver->level_ema -= solver->level_ema >> 16;
8309   solver->level_ema += ((uint64_t) solver->decision_level) << 16;
8310 }
8311 
8312 
8313 /*
8314  * Resolve a conflict and add a learned clause
8315  * - solver->decision_level must be positive
8316  */
resolve_conflict(sat_solver_t * solver)8317 static void resolve_conflict(sat_solver_t *solver) {
8318   uint32_t n, d;
8319   literal_t l;
8320   cidx_t cidx;
8321 
8322   //  update_max_depth(solver);
8323 
8324   analyze_conflict(solver);
8325   simplify_learned_clause(solver);
8326   prepare_to_backtrack(solver);
8327 
8328   // EMA statistics
8329   n = solver->buffer.size;
8330   d = clause_lbd(solver, n, (literal_t *) solver->buffer.data);
8331   update_emas(solver, d);
8332 
8333   // Collect data if compiled with DATA=1
8334   export_conflict_data(solver, d);
8335 
8336   backtrack(solver, solver->backtrack_level);
8337   solver->conflict_tag = CTAG_NONE;
8338 
8339   // statistics
8340   update_level(solver);
8341 
8342   // add the learned clause
8343   l = solver->buffer.data[0];
8344   if (n >= 3) {
8345 #if USE_DIVING
8346     if (solver->diving && n >= solver->params.stack_threshold) {
8347       cidx = push_clause(&solver->stash, n, (literal_t *) solver->buffer.data);
8348       stacked_clause_propagation(solver, l, cidx);
8349     } else {
8350       cidx = add_learned_clause(solver, n, (literal_t *) solver->buffer.data);
8351       clause_propagation(solver, l, cidx);
8352     }
8353 #else
8354     cidx = add_learned_clause(solver, n, (literal_t *) solver->buffer.data);
8355     clause_propagation(solver, l, cidx);
8356 #endif
8357   } else if (n == 2) {
8358     add_binary_clause(solver, l, solver->buffer.data[1]);
8359     binary_clause_propagation(solver, l, solver->buffer.data[1]);
8360   } else {
8361     assert(n > 0);
8362     add_unit_clause(solver, l);
8363   }
8364 }
8365 
8366 
8367 
8368 
8369 /*****************************************************
8370  *  VARIABLE SUBSTITUTION + DATABASE SIMPLIFICATION  *
8371  ****************************************************/
8372 
8373 /*
8374  * Process unit literals found by equivalence checks
8375  */
process_subst_units(sat_solver_t * solver)8376 static void process_subst_units(sat_solver_t *solver) {
8377   vector_t *v;
8378   uint32_t i, n;
8379   literal_t l;
8380 
8381   v = &solver->subst_units;
8382   n = v->size;
8383   for (i=0; i<n; i++) {
8384     l = full_lit_subst(solver, v->data[i]);
8385     if (lit_is_unassigned(solver, l)) {
8386       add_unit_clause(solver, l);
8387     }
8388   }
8389   reset_vector(v);
8390 }
8391 
8392 /*
8393  * Compute SCCs and apply the substitution if any + perform one
8394  * round of propagation.
8395  *
8396  * - sets solver->has_empty_clause to true if a conflict is detected.
8397  */
try_scc_simplification(sat_solver_t * solver)8398 static void try_scc_simplification(sat_solver_t *solver) {
8399   vector_t *v;
8400   uint32_t i, n, n0, units;
8401   bvar_t x;
8402 
8403   assert(solver->decision_level == 0);
8404 
8405   solver->stats.scc_calls ++;
8406   units = solver->units;
8407 
8408   compute_sccs(solver);
8409   if (solver->has_empty_clause) {
8410     fprintf(stderr, "c empty clause after SCC computation\n");
8411     reset_vector(&solver->subst_vars);
8412     return;
8413   }
8414 
8415   assert(solver->subst_units.size == 0);
8416 
8417   v = &solver->subst_vars;
8418   n0 = v->size;
8419   if (n0 > 0) {
8420     if (solver->verbosity >= 3) {
8421       fprintf(stderr, "c  scc %"PRIu32" variable substitutions\n", n0);
8422     }
8423     if (solver->stats.subst_vars >= solver->simplify_subst_next) {
8424       try_equivalent_vars(solver, 2);
8425       solver->simplify_subst_next = solver->stats.subst_vars + solver->params.simplify_subst_delta;
8426     }
8427     n = v->size;
8428 
8429     // equivalent_vars may add more variables to vector v
8430     if (solver->verbosity >= 3) {
8431       if (n > n0)
8432 	fprintf(stderr, "c  eq  %"PRIu32" substitutions\n", n - n0);
8433       if (solver->subst_units.size > 0)
8434 	fprintf(stderr, "c  eq  %"PRIu32" units\n", solver->subst_units.size);
8435     }
8436 
8437     // save clause to extend the model later
8438     for (i=0; i<n; i++) {
8439       x = v->data[i];
8440       assert(solver->ante_tag[x] == ATAG_SUBST);
8441       // the substitution is x := ante_data[x]
8442       clause_vector_save_subst_clause(&solver->saved_clauses, solver->ante_data[x], pos_lit(x));
8443     }
8444     reset_vector(v);
8445 
8446     report(solver, "scc");
8447 
8448     // apply the substitution
8449     apply_substitution(solver);
8450     if (solver->has_empty_clause) {
8451       fprintf(stderr, "c empty clause after substitution\n");
8452       return;
8453     }
8454 
8455     // process the unit literals
8456     solver->stats.subst_units += solver->subst_units.size;
8457     process_subst_units(solver);
8458 
8459     // one round of propagation
8460     if (solver->units > units) {
8461       level0_propagation(solver);
8462       if (solver->has_empty_clause) {
8463 	fprintf(stderr, "c empty clause after substitution and propagation\n");
8464 	return;
8465       }
8466     }
8467   }
8468 }
8469 
8470 
8471 
8472 
8473 /*************************************************
8474  *  RECOVER TRUTH VALUE OF ELIMINATED VARIABLES  *
8475  ************************************************/
8476 
8477 /*
8478  * Check whether all literals in a[0 ... n] are false
8479  */
saved_clause_is_false(sat_solver_t * solver,uint32_t * a,uint32_t n)8480 static bool saved_clause_is_false(sat_solver_t *solver, uint32_t *a, uint32_t n) {
8481   uint32_t i;
8482 
8483   for (i=0; i<n; i++) {
8484     if (lit_value(solver, a[i]) == VAL_TRUE) {
8485       return false;
8486     }
8487     assert(lit_value(solver, a[i]) == VAL_FALSE);
8488   }
8489 
8490   return true;
8491 }
8492 
8493 /*
8494  * Process a block of saved clauses
8495  * - a = start of the block
8496  * - n = block length
8497  * - a[n-1] = literal to flip if needed
8498  */
extend_assignment_for_block(sat_solver_t * solver,uint32_t * a,uint32_t n)8499 static void extend_assignment_for_block(sat_solver_t *solver, uint32_t *a, uint32_t n) {
8500   literal_t l;
8501   uint32_t i, j;
8502   bval_t val;
8503 
8504   l = a[n-1];
8505   assert(solver->ante_tag[var_of(l)] == ATAG_ELIM || solver->ante_tag[var_of(l)] == ATAG_SUBST);
8506 
8507   val = VAL_FALSE; // default value for l
8508   i = 0;
8509   while (i < n) {
8510     j = i;
8511     while (a[j] != l) j++;
8512     // a[i ... j] = saved clause with a[j] == l
8513     if (saved_clause_is_false(solver, a+i, j-i)) {
8514       // all literals in a[i ... j-1] are false so l is forced to true
8515       val = VAL_TRUE;
8516       break;
8517     }
8518     i = j+1;
8519   }
8520 
8521   solver->value[l] = val;
8522   solver->value[not(l)] = opposite_val(val);
8523 }
8524 
8525 
8526 #if 0
8527 // NOT USED ANYMORE.
8528 
8529 // we now store a clause in the saved_clause vector whenever we
8530 // eliminate a variable.
8531 /*
8532  * Extend the current assignment to variables eliminated by substitution
8533  */
8534 static void extend_assignment_by_substitution(sat_solver_t *solver) {
8535   uint32_t i, n;
8536   literal_t l;
8537   bval_t val;
8538 
8539   n = solver->nvars;
8540   for (i=1; i<n; i++) {
8541     if (solver->ante_tag[i] == ATAG_SUBST) {
8542       l = full_var_subst(solver, i);
8543       assert(lit_is_assigned(solver, l));
8544       val = lit_value(solver, l);
8545 
8546       solver->value[pos_lit(i)] = val;
8547       solver->value[neg_lit(i)] = opposite_val(val);
8548     }
8549   }
8550 }
8551 
8552 #endif
8553 
8554 
8555 /*
8556  * Extend the current assignment to all eliminated variables
8557  */
extend_assignment(sat_solver_t * solver)8558 static void extend_assignment(sat_solver_t *solver) {
8559   nclause_vector_t *v;
8560   uint32_t n, block_size;;
8561 
8562   v = &solver->saved_clauses;
8563   n = v->top;
8564   while (n > 0) {
8565     n --;
8566     block_size = v->data[n];
8567     assert(block_size >= 1 && block_size <= n);
8568     n -= block_size;
8569     extend_assignment_for_block(solver, v->data + n, block_size);
8570   }
8571 }
8572 
8573 
8574 
8575 /*****************
8576  *  HEURISTICS   *
8577  ****************/
8578 
8579 /*
8580  * Number of literals assigned at level 0
8581  * - this is used to decide whether to call simplify_clause_database
8582  */
level0_literals(const sat_solver_t * solver)8583 static uint32_t level0_literals(const sat_solver_t *solver) {
8584   uint32_t n;
8585 
8586   n = solver->stack.top;
8587   if (solver->decision_level > 0) {
8588     n = solver->stack.level_index[1];
8589   }
8590   return n;
8591 }
8592 
8593 
8594 /*
8595  * MODE
8596  */
8597 
8598 /*
8599  * Initial mode
8600  */
init_mode(sat_solver_t * solver)8601 static void init_mode(sat_solver_t *solver) {
8602   solver->progress_units = 0;
8603   solver->progress_binaries = 0;
8604   solver->progress = solver->params.search_counter;
8605   solver->check_next = solver->params.search_period;
8606   solver->diving = false;
8607   solver->dive_budget = solver->params.diving_budget;
8608   solver->max_depth = 0;
8609   solver->max_depth_conflicts = 0;
8610   solver->dive_start = 0;
8611 }
8612 
8613 #if USE_DIVING
8614 /*
8615  * Check whether we're making progress (in search mode).
8616  * - we declare progress when we've learned new unit or binary clauses
8617  */
made_progress(sat_solver_t * solver)8618 static bool made_progress(sat_solver_t *solver) {
8619   uint32_t units, binaries;
8620   bool progress;
8621 
8622   units = level0_literals(solver);
8623   binaries = solver->binaries;
8624   progress = units > solver->progress_units || binaries > solver->progress_binaries;
8625   solver->progress_units = units;
8626   solver->progress_binaries = binaries;
8627 
8628   return progress;
8629 }
8630 
need_check(const sat_solver_t * solver)8631 static inline bool need_check(const sat_solver_t *solver) {
8632   return solver->stats.conflicts >= solver->check_next;
8633 }
8634 
switch_to_diving(sat_solver_t * solver)8635 static bool switch_to_diving(sat_solver_t *solver) {
8636   assert(! solver->diving);
8637 
8638   solver->check_next += solver->params.search_period;
8639 
8640   if (made_progress(solver)) {
8641     solver->progress = solver->params.search_counter;
8642   } else {
8643     assert(solver->progress > 0);
8644     solver->progress --;
8645     if (solver->progress == 0) {
8646       solver->diving = true;
8647       solver->max_depth_conflicts = solver->stats.conflicts;
8648       solver->max_depth = 0;
8649       solver->dive_start = solver->stats.conflicts;
8650       solver->stats.dives ++;
8651       return true;
8652     }
8653   }
8654 
8655   return false;
8656 }
8657 
done_diving(sat_solver_t * solver)8658 static void done_diving(sat_solver_t *solver) {
8659   uint64_t delta;
8660 
8661   solver->diving = false;
8662   if (solver->dive_budget <= 200000) {
8663     solver->dive_budget += solver->dive_budget >> 2;
8664   }
8665   solver->progress = solver->params.search_counter;
8666   solver->progress_units = level0_literals(solver);
8667   solver->progress_binaries = solver->binaries;
8668 
8669   // adjust reduce_next, restart_next, simplify_next, etc.
8670   // delta = number of conflicts in the dive
8671   delta = solver->stats.conflicts - solver->dive_start;
8672   solver->reduce_next += delta;
8673   solver->restart_next += delta;
8674   solver->simplify_next += delta;
8675   solver->check_next += delta;
8676 }
8677 
8678 #endif
8679 
8680 /*
8681  * WHEN TO RESTART
8682  */
8683 
8684 /*
8685  * Glucose-style restart condition:
8686  * 1) solver->fast_ema is an estimate of the quality of the recently
8687  *    learned clauses.
8688  * 2) solver->slow_ema is an estimate of the average quality of all
8689  *    learned clauses.
8690  *
8691  * Intuition:
8692  * - if solver->fast_ema is larger than solver->slow_ema then recent
8693  *   learned clauses don't seem too good. We want to restart.
8694  *
8695  * To make this more precise: we use a magic constant K = 0.9 (approximately)
8696  * Worse than average learned clauses is 'fast_ema * K > slow_ema'
8697  * For our fixed point implementation, we use
8698  *    K = (1 - 1/2^4 - 1/2^5) = 0.90625
8699  *
8700  * To avoid restarting every time, we keep track of the number of
8701  * samples from which fast_ema is computed (in solver->fast_count).
8702  * We wait until fast_count >= 50 before restarting.
8703  */
8704 
8705 
8706 /*
8707  * Initialize the restart counters
8708  */
init_restart(sat_solver_t * solver)8709 static void init_restart(sat_solver_t *solver) {
8710   solver->slow_ema = 0;
8711   solver->fast_ema = 0;
8712   solver->level_ema = 0;
8713   solver->restart_next = solver->params.restart_interval;
8714   solver->fast_count = 0;
8715 }
8716 
8717 /*
8718  * Check for restart
8719  */
8720 #if USE_DIVING
8721 
need_restart(sat_solver_t * solver)8722 static bool need_restart(sat_solver_t *solver) {
8723   uint64_t aux;
8724 
8725   if (solver->diving) {
8726     return solver->stats.conflicts > solver->max_depth_conflicts + solver->dive_budget;
8727   }
8728 
8729   if (solver->stats.conflicts >= solver->restart_next &&
8730       solver->decision_level >= (uint32_t) (solver->fast_ema >> 32)) {
8731     aux = solver->fast_ema;
8732     //    aux -= (aux >> 3) + (aux >> 4) + (aux >> 6); // K * fast_ema
8733     aux -= (aux >> 4) + (aux >> 5);    // approximately 0.9 * fast_ema
8734     if (aux >= solver->slow_ema) {
8735       return true;
8736     }
8737   }
8738 
8739   return solver->stats.conflicts >= solver->check_next;
8740 }
8741 
8742 #else
8743 
need_restart(sat_solver_t * solver)8744 static bool need_restart(sat_solver_t *solver) {
8745   uint64_t aux;
8746 
8747   if (solver->stats.conflicts >= solver->restart_next &&
8748       solver->decision_level >= (uint32_t) (solver->fast_ema >> 32)) {
8749     aux = solver->fast_ema;
8750     //    aux -= (aux >> 3) + (aux >> 4) + (aux >> 6); // K * fast_ema
8751     aux -= (aux >> 4) + (aux >> 5);    // approximately 0.9 * fast_ema
8752     if (aux >= solver->slow_ema) {
8753       return true;
8754     }
8755   }
8756 
8757   return false;
8758 }
8759 
8760 #endif
8761 
done_restart(sat_solver_t * solver)8762 static void done_restart(sat_solver_t *solver) {
8763   solver->restart_next = solver->stats.conflicts + solver->params.restart_interval;
8764 }
8765 
8766 
8767 
8768 /*
8769  * WHEN TO REDUCE
8770  */
8771 
8772 /*
8773  * Heuristic similar to Cadical:
8774  * - we keep three counters:
8775  *    reduce_next
8776  *    reduce_inc
8777  *    reduce_inc2
8778  * - when the number of conflicts is bigger than reduce_next
8779  *   we call reduce
8780  * - after reduce, we update the counters:
8781  *    reduce_inc = reduce_inc + reduce_inc2
8782  *    reduce_next = reduce_next + reduce_inc
8783  *    reduce_inc2 = max(0, reduce_inc2 - 1)
8784  */
8785 
8786 /*
8787  * Initialize the reduce counters
8788  */
init_reduce(sat_solver_t * solver)8789 static void init_reduce(sat_solver_t *solver) {
8790   solver->reduce_next = solver->params.reduce_interval;
8791   solver->reduce_inc = solver->params.reduce_interval;
8792   solver->reduce_inc2 = solver->params.reduce_delta;
8793 }
8794 
8795 /*
8796  * Check to trigger call to reduce_learned_clause_set
8797  */
need_reduce(const sat_solver_t * solver)8798 static inline bool need_reduce(const sat_solver_t *solver) {
8799   //  return !solver->diving && solver->stats.conflicts >= solver->reduce_next;
8800   return solver->stats.conflicts >= solver->reduce_next;
8801 }
8802 
8803 /*
8804  * Update counters after a call to reduce
8805  */
done_reduce(sat_solver_t * solver)8806 static void done_reduce(sat_solver_t *solver) {
8807   solver->reduce_inc += solver->reduce_inc2;
8808   solver->reduce_next = solver->stats.conflicts + solver->reduce_inc;
8809   if (solver->reduce_inc2 > 0) {
8810     solver->reduce_inc2 --;
8811   }
8812 }
8813 
8814 
8815 /*
8816  * WHEN TO SIMPLIFY
8817  */
8818 
8819 /*
8820  * Initialize counters
8821  */
init_simplify(sat_solver_t * solver)8822 static void init_simplify(sat_solver_t *solver) {
8823   solver->simplify_assigned = 0;
8824   solver->simplify_binaries = 0;
8825   solver->simplify_subst_next = 0;
8826   solver->simplify_next = 0;
8827 }
8828 
8829 /*
8830  * Heuristic to trigger a call to simplify_clause_database:
8831  * - we call simplify when there's more literals assigned at level 0
8832  *   (or more binary clauses)
8833  */
need_simplify(const sat_solver_t * solver)8834 static bool need_simplify(const sat_solver_t *solver) {
8835   return (level0_literals(solver) > solver->simplify_assigned ||
8836 	  solver->binaries > solver->simplify_binaries + solver->params.simplify_bin_delta ||
8837 	  (solver->binaries > solver->simplify_binaries && solver->stats.conflicts >= solver->simplify_next + 100000))
8838     && solver->stats.conflicts >= solver->simplify_next;
8839 }
8840 
8841 
8842 /*
8843  * Update counters after simplify
8844  */
done_simplify(sat_solver_t * solver)8845 static void done_simplify(sat_solver_t *solver) {
8846   /*
8847    * new_bins = number of binary clauses produced in this
8848    *            simplification round
8849    * these clauses have not been seen by the SCC construction.
8850    * Some of the new bin clauses may have been deleted so we can't assume
8851    */
8852   if (solver->simplify_new_bins > solver->binaries) {
8853     solver->simplify_binaries = solver->binaries;
8854   } else {
8855     solver->simplify_binaries = solver->binaries - solver->simplify_new_bins;
8856   }
8857   solver->simplify_assigned = solver->stack.top;
8858   solver->simplify_next = solver->stats.conflicts + solver->params.simplify_interval;
8859 
8860   solver->check_next = solver->stats.conflicts + solver->params.search_period;
8861   solver->progress = solver->params.search_counter;
8862   solver->progress_units = level0_literals(solver);
8863   solver->progress_binaries = solver->binaries;
8864 
8865 #if 0
8866   fprintf(stderr, "c done simplify\n");
8867   fprintf(stderr, "c   simplify_binaries = %"PRIu32"\n", solver->simplify_binaries);
8868   fprintf(stderr, "c   simplify_assigned = %"PRIu32"\n", solver->simplify_assigned);
8869   fprintf(stderr, "c   simplify_next = %"PRIu64"\n", solver->simplify_next);
8870   fprintf(stderr, "c   simplify_next + 100000 = %"PRIu64"\n", solver->simplify_next + 100000);
8871   fprintf(stderr, "c\n");
8872 #endif
8873 }
8874 
8875 
8876 
8877 
8878 /*****************************
8879  *  MAIN SOLVING PROCEDURES  *
8880  ****************************/
8881 
8882 /*
8883  * Select an unassigned decision variable
8884  * - return 0 if all variables are assigned
8885  */
nsat_select_decision_variable(sat_solver_t * solver)8886 static bvar_t nsat_select_decision_variable(sat_solver_t *solver) {
8887   uint32_t rnd;
8888   bvar_t x;
8889 
8890   if (solver->params.randomness > 0) {
8891     rnd = random_uint32(solver) & VAR_RANDOM_MASK;
8892     if (rnd < solver->params.randomness) {
8893       x = random_uint(solver, solver->nvars);
8894       if (var_is_active(solver, x)) {
8895         assert(x > 0);
8896         solver->stats.random_decisions ++;
8897         return x;
8898       }
8899     }
8900   }
8901 
8902   /*
8903    * Unassigned variable of highest activity
8904    */
8905   while (! heap_is_empty(&solver->heap)) {
8906     x = heap_get_top(&solver->heap);
8907     if (var_is_active(solver, x)) {
8908       assert(x > 0);
8909       return x;
8910     }
8911   }
8912 
8913 #if 0
8914   /*
8915    * Check the variables in [heap->vmax ... heap->nvars - 1]
8916    */
8917   x = solver->heap.vmax;
8918   while (x < solver->heap.nvars) {
8919     if (var_is_active(solver, x)) {
8920       solver->heap.vmax = x+1;
8921       return x;
8922     }
8923     x ++;
8924   }
8925 
8926   assert(x == solver->heap.nvars);
8927   solver->heap.vmax = x;
8928 #endif
8929 
8930   return 0;
8931 }
8932 
8933 /*
8934  * Preferred literal when x is selected as decision variable.
8935  * - we pick l := pos_lit(x) then check whether value[l] is 0b00 or 0b01
8936  * - in the first case, the preferred value for l is false so we return not(l)
8937  */
preferred_literal(const sat_solver_t * solver,bvar_t x)8938 static inline literal_t preferred_literal(const sat_solver_t *solver, bvar_t x) {
8939   literal_t l;
8940 
8941   assert(var_is_unassigned(solver, x));
8942 
8943   l = pos_lit(x);
8944   /*
8945    * Since l is not assigned, value[l] is either VAL_UNDEF_FALSE (i.e., 0)
8946    * or VAL_UNDEF_TRUE (i.e., 1).
8947    *
8948    * We return l if value[l] = VAL_UNDEF_TRUE = 1.
8949    * We return not(l) if value[l] = VAL_UNDEF_FALSE = 0.
8950    * Since not(l) is l^1, the returned value is (l ^ 1 ^ value[l]).
8951    */
8952   l ^= 1 ^ solver->value[l];
8953   assert((var_prefers_true(solver, x) && l == pos_lit(x)) ||
8954          (!var_prefers_true(solver, x) && l == neg_lit(x)));
8955 
8956   return l;
8957 }
8958 
8959 
8960 /*
8961  * Search until we get sat/unsat or we restart
8962  * - restart is based on the LBD/Glucose heuristics as modified by
8963  *   Biere & Froehlich.
8964  */
sat_search(sat_solver_t * solver)8965 static void sat_search(sat_solver_t *solver) {
8966   bvar_t x;
8967 
8968   assert(solver->stack.prop_ptr == solver->stack.top);
8969 
8970   check_propagation(solver);
8971   check_watch_vectors(solver);
8972 
8973   for (;;) {
8974     nsat_boolean_propagation(solver);
8975     if (solver->conflict_tag == CTAG_NONE) {
8976       // No conflict
8977 #if USE_DIVING
8978       if (need_restart(solver) || need_simplify(solver)) {
8979         break;
8980       }
8981 #else
8982       if (need_restart(solver)) {
8983 	break;
8984       }
8985 #endif
8986       if (need_reduce(solver)) {
8987         nsat_reduce_learned_clause_set(solver);
8988         check_watch_vectors(solver);
8989 	done_reduce(solver);
8990       }
8991 
8992       update_max_depth(solver);
8993 
8994       x = nsat_select_decision_variable(solver);
8995       if (x == 0) {
8996         solver->status = STAT_SAT;
8997         break;
8998       }
8999       nsat_decide_literal(solver, preferred_literal(solver, x));
9000     } else {
9001       // Conflict
9002       if (solver->decision_level == 0) {
9003         export_last_conflict(solver);
9004         solver->status = STAT_UNSAT;
9005         break;
9006       }
9007       resolve_conflict(solver);
9008       check_watch_vectors(solver);
9009 
9010 #if USE_DIVING
9011       if (! solver->diving) {
9012 	decay_clause_activities(solver);
9013       }
9014 #else
9015       decay_clause_activities(solver);
9016 #endif
9017     }
9018   }
9019 }
9020 
9021 
9022 
9023 /*
9024  * Simplify: call try_scc_simplification, then simplify clause database
9025  * - add empty clause and set status to UNSAT if there's a conflict.
9026  */
nsat_simplify(sat_solver_t * solver)9027 static void nsat_simplify(sat_solver_t *solver) {
9028   solver->simplify_new_units = 0;
9029   solver->simplify_new_bins = 0;
9030   if (solver->binaries > solver->simplify_binaries) {
9031     try_scc_simplification(solver);
9032     if (solver->has_empty_clause) return;
9033   }
9034   if (level0_literals(solver) > solver->simplify_assigned) {
9035     simplify_clause_database(solver);
9036   }
9037 }
9038 
9039 
9040 /*
9041  * Preprocessing: call nsat_preprocess and print statistics
9042  */
nsat_do_preprocess(sat_solver_t * solver)9043 static void nsat_do_preprocess(sat_solver_t *solver) {
9044   double start, end;
9045 
9046   if (solver->verbosity >= 1) {
9047     start = get_cpu_time();
9048     nsat_preprocess(solver);
9049     end = get_cpu_time();
9050     show_preprocessing_stats(solver, time_diff(end, start));
9051   } else {
9052     nsat_preprocess(solver);
9053   }
9054 
9055   solver->preprocess = false;
9056 }
9057 
9058 
9059 #if 0
9060 static void add_not_eq(sat_solver_t *solver, bvar_t x, literal_t l) {
9061   literal_t a[2];
9062 
9063   // not (x == l) is (not ((x and l) or (~x and ~l)))
9064   //              is (not (x and l)) and (not (~x and ~l))
9065   //              is (~x or ~l) and (x or l)
9066   a[0] = pos_lit(x);
9067   a[1] = l;
9068   nsat_solver_simplify_and_add_clause(solver, 2, a);
9069 
9070   a[0] = neg_lit(x);
9071   a[1] = not(l);
9072   nsat_solver_simplify_and_add_clause(solver, 2, a);
9073 
9074 }
9075 
9076 static void add_eq(sat_solver_t *solver, bvar_t x, literal_t l) {
9077   add_not_eq(solver, x, not(l));
9078 }
9079 
9080 static void make_true(sat_solver_t *solver, literal_t l) {
9081   literal_t aux[1];
9082   aux[0] = l;
9083   nsat_solver_simplify_and_add_clause(solver, 1, aux);
9084 }
9085 
9086 static void make_false(sat_solver_t *solver, literal_t l) {
9087   literal_t aux[1];
9088   aux[0] = not(l);
9089   nsat_solver_simplify_and_add_clause(solver, 1, aux);
9090 }
9091 
9092 #endif
9093 
9094 
9095 /*
9096  * Solving procedure
9097  */
nsat_solve(sat_solver_t * solver)9098 solver_status_t nsat_solve(sat_solver_t *solver) {
9099 
9100   //  open_stat_file();
9101 
9102   if (solver->has_empty_clause) goto done;
9103 
9104   solver->prng = solver->params.seed;
9105   solver->cla_inc = INIT_CLAUSE_ACTIVITY_INCREMENT;
9106 
9107   init_var_ranks(solver);
9108   init_mode(solver);
9109   init_restart(solver);
9110   init_reduce(solver);
9111   init_simplify(solver);
9112 
9113   if (solver->preprocess) {
9114     // preprocess + one round of simplification
9115     nsat_do_preprocess(solver);
9116     if (solver->has_empty_clause) goto done;
9117     nsat_simplify(solver);
9118     done_simplify(solver);
9119   } else {
9120     // one round of propagation + one round of simplification
9121     level0_propagation(solver);
9122     if (solver->has_empty_clause) goto done;
9123     nsat_simplify(solver);
9124     done_simplify(solver);
9125   }
9126 
9127   report(solver, "");
9128 
9129   // main loop: simplification may detect unsat
9130   // and set has_empty_clause to true
9131   while (! solver->has_empty_clause) {
9132     sat_search(solver);
9133     if (solver->status != STAT_UNKNOWN) break;
9134 
9135 #if USE_DIVING
9136     if (need_simplify(solver)) {
9137       if (solver->diving) {
9138 	done_diving(solver);
9139       }
9140       full_restart(solver);
9141       done_restart(solver);
9142       nsat_simplify(solver);
9143       done_simplify(solver);
9144     } else if (solver->diving) {
9145       done_diving(solver);
9146       full_restart(solver);
9147       report(solver, "");
9148     } else if (need_check(solver)) {
9149       if (switch_to_diving(solver)) {
9150 	full_restart(solver);
9151 	report(solver, "dive");
9152       }
9153     } else {
9154       partial_restart(solver);
9155       done_restart(solver);
9156     }
9157 #else
9158     if (need_simplify(solver)) {
9159 #if 0
9160       fprintf(stderr, "c start simplify\n");
9161       fprintf(stderr, "c   binaries = %"PRIu32"\n", solver->binaries);
9162       fprintf(stderr, "c   assigned = %"PRIu32"\n", level0_literals(solver));
9163       fprintf(stderr, "c   conflicts = %"PRIu64"\n", solver->stats.conflicts);
9164       fprintf(stderr, "c\n");
9165 #endif
9166       full_restart(solver);
9167       done_restart(solver);
9168       nsat_simplify(solver);
9169       done_simplify(solver);
9170     } else {
9171       partial_restart(solver);
9172       done_restart(solver);
9173     }
9174 #endif
9175 
9176   }
9177 
9178   report(solver, "end");
9179 
9180  done:
9181   assert(solver->status == STAT_UNSAT || solver->status == STAT_SAT);
9182 
9183   if (solver->status == STAT_SAT) {
9184     solver->stats.successful_dive = solver->diving;
9185     extend_assignment(solver);
9186   }
9187 
9188 #if 0
9189   fprintf(stderr, "\n\n*** DONE ***\n");
9190   show_state(stderr, solver);
9191 #endif
9192 
9193   if (solver->verbosity >= 2) {
9194     nsat_show_statistics(stderr, solver);
9195   }
9196 
9197   //  close_stat_file();
9198 
9199   return solver->status;
9200 }
9201 
9202 
9203 /************************
9204  *  DISPLAY STATISTICS  *
9205  ***********************/
9206 
nsat_show_statistics(FILE * f,const sat_solver_t * solver)9207 void nsat_show_statistics(FILE *f, const sat_solver_t *solver) {
9208   const solver_stats_t *stat = &solver->stats;
9209 
9210   fprintf(f, "c\n");
9211   fprintf(f, "c Statistics\n");
9212   fprintf(f, "c  starts                  : %"PRIu32"\n", stat->starts);
9213 #if USE_DIVING
9214   fprintf(f, "c  dives                   : %"PRIu32"\n", stat->dives);
9215   fprintf(f, "c  successful dive         : %"PRIu32"\n", stat->successful_dive);
9216 #endif
9217   fprintf(f, "c  simplify db             : %"PRIu32"\n", stat->simplify_calls);
9218   fprintf(f, "c  reduce db               : %"PRIu32"\n", stat->reduce_calls);
9219   fprintf(f, "c  scc calls               : %"PRIu32"\n", stat->scc_calls);
9220   fprintf(f, "c  apply subst calls       : %"PRIu32"\n", stat->subst_calls);
9221   fprintf(f, "c  substituted vars        : %"PRIu32"\n", stat->subst_vars);
9222   fprintf(f, "c  unit equiv              : %"PRIu32"\n", stat->subst_units);
9223   fprintf(f, "c  equivalences            : %"PRIu32"\n", stat->equivs);
9224   fprintf(f, "c  decisions               : %"PRIu64"\n", stat->decisions);
9225   fprintf(f, "c  random decisions        : %"PRIu64"\n", stat->random_decisions);
9226   fprintf(f, "c  propagations            : %"PRIu64"\n", stat->propagations);
9227   fprintf(f, "c  conflicts               : %"PRIu64"\n", stat->conflicts);
9228   fprintf(f, "c  lits in pb. clauses     : %"PRIu32"\n", solver->pool.num_prob_literals);
9229   fprintf(f, "c  lits in learned clauses : %"PRIu32"\n", solver->pool.num_learned_literals);
9230   fprintf(f, "c  subsumed lits.          : %"PRIu64"\n", stat->subsumed_literals);
9231   fprintf(f, "c  deleted pb. clauses     : %"PRIu64"\n", stat->prob_clauses_deleted);
9232   fprintf(f, "c  deleted learned clauses : %"PRIu64"\n", stat->learned_clauses_deleted);
9233   fprintf(f, "c\n");
9234 }
9235 
9236 
9237 
9238 
9239 /************
9240  *  MODELS  *
9241  ***********/
9242 
9243 /*
9244  * Return the model: copy all variable value into val
9245  * - val's size must be at least solver->nvars
9246  * - val[0] is always true
9247  */
nsat_get_allvars_assignment(const sat_solver_t * solver,bval_t * val)9248 void nsat_get_allvars_assignment(const sat_solver_t *solver, bval_t *val) {
9249   uint32_t i, n;
9250 
9251   n = solver->nvars;
9252   for (i=0; i<n; i++) {
9253     val[i] = var_value(solver, i);
9254   }
9255 }
9256 
9257 
9258 /*
9259  * Copy all true literals in array a:
9260  * - a must have size >= solver->nvars.
9261  * return the number of literals added to a.
9262  */
nsat_get_true_literals(const sat_solver_t * solver,literal_t * a)9263 uint32_t nsat_get_true_literals(const sat_solver_t *solver, literal_t *a) {
9264   uint32_t n;
9265   literal_t l;
9266 
9267   n = 0;
9268   for (l = 0; l< solver->nliterals; l++) {
9269     if (lit_value(solver, l) == VAL_TRUE) {
9270       a[n] = l;
9271       n ++;
9272     }
9273   }
9274 
9275   return n;
9276 }
9277 
9278 
9279 
9280 /***********************
9281  *  EXPORT/DUMP STATE  *
9282  **********************/
9283 
9284 /*
9285  * For debugging: show the definition of variable x
9286  */
show_var_def(const sat_solver_t * solver,bvar_t x)9287 static void show_var_def(const sat_solver_t *solver, bvar_t x) {
9288   ttbl_t tt;
9289    uint32_t i;
9290 
9291   i = bvar_get_gate(&solver->descriptors, x);
9292   get_bgate(&solver->gates, i, &tt);
9293 
9294   fprintf(stderr, "c %"PRId32" = G(", x);
9295   for (i=0; i<tt.nvars; i++) {
9296     fprintf(stderr, "%"PRId32", ", tt.label[i]);
9297   }
9298   fprintf(stderr, "0x%02x)\n", tt.mask);
9299 }
9300 
9301 
show_tt(const ttbl_t * tt)9302 static void show_tt(const ttbl_t *tt) {
9303   uint32_t i;
9304   fprintf(stderr, "G(");
9305   for (i=0; i<tt->nvars; i++) {
9306     fprintf(stderr, "%"PRId32", ", tt->label[i]);
9307   }
9308   fprintf(stderr, "0x%02x)\n", tt->mask);
9309 }
9310 
9311 
9312 /*
9313  * Show the full substitution
9314  */
show_subst(const sat_solver_t * solver)9315 static void show_subst(const sat_solver_t *solver) {
9316   uint32_t i, n;
9317   literal_t l;
9318   literal_t l0;
9319   bvar_t x;
9320   int sign;
9321 
9322   n = solver->nvars;
9323   for (i=0; i<n; i++) {
9324     l = full_var_subst(solver, i);
9325     if (l != pos_lit(i)) {
9326       x = var_of(l);
9327       sign = is_pos(l) ? ' ' : '~';
9328       l0 = nsat_base_literal(solver, l);
9329       if (l0 != pos_lit(i)) {
9330 	if (l0 == true_literal) {
9331 	  fprintf(stderr, "c   subst(%"PRId32") = %c%"PRId32" --> true\n", i, sign, x);
9332 	} else if (l0 == false_literal) {
9333 	  fprintf(stderr, "c   subst(%"PRId32") = %c%"PRId32" --> false\n", i, sign, x);
9334 	} else {
9335 	  assert(l0 == l);
9336 	  fprintf(stderr, "c   subst(%"PRId32") = %c%"PRId32"\n", i, sign, x);
9337 	}
9338       }
9339     }
9340   }
9341 }
9342 
9343 
9344 
9345 
show_all_var_defs(const sat_solver_t * solver)9346 void show_all_var_defs(const sat_solver_t *solver) {
9347   uint32_t i, n;
9348 
9349   n = solver->descriptors.size;
9350   for (i=0; i<n; i++) {
9351     if (bvar_is_gate(&solver->descriptors, i)) {
9352       show_var_def(solver, i);
9353     }
9354   }
9355 }
9356 
9357 
9358 
tag2string(antecedent_tag_t tag)9359 static const char* tag2string(antecedent_tag_t tag) {
9360   switch (tag) {
9361   case ATAG_NONE: return "none";
9362   case ATAG_UNIT: return "unit";
9363   case ATAG_DECISION: return "decision";
9364   case ATAG_BINARY: return "binary";
9365   case ATAG_CLAUSE: return "clause";
9366   case ATAG_STACKED: return "stacked";
9367 
9368   case ATAG_PURE: return "pure";
9369   case ATAG_ELIM: return "elim";
9370   case ATAG_SUBST: return "subst";
9371   default: return "badtag";
9372   }
9373 }
9374 
show_assigned_vars(FILE * f,const sat_solver_t * solver)9375 static void show_assigned_vars(FILE *f, const sat_solver_t *solver) {
9376   uint32_t i, n;
9377 
9378   n = solver->nvars;
9379   for (i=0; i<n; i++) {
9380     switch (var_value(solver, i)) {
9381     case VAL_TRUE:
9382       fprintf(f, "%"PRIu32" := true, %s, lev = %"PRIu32"\n", i, tag2string(solver->ante_tag[i]), solver->level[i]);
9383       break;
9384 
9385     case VAL_FALSE:
9386       fprintf(f, "%"PRIu32" := false, %s, lev = %"PRIu32"\n", i, tag2string(solver->ante_tag[i]), solver->level[i]);
9387       break;
9388 
9389     default:
9390       break;
9391     }
9392   }
9393 }
9394 
show_clause(FILE * f,const clause_pool_t * pool,cidx_t idx)9395 static void show_clause(FILE *f, const clause_pool_t *pool, cidx_t idx) {
9396   uint32_t n, i;
9397   literal_t *lit;
9398 
9399   assert(good_clause_idx(pool, idx));
9400 
9401   n = clause_length(pool, idx);
9402   lit = clause_literals(pool, idx);
9403 
9404   fprintf(f, "%"PRIu32":", idx);
9405   for (i=0; i<n; i++) {
9406     fprintf(f, " %"PRIu32, lit[i]);
9407   }
9408   fprintf(f, "\n");
9409 }
9410 
show_all_clauses(FILE * f,const clause_pool_t * pool)9411 static void show_all_clauses(FILE *f, const clause_pool_t *pool) {
9412   uint32_t cidx;
9413 
9414   cidx = clause_pool_first_clause(pool);
9415   while (cidx < pool->size) {
9416     show_clause(f, pool, cidx);
9417     cidx = clause_pool_next_clause(pool, cidx);
9418   }
9419 }
9420 
show_watch_vector(FILE * f,const sat_solver_t * solver,literal_t l)9421 static void show_watch_vector(FILE *f, const sat_solver_t *solver, literal_t l) {
9422   watch_t *w;
9423   uint32_t i, n, k;
9424 
9425   assert(l < solver->nliterals);
9426   w = solver->watch[l];
9427   fprintf(f, "watch[%"PRIu32"]:", l);
9428   if (w == NULL) {
9429     fprintf(f, " null\n");
9430   } else {
9431     n = w->size;
9432     i = 0;
9433     if (n == 0) {
9434       fprintf(f, " empty\n");
9435     } else if (solver->preprocess) {
9436       // all elements in w->data are clause indices
9437       while (i<n) {
9438 	k = w->data[i];
9439 	assert(idx_is_clause(k));
9440 	fprintf(f, " cl(%"PRIu32")", k);
9441 	i ++;
9442       }
9443       fprintf(f, "\n");
9444     } else {
9445       while (i<n) {
9446         k = w->data[i];
9447         if (idx_is_literal(k)) {
9448           fprintf(f, " lit(%"PRIu32")", idx2lit(k));
9449           i ++;
9450         } else {
9451           fprintf(f, " cl(%"PRIu32")", k);
9452           i += 2;
9453         }
9454       }
9455       fprintf(f, "\n");
9456     }
9457   }
9458 }
9459 
show_all_watch_vectors(FILE * f,const sat_solver_t * solver)9460 static void show_all_watch_vectors(FILE *f, const sat_solver_t *solver) {
9461   uint32_t i;
9462 
9463   for (i=0; i<solver->nliterals; i++) {
9464     show_watch_vector(f, solver, i);
9465   }
9466 }
9467 
show_state(FILE * f,const sat_solver_t * solver)9468 void show_state(FILE *f, const sat_solver_t *solver) {
9469   fprintf(f, "nvars: %"PRIu32"\n", solver->nvars);
9470   fprintf(f, "nliterals: %"PRIu32"\n", solver->nliterals);
9471   fprintf(f, "num prob. clauses: %"PRIu32"\n", solver->pool.num_prob_clauses);
9472   fprintf(f, "num learned clauses: %"PRIu32"\n", solver->pool.num_learned_clauses);
9473   fprintf(f, "assignment\n");
9474   show_assigned_vars(f, solver);
9475   fprintf(f, "clauses\n");
9476   show_all_clauses(f, &solver->pool);
9477   fprintf(f, "watch vectors\n");
9478   show_all_watch_vectors(f, solver);
9479 }
9480 
9481 
9482 
9483 
9484 /****************************************
9485  *   CONSISTENCY CHECKS FOR DEBUGGING   *
9486  ***************************************/
9487 
9488 #if DEBUG
9489 
9490 /*
9491  * Check whether the clause pool counters are correct.
9492  */
good_counters(const clause_pool_t * pool)9493 static bool good_counters(const clause_pool_t *pool) {
9494   uint32_t prob_clauses, prob_lits, learned_clauses, learned_lits, i;
9495 
9496   prob_clauses = 0;
9497   prob_lits = 0;
9498   learned_clauses = 0;
9499   learned_lits = 0;
9500 
9501   i = clause_pool_first_clause(pool);
9502   while (i < pool->learned) {
9503     prob_clauses ++;
9504     prob_lits += clause_length(pool, i);
9505     i = clause_pool_next_clause(pool, i);
9506   }
9507   while (i < pool->size) {
9508     learned_clauses ++;
9509     learned_lits += clause_length(pool, i);
9510     i = clause_pool_next_clause(pool, i);
9511   }
9512 
9513   return
9514     prob_clauses == pool->num_prob_clauses &&
9515     prob_lits == pool->num_prob_literals &&
9516     learned_clauses == pool->num_learned_clauses &&
9517     learned_lits == pool->num_learned_literals;
9518 }
9519 
9520 /*
9521  * Check that the padding counter is correct
9522  */
good_padding_counter(const clause_pool_t * pool)9523 static bool good_padding_counter(const clause_pool_t *pool) {
9524   cidx_t cidx;
9525   uint32_t n, len;
9526 
9527   n = 0;
9528   cidx = 0;
9529   while (cidx < pool->size) {
9530     if (is_clause_start(pool, cidx)) {
9531       cidx += clause_full_length(pool, cidx);
9532     } else {
9533       len = padding_length(pool, cidx);
9534       cidx += len;
9535       n += len;
9536     }
9537   }
9538 
9539   return n == pool->padding;
9540 }
9541 
9542 
9543 /*
9544  * Check the counters, assuming pool->learned and pool->size are correct.
9545  */
check_clause_pool_counters(const clause_pool_t * pool)9546 static void check_clause_pool_counters(const clause_pool_t *pool) {
9547   if (!good_counters(pool)) {
9548     fprintf(stderr, "**** BUG: inconsistent pool counters ****\n");
9549     fflush(stderr);
9550   }
9551   if (!good_padding_counter(pool)) {
9552     fprintf(stderr, "**** BUG: inconsistent padding pool counter ****\n");
9553     fflush(stderr);
9554   }
9555 }
9556 
9557 
9558 /*
9559  * Check that all problem clauses have index < pool->learned
9560  * and that all learned clause have index >= pool->learned;
9561  * This assumes that pool->num_prob_clauses is correct.
9562  */
check_clause_pool_learned_index(const clause_pool_t * pool)9563 static void check_clause_pool_learned_index(const clause_pool_t *pool) {
9564   cidx_t cidx, end, next;
9565   uint32_t n, i;
9566 
9567   /*
9568    * Find the index of the last problem clause:
9569    *   cidx = 0 if there are no problem clauses
9570    *   cidx = pool->size if there are less problem clauses than expected
9571    */
9572   n = pool->num_prob_clauses;
9573   cidx = 0;
9574   end = 0;
9575   for (i=0; i<n; i++) {
9576     cidx = next_clause_index(pool, end);
9577     if (cidx >= pool->size) break;
9578     end = cidx + clause_full_length(pool, cidx);
9579   }
9580 
9581   if (cidx == pool->size) {
9582     fprintf(stderr, "**** BUG: expected %"PRIu32" problem clauses. Found %"PRIu32". ****\n",
9583             pool->num_prob_clauses, i + 1);
9584     fflush(stderr);
9585   } else {
9586     next = next_clause_index(pool, end);        // next clause after that (i.e., first learned clause or nothing)
9587     if (cidx >= pool->learned) {
9588       fprintf(stderr, "**** BUG: last problem clause starts at %"PRIu32". Learned index is %"PRIu32" ****\n",
9589               cidx, pool->learned);
9590       fflush(stderr);
9591     } else if (end > pool->learned) {
9592       fprintf(stderr, "**** BUG: last problem clause ends at %"PRIu32". Learned index is %"PRIu32" ****\n",
9593               end, pool->learned);
9594       fflush(stderr);
9595     } else if (next < pool->size && next < pool->learned) {
9596       fprintf(stderr, "**** BUG: first learned clause starts at %"PRIu32". Learned index is %"PRIu32" ****\n",
9597               next, pool->learned);
9598       fflush(stderr);
9599     }
9600   }
9601 }
9602 
9603 
9604 /*
9605  * HEAP INVARIANTS
9606  */
check_heap(const nvar_heap_t * heap)9607 static void check_heap(const nvar_heap_t *heap) {
9608   uint32_t i, j, n;
9609   int32_t k;
9610   bvar_t x, y;
9611 
9612   n = heap->heap_last;
9613   for (i=0; i<=n; i++) {
9614     x = heap->heap[i];
9615     if (heap->heap_index[x] != (int32_t) i) {
9616       fprintf(stderr, "*** BUG: heap[%"PRIu32"] = %"PRIu32" but heap_index[%"PRIu32"] = %"PRId32" ****\n",
9617               i, x, x, heap->heap_index[x]);
9618     }
9619     j = i>>1; // parent of i (or j=i=0 for the special marker)
9620     y = heap->heap[j];
9621     if (heap->rank[y] < heap->rank[x]) {
9622       fprintf(stderr, "*** BUG: bad heap ordering: activity[%"PRIu32"] < activity[%"PRIu32"] ****\n", j, i);
9623     }
9624   }
9625 
9626   n = heap->nvars;
9627   for (i=0; i<n; i++) {
9628     k= heap->heap_index[i];
9629     if (k >= 0 && heap->heap[k] != i) {
9630       fprintf(stderr, "*** BUG: heap_index[%"PRIu32"] = %"PRId32" but heap[%"PRId32"] = %"PRIu32" ****\n",
9631               i, k, k, heap->heap[k]);
9632     }
9633   }
9634 }
9635 
9636 
9637 /*
9638  * SORTING FOR CLAUSE DELETION
9639  * - a = array of clause idx
9640  * - n = number of elements in a
9641  * We check that all elements in a can be deleted and that a is sorted in increasing order.
9642  */
check_candidate_clauses_to_delete(const sat_solver_t * solver,const cidx_t * a,uint32_t n)9643 static void check_candidate_clauses_to_delete(const sat_solver_t *solver, const cidx_t *a, uint32_t n) {
9644   uint32_t i;
9645   cidx_t c1, c2;
9646   float a1, a2;
9647 
9648   for (i=0; i<n; i++) {
9649     c1 = a[i];
9650     if (clause_is_locked(solver, c1)) {
9651       fprintf(stderr, "**** BUG: locked clause (cidx = %"PRIu32") is candidate for deletion ****\n", c1);
9652       fflush(stderr);
9653     }
9654   }
9655 
9656   if (n <= 1) return;
9657 
9658   c1 = a[0];
9659   a1 = get_learned_clause_activity(&solver->pool, c1);
9660   for (i=1; i<n; i++) {
9661     c2 = a[i];
9662     a2 = get_learned_clause_activity(&solver->pool, c2);
9663     if (a1 > a2 || (a1 == a2 && c1 > c2)) {
9664       fprintf(stderr, "**** BUG: candidates for deletion not sorted (at position i = %"PRIu32")\n", i);
9665       fflush(stderr);
9666     }
9667     a1 = a2;
9668     c1 = c2;
9669   }
9670 }
9671 
9672 
9673 /*
9674  * WATCH VECTORS
9675  */
9676 
9677 /*
9678  * Check that cidx occurs in vector watch[l]
9679  */
clause_is_in_watch_vector(const sat_solver_t * solver,literal_t l,cidx_t cidx)9680 static bool clause_is_in_watch_vector(const sat_solver_t *solver, literal_t l, cidx_t cidx) {
9681   const watch_t *w;
9682   uint32_t i, n;
9683 
9684   w = solver->watch[l];
9685   if (w != NULL) {
9686     n = w->size;
9687     i = 0;
9688     while (i < n) {
9689       if (idx_is_literal(w->data[i])) {
9690         i ++;
9691       } else {
9692         if (w->data[i] == cidx) {
9693           return true;
9694         }
9695         i += 2;
9696       }
9697     }
9698   }
9699 
9700   return false;
9701 }
9702 
check_all_clauses_are_in_watch_vectors(const sat_solver_t * solver)9703 static void check_all_clauses_are_in_watch_vectors(const sat_solver_t *solver) {
9704   cidx_t cidx, end;
9705   literal_t l0, l1;
9706 
9707   cidx = clause_pool_first_clause(&solver->pool);
9708   end = solver->pool.size;
9709 
9710   while (cidx < end) {
9711     l0 = first_literal_of_clause(&solver->pool, cidx);
9712     l1 = second_literal_of_clause(&solver->pool, cidx);
9713     assert(l0 < solver->nliterals && l1 < solver->nliterals);
9714     if (!clause_is_in_watch_vector(solver, l0, cidx)) {
9715       fprintf(stderr, "*** BUG: missing clause index (%"PRIu32") in watch vector for literal %"PRIu32" ***\n",
9716               cidx, l0);
9717       fflush(stderr);
9718     }
9719     if (!clause_is_in_watch_vector(solver, l1, cidx)) {
9720       fprintf(stderr, "*** BUG: missing clause index (%"PRIu32") in watch vector for literal %"PRIu32" ***\n",
9721               cidx, l1);
9722       fflush(stderr);
9723     }
9724     cidx = clause_pool_next_clause(&solver->pool, cidx);
9725   }
9726 }
9727 
check_watch_vector_is_good(const sat_solver_t * solver,const watch_t * w,literal_t l)9728 static void check_watch_vector_is_good(const sat_solver_t *solver, const watch_t *w, literal_t l) {
9729   uint32_t i, n, k;
9730 
9731   assert(w != NULL && w == solver->watch[l]);
9732 
9733   n = w->size;
9734   i = 0;
9735   while (i < n) {
9736     k = w->data[i];
9737     if (idx_is_clause(k)) {
9738       if (first_literal_of_clause(&solver->pool, k) != l &&
9739           second_literal_of_clause(&solver->pool, k) != l) {
9740         fprintf(stderr, "*** BUG: clause %"PRIu32" is in watch vector for literal %"PRIu32"\n, but the literal is not first or second ***\n", k, l);
9741         fflush(stderr);
9742       }
9743       i += 2;
9744     } else {
9745       i ++;
9746     }
9747   }
9748 }
9749 
check_all_watch_vectors_are_good(const sat_solver_t * solver)9750 static void check_all_watch_vectors_are_good(const sat_solver_t *solver) {
9751   uint32_t i, n;
9752   watch_t *w;
9753 
9754   n = solver->nliterals;
9755   for (i=0; i<n; i++) {
9756     w = solver->watch[i];
9757     if (w != NULL) {
9758       check_watch_vector_is_good(solver, w, i);
9759     }
9760   }
9761 }
9762 
check_watch_vectors(const sat_solver_t * solver)9763 static void check_watch_vectors(const sat_solver_t *solver) {
9764   check_all_clauses_are_in_watch_vectors(solver);
9765   check_all_watch_vectors_are_good(solver);
9766 }
9767 
9768 
9769 /*
9770  * PROPAGATION
9771  */
9772 
9773 /*
9774  * Check whether clause cidx is true
9775  */
clause_is_true(const sat_solver_t * solver,cidx_t cidx)9776 static bool clause_is_true(const sat_solver_t *solver, cidx_t cidx) {
9777   uint32_t i, n;
9778   literal_t *lit;
9779 
9780   assert(good_clause_idx(&solver->pool, cidx));
9781 
9782   n = clause_length(&solver->pool, cidx);
9783   lit = clause_literals(&solver->pool, cidx);
9784   for (i=0; i<n; i++) {
9785     if (lit_is_true(solver, lit[i])) {
9786       return true;
9787     }
9788   }
9789 
9790   return false;
9791 }
9792 
9793 
9794 /*
9795  * Get the number of false literals in clause cidx
9796  */
num_false_literals_in_clause(const sat_solver_t * solver,cidx_t cidx)9797 static uint32_t num_false_literals_in_clause(const sat_solver_t *solver, cidx_t cidx) {
9798   uint32_t i, n, cnt;
9799   literal_t *lit;
9800 
9801   assert(good_clause_idx(&solver->pool, cidx));
9802 
9803   n = clause_length(&solver->pool, cidx);
9804   lit = clause_literals(&solver->pool, cidx);
9805   cnt = 0;
9806   for (i=0; i<n; i++) {
9807     if (lit_is_false(solver, lit[i])) {
9808       cnt ++;
9809     }
9810   }
9811 
9812   return cnt;
9813 }
9814 
9815 /*
9816  * Same thing for a stacked clause cidx
9817  */
num_false_literals_in_stacked_clause(const sat_solver_t * solver,cidx_t cidx)9818 static uint32_t num_false_literals_in_stacked_clause(const sat_solver_t *solver, cidx_t cidx) {
9819   uint32_t i, n, cnt;
9820   literal_t *lit;
9821 
9822   assert(good_stacked_clause_idx(&solver->stash, cidx));
9823 
9824   n = stacked_clause_length(&solver->stash, cidx);
9825   lit = stacked_clause_literals(&solver->stash, cidx);
9826   cnt = 0;
9827   for (i=0; i<n; i++) {
9828     if (lit_is_false(solver, lit[i])) {
9829       cnt ++;
9830     }
9831   }
9832 
9833   return cnt;
9834 }
9835 
9836 
9837 /*
9838  * Check that no propagation was missed (for the clause pool)
9839  * - this is called when there's no conflict reported
9840  */
check_pool_propagation(const sat_solver_t * solver)9841 static void check_pool_propagation(const sat_solver_t *solver) {
9842   cidx_t cidx;
9843   uint32_t f, n;
9844 
9845   for (cidx = clause_pool_first_clause(&solver->pool);
9846        cidx < solver->pool.size;
9847        cidx = clause_pool_next_clause(&solver->pool, cidx)) {
9848     if (! clause_is_true(solver, cidx)) {
9849       f = num_false_literals_in_clause(solver, cidx);
9850       n = clause_length(&solver->pool, cidx);
9851       if (f == n) {
9852         fprintf(stderr, "*** BUG: missed conflict. Clause %"PRIu32" is false ***\n", cidx);
9853         fflush(stderr);
9854       } else if (f == n -1) {
9855         fprintf(stderr, "*** BUG: missed propagation for clause %"PRIu32" ***\n", cidx);
9856         fflush(stderr);
9857       }
9858     }
9859   }
9860 }
9861 
9862 
9863 /*
9864  * Report missed conflicts and propagation for vector w
9865  * - l = literal corresponding to w (i.e., solver->watch[l] is w)
9866  * - l is false in the solver.
9867  */
check_missed_watch_prop(const sat_solver_t * solver,const watch_t * w,literal_t l)9868 static void check_missed_watch_prop(const sat_solver_t *solver, const watch_t *w, literal_t l) {
9869   uint32_t i, k, n;
9870   literal_t l1;
9871 
9872   assert(lit_is_false(solver, l) && solver->watch[l] == w);
9873 
9874   n = w->size;
9875   i = 0;
9876   while (i < n) {
9877     k = w->data[i];
9878     if (idx_is_literal(k)) {
9879       l1 = idx2lit(k);
9880       if (lit_is_false(solver, l1)) {
9881         fprintf(stderr, "*** BUG: missed binary conflict for clause %"PRIu32" %"PRIu32" ***\n", l, l1);
9882         fflush(stderr);
9883       } else if (lit_is_unassigned(solver, l1)) {
9884         fprintf(stderr, "*** BUG: missed binary propagation for clause %"PRIu32" %"PRIu32" ***\n", l, l1);
9885         fflush(stderr);
9886       }
9887       i ++;
9888     } else {
9889       i += 2;
9890     }
9891   }
9892 }
9893 
9894 
9895 /*
9896  * Check that no propagation was missed (for the binary clauses)
9897  * - this is called when no conflict was reported
9898  */
check_binary_propagation(const sat_solver_t * solver)9899 static void check_binary_propagation(const sat_solver_t *solver) {
9900   uint32_t i, n;
9901   const watch_t *w;
9902 
9903   n = solver->nliterals;
9904   for (i=0; i<n; i++) {
9905     if (lit_is_false(solver, i)) {
9906       w = solver->watch[i];
9907       if (w != NULL) {
9908         check_missed_watch_prop(solver, w, i);
9909       }
9910     }
9911   }
9912 }
9913 
9914 
9915 /*
9916  * Check that all literals implied by a clause cidx are in first
9917  * position in that clause.
9918  */
check_clause_antecedents(const sat_solver_t * solver)9919 static void check_clause_antecedents(const sat_solver_t *solver) {
9920   uint32_t i;
9921   literal_t l;
9922   cidx_t cidx;
9923 
9924   for (i=0; i<solver->stack.top; i++) {
9925     l = solver->stack.lit[i];
9926     if (solver->ante_tag[var_of(l)] == ATAG_CLAUSE) {
9927       cidx = solver->ante_data[var_of(l)];
9928       if (first_literal_of_clause(&solver->pool, cidx) != l) {
9929         fprintf(stderr, "*** BUG: implied literal %"PRIu32" is not first in clause %"PRIu32" ****\n", l, cidx);
9930         fflush(stderr);
9931       }
9932     }
9933   }
9934 }
9935 
9936 
9937 /*
9938  * Check that all propagations are sound:
9939  * - in a binary propagation {l, l1} then l1 must be false
9940  * - in a clause propagation {l, l1 .... l_k} then l1 ... l_k must all be false
9941  */
check_sound_propagation(const sat_solver_t * solver)9942 static void check_sound_propagation(const sat_solver_t *solver) {
9943   uint32_t i, n, f;
9944   cidx_t cidx;
9945   literal_t l, l1;
9946 
9947   for (i=0; i<solver->stack.top; i++) {
9948     l = solver->stack.lit[i];
9949     assert(lit_is_true(solver, l));
9950     switch (solver->ante_tag[var_of(l)]) {
9951     case ATAG_BINARY:
9952       l1 = solver->ante_data[var_of(l)];
9953       if (! lit_is_false(solver, l1)) {
9954         fprintf(stderr, "*** BUG: unsound propagation for binary clause %"PRIu32" %"PRIu32" ***\n", l, l1);
9955         fflush(stderr);
9956       }
9957       break;
9958 
9959     case ATAG_CLAUSE:
9960       cidx = solver->ante_data[var_of(l)];
9961       f = num_false_literals_in_clause(solver, cidx);
9962       n = clause_length(&solver->pool, cidx);
9963       if (f != n - 1) {
9964         fprintf(stderr, "*** BUG: unsound propagation. Clause %"PRIu32" antecedent of literal %"PRIu32" ***\n",
9965                 cidx, l);
9966         fflush(stderr);
9967       }
9968       break;
9969 
9970     default:
9971       break;
9972     }
9973   }
9974 }
9975 
9976 
9977 /*
9978  * Check the stacked clauses:
9979  * - if an assigned literal l has stack clause cidx as antecedent then
9980  *   l must be first in the clause
9981  */
check_stacked_clause_antecedents(const sat_solver_t * solver)9982 static void check_stacked_clause_antecedents(const sat_solver_t *solver) {
9983   uint32_t i;
9984   literal_t l;
9985   cidx_t cidx;
9986 
9987   for (i=0; i<solver->stack.top; i++) {
9988     l = solver->stack.lit[i];
9989     if (solver->ante_tag[var_of(l)] == ATAG_STACKED) {
9990       cidx = solver->ante_data[var_of(l)];
9991       if (first_literal_of_stacked_clause(&solver->stash, cidx) != l) {
9992         fprintf(stderr, "*** BUG: implied literal %"PRIu32" is not first in stacked clause %"PRIu32" ****\n", l, cidx);
9993         fflush(stderr);
9994       }
9995     }
9996   }
9997 }
9998 
9999 /*
10000  * Check the stacked clauses (continued)
10001  * - for every stacked clause cidx:
10002  *   its first literal must be assigned and true
10003  * - all the other literals must be false
10004  */
check_stacked_clauses(const sat_solver_t * solver)10005 static void check_stacked_clauses(const sat_solver_t *solver) {
10006   cidx_t cidx;
10007   uint32_t f, n;
10008   literal_t l;
10009 
10010   for (cidx = 0;
10011        cidx < solver->stash.top;
10012        cidx = next_stacked_clause(&solver->stash, cidx)) {
10013     l = first_literal_of_stacked_clause(&solver->stash, cidx);
10014     if (solver->ante_tag[var_of(l)] != ATAG_STACKED ||
10015         solver->ante_data[var_of(l)] != cidx) {
10016       fprintf(stderr, "*** BUG: bad antecedent for literal %"PRIu32" (first in stacked clause %"PRIu32") ****\n", l, cidx);
10017       fflush(stderr);
10018     }
10019     if (!lit_is_true(solver, l)) {
10020       fprintf(stderr, "*** BUG: literal %"PRIu32" (first in stacked clause %"PRIu32") is not true ****\n", l, cidx);
10021       fflush(stderr);
10022     }
10023     n = stacked_clause_length(&solver->stash, cidx);
10024     f = num_false_literals_in_stacked_clause(solver, cidx);
10025     if (f != n-1) {
10026       fprintf(stderr, "*** BUG: stacked clause %"PRIu32" has %"PRIu32" false literals (out of %"PRIu32") ***\n", cidx, f, n);
10027       fflush(stderr);
10028     }
10029   }
10030 }
10031 
10032 /*
10033  * Full check
10034  */
check_propagation(const sat_solver_t * solver)10035 static void check_propagation(const sat_solver_t *solver) {
10036   check_binary_propagation(solver);
10037   check_pool_propagation(solver);
10038   check_clause_antecedents(solver);
10039   check_sound_propagation(solver);
10040   check_stacked_clause_antecedents(solver);
10041   check_stacked_clauses(solver);
10042 }
10043 
10044 
10045 /*******************************
10046  *  MARKS AND LEARNED CLAUSES  *
10047  ******************************/
10048 
10049 /*
10050  * Check that all literals in solver->buffer are marked
10051  */
check_buffer_marks(const sat_solver_t * solver)10052 static void check_buffer_marks(const sat_solver_t *solver) {
10053   uint32_t n, i;
10054   literal_t l;
10055 
10056   n = solver->buffer.size;
10057   for (i=0; i<n; i++) {
10058     l = solver->buffer.data[i];
10059     if (! variable_is_marked(solver, var_of(l))) {
10060       fprintf(stderr, "*** BUG: literal %"PRIu32" in the learned clause is not marked ***\n", l);
10061       fflush(stderr);
10062     }
10063   }
10064 }
10065 
10066 /*
10067  * Count the number of marked variables
10068  */
num_marked_variables(const sat_solver_t * solver)10069 static uint32_t num_marked_variables(const sat_solver_t *solver) {
10070   uint32_t n, i, c;
10071 
10072   c = 0;
10073   n = solver->nvars;
10074   for (i=0; i<n; i++) {
10075     if (variable_is_marked(solver, i)) {
10076       c ++;
10077     }
10078   }
10079 
10080   return c;
10081 }
10082 
10083 
10084 /*
10085  * After construction of the learned clause (before it's simplified):
10086  * - all literals in the clause must be marked.
10087  * - no other literals should be marked.
10088  */
check_marks(const sat_solver_t * solver)10089 static void check_marks(const sat_solver_t *solver) {
10090   uint32_t n;
10091 
10092   n = num_marked_variables(solver);
10093   if (n != solver->buffer.size) {
10094     fprintf(stderr, "*** BUG: expected %"PRIu32" marked variables; found %"PRIu32" ***\n",
10095             solver->buffer.size, n);
10096   } else {
10097     check_buffer_marks(solver);
10098   }
10099 }
10100 
10101 
10102 /*
10103  * When we've simplified the learned clause: no variable should be marked
10104  */
check_all_unmarked(const sat_solver_t * solver)10105 static void check_all_unmarked(const sat_solver_t *solver) {
10106   uint32_t n;
10107 
10108   n = num_marked_variables(solver);
10109   if (n > 0) {
10110     fprintf(stderr, "*** BUG: found %"PRIu32" marked variables: should be 0 ***\n", n);
10111     fflush(stderr);
10112   }
10113 }
10114 
10115 
10116 /**********************
10117  *  ELIMINATION HEAP  *
10118  *********************/
10119 
check_elim_heap(const sat_solver_t * solver)10120 static void check_elim_heap(const sat_solver_t *solver) {
10121   const elim_heap_t *heap;
10122   uint32_t i, n;
10123   bvar_t x;
10124 
10125   heap = &solver->elim;
10126   n = heap->size;
10127   for (i=2; i<n; i++) {
10128     if (elim_lt(solver, heap->data[i], heap->data[i>>1])) {
10129       fprintf(stderr, "*** BUG: invalid elimination heap: at index %"PRIu32" ***\n", i);
10130       fflush(stderr);
10131     }
10132   }
10133 
10134   for (i=0; i<n; i++) {
10135     x = heap->data[i];
10136     if (heap->elim_idx[x] != i) {
10137       fprintf(stderr, "*** BUG: invalid heap index: data[%"PRIu32"] = %"PRIu32", but elim_idx[%"PRIu32"] /= %"PRIu32" ***\n", i, x, x, i);
10138       fflush(stderr);
10139     }
10140   }
10141 
10142   for (x=0; x<solver->nvars; x++) {
10143     if (heap->elim_idx[x] >= 0) {
10144       i = heap->elim_idx[x];
10145       if (i >= heap->size) {
10146         fprintf(stderr, "*** BUG: bad elim_idx for variable %"PRIu32": index = %"PRIu32", heap size = %"PRIu32"\n", x, i, heap->size);
10147         fflush(stderr);
10148       }
10149       if (heap->data[i] != x) {
10150         fprintf(stderr, "*** BUG: invalid data: elim_idx[%"PRIu32"] = %"PRIu32", but data[%"PRIu32"] /= %"PRIu32" ***\n", x, i, i, x);
10151         fflush(stderr);
10152       }
10153     }
10154   }
10155 }
10156 
10157 #endif
10158