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