ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
check.c
Go to the documentation of this file.
1#include "global.h"
2
3#ifndef KISSAT_NDEBUG
4
5#include "check.h"
6#include "error.h"
7#include "internal.h"
8#include "literal.h"
9#include "logging.h"
10#include "print.h"
11
12#include <limits.h>
13#include <stdio.h>
14#include <string.h>
15
16#undef LOGPREFIX
17#define LOGPREFIX "CHECK"
18
20
21void kissat_check_satisfying_assignment (kissat *solver) {
22 LOG ("checking satisfying assignment");
23 const int *const begin = BEGIN_STACK (solver->original);
24 const int *const end = END_STACK (solver->original);
25#ifdef LOGGING
26 size_t count = 0;
27#endif
28 for (const int *p = begin, *q; p != end; p = q + 1) {
29 bool satisfied = false;
30 int lit, other;
31 for (q = p; (lit = *q); q++)
32 if (!satisfied && kissat_value (solver, lit) == lit)
33 satisfied = true;
34#ifdef LOGGING
35 count++;
36#endif
37 if (satisfied)
38 continue;
39 for (q = p; (lit = *q); q++)
40 for (const int *r = q + 1; (other = *r); r++)
41 if (lit == -other)
42 satisfied = true;
43 if (satisfied)
44 continue;
46 fputs ("unsatisfied clause:\n", stderr);
47 for (q = p; (lit = *q); q++)
48 fprintf (stderr, "%d ", lit);
49 fputs ("0\n", stderr);
50 fflush (stderr);
51 kissat_abort ();
52 }
53 LOG ("assignment satisfies all %zu original clauses", count);
54}
55
57
58#include "allocate.h"
59#include "inline.h"
60#include "sort.h"
61
63
64typedef struct hash hash;
65typedef struct bucket bucket;
66
67// clang-format off
68
69typedef STACK (bucket*) buckets_;
70
71// clang-format on
72
73struct bucket {
74 bucket *next;
75 unsigned size;
76 unsigned hash;
77 unsigned lits[];
78};
79
80struct checker {
81 bool inconsistent;
82
83 unsigned vars;
84 unsigned size;
85
86 unsigned buckets;
87 unsigned hashed;
88
89 bucket **table;
90
91 buckets_ *watches;
92 bool *marks;
93 bool *large;
94 bool *used;
95 signed char *values;
96
97 bool marked;
98 unsigneds imported;
99
100 unsigneds trail;
101 unsigned propagated;
102
103 unsigned nonces[32];
104
105 uint64_t added;
106 uint64_t blocked;
107 uint64_t checked;
108 uint64_t collisions;
109 uint64_t decisions;
110 uint64_t propagations;
111 uint64_t pure;
112 uint64_t removed;
113 uint64_t satisfied;
114 uint64_t searches;
115 uint64_t unchecked;
116};
117
118#define LOGIMPORTED3(...) \
119 LOGUNSIGNEDS3 (SIZE_STACK (checker->imported), \
120 BEGIN_STACK (checker->imported), __VA_ARGS__)
121
122#define LOGLINE3(...) \
123 LOGUNSIGNEDS3 (bucket->size, bucket->lits, __VA_ARGS__)
124
125#define MAX_NONCES (sizeof checker->nonces / sizeof *checker->nonces)
126
127static inline bool less_unsigned (unsigned a, unsigned b) { return a < b; }
128
129static void sort_line (kissat *solver, checker *checker) {
130 SORT_STACK (unsigned, checker->imported, less_unsigned);
131 LOGIMPORTED3 ("sorted checker");
132}
133
134static unsigned hash_line (checker *checker) {
135 unsigned res = 0, pos = 0;
136 for (all_stack (unsigned, lit, checker->imported)) {
137 res += checker->nonces[pos++] * lit;
138 if (pos == MAX_NONCES)
139 pos = 0;
140 }
141 return res;
142}
143
144static size_t bytes_line (unsigned size) {
145 return sizeof (bucket) + size * sizeof (unsigned);
146}
147
148static void init_nonces (kissat *solver, checker *checker) {
149 generator random = 42;
150 for (unsigned i = 0; i < MAX_NONCES; i++)
151 checker->nonces[i] = 1 | kissat_next_random32 (&random);
152 LOG3 ("initialized %zu checker nonces", MAX_NONCES);
153#ifndef LOGGING
154 (void) solver;
155#endif
156}
157
158void kissat_init_checker (kissat *solver) {
159 LOG ("initializing internal proof checker");
160 checker *checker = (struct checker*)kissat_calloc (solver, 1, sizeof (struct checker));
161 solver->checker = checker;
162 init_nonces (solver, checker);
163}
164
165static void release_hash (kissat *solver, checker *checker) {
166 for (unsigned h = 0; h < checker->hashed; h++) {
167 for (bucket *bucket = checker->table[h], *next; bucket; bucket = next) {
168 next = bucket->next;
169 kissat_free (solver, bucket, bytes_line (bucket->size));
170 }
171 }
172 kissat_dealloc (solver, checker->table, checker->hashed,
173 sizeof (bucket *));
174}
175
176static void release_watches (kissat *solver, checker *checker) {
177 const unsigned lits = 2 * checker->vars;
178 for (unsigned i = 0; i < lits; i++)
179 RELEASE_STACK (checker->watches[i]);
180 kissat_dealloc (solver, checker->watches, 2 * checker->size,
181 sizeof (buckets_));
182}
183
184void kissat_release_checker (kissat *solver) {
185 LOG ("releasing internal proof checker");
186 checker *checker = solver->checker;
187 release_hash (solver, checker);
188 RELEASE_STACK (checker->imported);
189 RELEASE_STACK (checker->trail);
190 kissat_free (solver, checker->marks, 2 * checker->size * sizeof (bool));
191 kissat_free (solver, checker->used, 2 * checker->size * sizeof (bool));
192 kissat_free (solver, checker->large, 2 * checker->size * sizeof (bool));
193 kissat_free (solver, checker->values, 2 * checker->size);
194 release_watches (solver, checker);
195 kissat_free (solver, checker, sizeof (struct checker));
196}
197
198#ifndef KISSAT_QUIET
199
201
202#include <inttypes.h>
203
205
206#define PERCENT_ADDED(NAME) kissat_percent (checker->NAME, checker->added)
207#define PERCENT_CHECKED(NAME) \
208 kissat_percent (checker->NAME, checker->checked)
209
210void kissat_print_checker_statistics (kissat *solver, bool verbose) {
211 checker *checker = solver->checker;
212 PRINT_STAT ("checker_added", checker->added, 100, "%", "");
213 if (verbose)
214 PRINT_STAT ("checker_blocked", checker->blocked,
215 PERCENT_CHECKED (blocked), "%", "checked");
216 PRINT_STAT ("checker_checked", checker->checked, PERCENT_ADDED (checked),
217 "%", "added");
218 if (verbose) {
219 PRINT_STAT ("checker_collisions", checker->collisions,
220 kissat_percent (checker->collisions, checker->searches),
221 "%", "per search");
222 PRINT_STAT ("checker_decisions", checker->decisions,
223 kissat_average (checker->decisions, checker->checked), "",
224 "per check");
225 PRINT_STAT ("checker_propagations", checker->propagations,
226 kissat_average (checker->propagations, checker->checked),
227 "", "per check");
228 PRINT_STAT ("checker_pure", checker->pure, PERCENT_CHECKED (pure), "%",
229 "checked");
230 }
231 PRINT_STAT ("checker_removed", checker->removed, PERCENT_ADDED (removed),
232 "%", "added");
233 if (verbose) {
234 PRINT_STAT ("checker_satisfied", checker->satisfied,
235 PERCENT_CHECKED (satisfied), "%", "checked");
236 PRINT_STAT ("checker_unchecked", checker->unchecked,
237 PERCENT_ADDED (unchecked), "%", "added");
238 }
239}
240
241#endif
242
243#define MAX_VARS (1u << 29)
244#define MAX_SIZE (1u << 30)
245
246static unsigned reduce_hash (unsigned hash, unsigned mod) {
247 if (mod < 2)
248 return 0;
249 KISSAT_assert (mod);
250 unsigned res = hash;
251 for (unsigned shift = 16, mask = 0xffff; res >= mod;
252 mask >>= (shift >>= 1))
253 res = (res >> shift) & mask;
254 KISSAT_assert (res < mod);
255 return res;
256}
257
258static void resize_hash (kissat *solver, checker *checker) {
259 const unsigned old_hashed = checker->hashed;
260 KISSAT_assert (old_hashed < MAX_SIZE);
261 const unsigned new_hashed = old_hashed ? 2 * old_hashed : 1;
262 bucket **table = (bucket**) kissat_calloc (solver, new_hashed, sizeof (bucket *));
263 bucket **old_table = checker->table;
264 for (unsigned i = 0; i < old_hashed; i++) {
265 for (bucket *bucket = old_table[i], *next; bucket; bucket = next) {
266 next = bucket->next;
267 const unsigned reduced = reduce_hash (bucket->hash, new_hashed);
268 bucket->next = table[reduced];
269 table[reduced] = bucket;
270 }
271 }
272 kissat_dealloc (solver, checker->table, old_hashed, sizeof (bucket *));
273 checker->hashed = new_hashed;
274 checker->table = table;
275}
276
277static bucket *new_line (kissat *solver, checker *checker, unsigned size,
278 unsigned hash) {
279 bucket *res = (bucket*)kissat_malloc (solver, bytes_line (size));
280 res->next = 0;
281 res->size = size;
282 res->hash = hash;
283 memcpy (res->lits, BEGIN_STACK (checker->imported),
284 size * sizeof *res->lits);
285 return res;
286}
287
288#define CHECKER_LITS (2 * (checker)->vars)
289#define VALID_CHECKER_LIT(LIT) ((LIT) < CHECKER_LITS)
290
291static bucket decision_line;
292static bucket unit_line;
293
294static void checker_assign (kissat *solver, checker *checker, unsigned lit,
295 bucket *bucket) {
296#ifdef LOGGING
297 if (bucket == &decision_line)
298 LOG3 ("checker assign %u (decision)", lit);
299 else if (bucket == &unit_line)
300 LOG3 ("checker assign %u (unit)", lit);
301 else
302 LOGLINE3 ("checker assign %u reason", lit);
303#else
304 (void) bucket;
305#endif
306 KISSAT_assert (VALID_CHECKER_LIT (lit));
307 const unsigned not_lit = lit ^ 1;
308 signed char *values = checker->values;
309 KISSAT_assert (!values[lit]);
310 KISSAT_assert (!values[not_lit]);
311 values[lit] = 1;
312 values[not_lit] = -1;
313 PUSH_STACK (checker->trail, lit);
314}
315
316static buckets_ *checker_watches (checker *checker, unsigned lit) {
317 KISSAT_assert (VALID_CHECKER_LIT (lit));
318 return checker->watches + lit;
319}
320
321static void watch_checker_literal (kissat *solver, checker *checker,
322 bucket *bucket, unsigned lit) {
323 LOGLINE3 ("checker watches %u in", lit);
324 buckets_ *buckets = checker_watches (checker, lit);
325 PUSH_STACK (*buckets, bucket);
326}
327
328static void unwatch_checker_literal (kissat *solver, checker *checker,
329 bucket *bucket, unsigned lit) {
330 LOGLINE3 ("checker unwatches %u in", lit);
331 buckets_ *buckets = checker_watches (checker, lit);
332 REMOVE_STACK (struct bucket *, *buckets, bucket);
333#ifndef LOGGING
334 (void) solver;
335#endif
336}
337
338static void unwatch_line (kissat *solver, checker *checker,
339 bucket *bucket) {
340 KISSAT_assert (bucket->size > 1);
341 const unsigned *const lits = bucket->lits;
342 unwatch_checker_literal (solver, checker, bucket, lits[0]);
343 unwatch_checker_literal (solver, checker, bucket, lits[1]);
344}
345
346static bool satisfied_or_trivial_imported (kissat *solver,
347 checker *checker) {
348 const unsigned *const lits = BEGIN_STACK (checker->imported);
349 const unsigned *const end_of_lits = END_STACK (checker->imported);
350 const signed char *values = checker->values;
351 bool *marks = checker->marks;
352 unsigned const *p;
353 bool res = false;
354 for (p = lits; !res && p != end_of_lits; p++) {
355 const unsigned lit = *p;
356 if (marks[lit])
357 continue;
358 marks[lit] = true;
359 const unsigned not_lit = lit ^ 1;
360 if (marks[not_lit]) {
361 LOGIMPORTED3 ("trivial by %u and %u imported checker", not_lit, lit);
362 res = true;
363 } else if (values[lit] > 0) {
364 LOGIMPORTED3 ("satisfied by %u imported checker", lit);
365 res = true;
366 }
367 }
368 for (const unsigned *q = lits; q != p; q++)
369 marks[*q] = 0;
370#ifndef LOGGING
371 (void) solver;
372#endif
373 return res;
374}
375
376static void mark_line (checker *checker) {
377 bool *marks = checker->marks;
378 for (all_stack (unsigned, lit, checker->imported))
379 marks[lit] = 1;
380 checker->marked = true;
381}
382
383static void unmark_line (checker *checker) {
384 bool *marks = checker->marks;
385 for (all_stack (unsigned, lit, checker->imported))
386 marks[lit] = 0;
387 checker->marked = false;
388}
389
390static bool simplify_imported (kissat *solver, checker *checker) {
391 if (checker->inconsistent) {
392 LOG3 ("skipping addition since checker already inconsistent");
393 return true;
394 }
395 unsigned non_false = 0;
396#ifdef LOGGING
397 unsigned num_false = 0;
398#endif
399 const unsigned *const end_of_lits = END_STACK (checker->imported);
400 unsigned *lits = BEGIN_STACK (checker->imported);
401 const signed char *values = checker->values;
402 bool *marks = checker->marks;
403 bool res = false;
404 unsigned *p;
405 for (p = lits; !res && p != end_of_lits; p++) {
406 const unsigned lit = *p;
407 if (marks[lit])
408 continue;
409 marks[lit] = true;
410 const unsigned not_lit = lit ^ 1;
411 if (marks[not_lit]) {
412 LOG3 ("simplified checker clause trivial (contains %u and %u)",
413 not_lit, lit);
414 res = true;
415 } else {
416 signed char lit_value = values[lit];
417 if (lit_value < 0) {
418#ifdef LOGGING
419 num_false++;
420#endif
421 } else if (lit_value > 0) {
422 LOG3 ("simplified checker clause satisfied by %u", lit);
423 res = true;
424 } else {
425 if (!non_false)
426 SWAP (unsigned, *p, lits[0]);
427 else if (non_false == 1)
428 SWAP (unsigned, *p, lits[1]);
429 non_false++;
430 }
431 }
432 }
433 for (const unsigned *q = lits; q != p; q++)
434 marks[*q] = 0;
435 if (!res) {
436 if (!non_false) {
437 LOG3 ("simplified checker clause inconsistent");
438 checker->inconsistent = true;
439 res = true;
440 } else if (non_false == 1) {
441 LOG3 ("simplified checker clause unit");
442 checker_assign (solver, checker, lits[0], &unit_line);
443 res = true;
444 }
445 }
446 if (!res) {
447 LOG3 ("non-trivial and non-satisfied imported checker clause "
448 "has %u false and %u non-false literals",
449 num_false, non_false);
450 LOGIMPORTED3 ("simplified checker");
451 }
452 return res;
453}
454
455static void use_literal (kissat *solver, checker *checker, unsigned lit) {
456 if (checker->used[lit])
457 return;
458 checker->used[lit] = true;
459#ifdef LOGGING
460 LOG3 ("used checker literal %u", lit);
461#else
462 (void) solver;
463#endif
464}
465
466static void large_literal (kissat *solver, checker *checker, unsigned lit) {
467 if (checker->large[lit])
468 return;
469 checker->large[lit] = true;
470#ifdef LOGGING
471 LOG3 ("large checker literal %u", lit);
472#else
473 (void) solver;
474#endif
475}
476
477static void use_line (kissat *solver, checker *checker) {
478 bool large = (SIZE_STACK (checker->imported) > 2);
479 for (all_stack (unsigned, lit, checker->imported)) {
480 use_literal (solver, checker, lit);
481 if (large)
482 large_literal (solver, checker, lit);
483 }
484}
485
486static void insert_imported (kissat *solver, checker *checker,
487 unsigned hash) {
488 size_t size = SIZE_STACK (checker->imported);
489 KISSAT_assert (size <= UINT_MAX);
490 if (checker->buckets == checker->hashed)
491 resize_hash (solver, checker);
492 bucket *bucket = new_line (solver, checker, size, hash);
493 const unsigned reduced = reduce_hash (hash, checker->hashed);
494 struct bucket **p = checker->table + reduced;
495 bucket->next = *p;
496 *p = bucket;
497 LOGLINE3 ("inserted checker");
498 const unsigned *const lits = BEGIN_STACK (checker->imported);
499 const signed char *values = checker->values;
500 KISSAT_assert (!values[lits[0]]);
501 KISSAT_assert (!values[lits[1]]);
502 watch_checker_literal (solver, checker, bucket, lits[0]);
503 watch_checker_literal (solver, checker, bucket, lits[1]);
504 checker->buckets++;
505 checker->added++;
506}
507
508static void insert_imported_if_not_simplified (kissat *solver,
509 checker *checker) {
510 sort_line (solver, checker);
511 const unsigned hash = hash_line (checker);
512 if (!simplify_imported (solver, checker)) {
513 insert_imported (solver, checker, hash);
514 use_line (solver, checker);
515 }
516}
517
518static bool match_line (checker *checker, unsigned size, unsigned hash,
519 bucket *bucket) {
520 if (bucket->size != size)
521 return false;
522 if (bucket->hash != hash)
523 return false;
524 if (!checker->marked)
525 mark_line (checker);
526 const unsigned *const lits = bucket->lits;
527 const unsigned *const end_of_lits = lits + bucket->size;
528 const bool *const marks = checker->marks;
529 for (const unsigned *p = lits; p != end_of_lits; p++)
530 if (!marks[*p])
531 return false;
532 return true;
533}
534
535static void resize_checker (kissat *solver, checker *checker,
536 unsigned new_vars) {
537 const unsigned vars = checker->vars;
538 const unsigned size = checker->size;
539 if (new_vars > size) {
540 KISSAT_assert (new_vars <= MAX_SIZE);
541 unsigned new_size = size ? 2 * size : 1;
542 while (new_size < new_vars)
543 new_size *= 2;
544 KISSAT_assert (new_size <= MAX_SIZE);
545 LOG3 ("resizing checker form %u to %u", size, new_size);
546 const unsigned size2 = 2 * size;
547 const unsigned new_size2 = 2 * new_size;
548 checker->marks = (bool*)kissat_realloc (solver, checker->marks, size2,
549 new_size2 * sizeof (bool));
550 checker->used = (bool*)kissat_realloc (solver, checker->used, size2,
551 new_size2 * sizeof (bool));
552 checker->large = (bool*)kissat_realloc (solver, checker->large, size2,
553 new_size2 * sizeof (bool));
554 checker->values =
555 (signed char *)kissat_realloc (solver, checker->values, size2, new_size2);
556 checker->watches = (buckets_*)kissat_realloc (
557 solver, checker->watches, size2 * sizeof *checker->watches,
558 new_size2 * sizeof *checker->watches);
559 checker->size = new_size;
560 }
561 const unsigned delta = new_vars - vars;
562 if (delta == 1)
563 LOG3 ("initializing one checker variable %u", vars);
564 else
565 LOG3 ("initializing %u checker variables from %u to %u", delta, vars,
566 new_vars - 1);
567 const unsigned vars2 = 2 * vars;
568 const unsigned new_vars2 = 2 * new_vars;
569 const unsigned delta2 = 2 * delta;
570 KISSAT_assert (delta2 == new_vars2 - vars2);
571 memset (checker->watches + vars2, 0, delta2 * sizeof *checker->watches);
572 memset (checker->marks + vars2, 0, delta2);
573 memset (checker->used + vars2, 0, delta2);
574 memset (checker->large + vars2, 0, delta2);
575 memset (checker->values + vars2, 0, delta2);
576 checker->vars = new_vars;
577}
578
579static inline unsigned
580import_external_checker (kissat *solver, checker *checker, int elit) {
581 KISSAT_assert (elit);
582 const unsigned var = ABS (elit) - 1;
583 if (var >= checker->vars)
584 resize_checker (solver, checker, var + 1);
585 KISSAT_assert (var < checker->vars);
586 return 2 * var + (elit < 0);
587}
588
589static inline unsigned
590import_internal_checker (kissat *solver, checker *checker, unsigned ilit) {
591 const int elit = kissat_export_literal (solver, ilit);
592 return import_external_checker (solver, checker, elit);
593}
594
595static inline int export_checker (checker *checker, unsigned ilit) {
596 KISSAT_assert (ilit <= 2 * checker->vars);
597 return (1 + (ilit >> 1)) * ((ilit & 1) ? -1 : 1);
598}
599
600static bucket *find_line (kissat *solver, checker *checker, size_t size,
601 bool remove) {
602 if (!checker->hashed)
603 return 0;
604 sort_line (solver, checker);
605 checker->searches++;
606 const unsigned hash = hash_line (checker);
607 const unsigned reduced = reduce_hash (hash, checker->hashed);
608 struct bucket **p, *bucket;
609 for (p = checker->table + reduced;
610 (bucket = *p) && !match_line (checker, size, hash, bucket);
611 p = &bucket->next)
612 checker->collisions++;
613 if (checker->marked)
614 unmark_line (checker);
615 if (bucket && remove)
616 *p = bucket->next;
617 return bucket;
618}
619
620static void remove_line (kissat *solver, checker *checker, size_t size) {
621 bucket *bucket = find_line (solver, checker, size, true);
622 if (!bucket) {
624 fputs ("trying to remove non-existing clause:\n", stderr);
625 for (all_stack (unsigned, lit, checker->imported))
626 fprintf (stderr, "%d ", export_checker (checker, lit));
627 fputs ("0\n", stderr);
628 fflush (stderr);
629 kissat_abort ();
630 }
631 unwatch_line (solver, checker, bucket);
632 LOGLINE3 ("removed checker");
633 kissat_free (solver, bucket, bytes_line (size));
634 KISSAT_assert (checker->buckets > 0);
635 checker->buckets--;
636 checker->removed++;
637}
638
639static void import_external_literals (kissat *solver, checker *checker,
640 size_t size, const int *elits) {
641 if (size > UINT_MAX)
642 kissat_fatal ("can not check handle original clause of size %zu", size);
643 CLEAR_STACK (checker->imported);
644 for (size_t i = 0; i < size; i++) {
645 const unsigned lit =
646 import_external_checker (solver, checker, elits[i]);
647 PUSH_STACK (checker->imported, lit);
648 }
649 LOGIMPORTED3 ("checker imported external");
650}
651
652static void import_internal_literals (kissat *solver, checker *checker,
653 size_t size, const unsigned *ilits) {
654 KISSAT_assert (size <= UINT_MAX);
655 CLEAR_STACK (checker->imported);
656 for (size_t i = 0; i < size; i++) {
657 const unsigned ilit = ilits[i];
658 const unsigned lit = import_internal_checker (solver, checker, ilit);
659 PUSH_STACK (checker->imported, lit);
660 }
661 LOGIMPORTED3 ("checker imported internal");
662}
663
664static void import_clause (kissat *solver, checker *checker, clause *c) {
665 import_internal_literals (solver, checker, c->size, c->lits);
666 LOGIMPORTED3 ("checker imported clause");
667}
668
669static void import_binary (kissat *solver, checker *checker, unsigned a,
670 unsigned b) {
671 CLEAR_STACK (checker->imported);
672 const unsigned c = import_internal_checker (solver, checker, a);
673 const unsigned d = import_internal_checker (solver, checker, b);
674 PUSH_STACK (checker->imported, c);
675 PUSH_STACK (checker->imported, d);
676 LOGIMPORTED3 ("checker imported binary");
677}
678
679static void import_internal_unit (kissat *solver, checker *checker,
680 unsigned a) {
681 CLEAR_STACK (checker->imported);
682 const unsigned b = import_internal_checker (solver, checker, a);
683 PUSH_STACK (checker->imported, b);
684 LOGIMPORTED3 ("checker imported unit");
685}
686
687static bool checker_propagate (kissat *solver, checker *checker) {
688 unsigned propagated = checker->propagated;
689 signed char *values = checker->values;
690 bool res = true;
691 while (res && propagated < SIZE_STACK (checker->trail)) {
692 const unsigned lit = PEEK_STACK (checker->trail, propagated);
693 const unsigned not_lit = lit ^ 1;
694 LOG3 ("checker propagate %u", lit);
695 KISSAT_assert (values[lit] > 0);
696 KISSAT_assert (values[not_lit] < 0);
697 propagated++;
698 buckets_ *buckets = checker_watches (checker, not_lit);
699 bucket **begin_of_lines = BEGIN_STACK (*buckets), **q = begin_of_lines;
700 bucket *const *end_of_lines = END_STACK (*buckets), *const *p = q;
701 while (p != end_of_lines) {
702 bucket *bucket = *q++ = *p++;
703 if (!res)
704 continue;
705 unsigned *lits = bucket->lits;
706 const unsigned other = not_lit ^ lits[0] ^ lits[1];
707 const signed char other_value = values[other];
708 if (other_value > 0)
709 continue;
710 const unsigned *const end_of_lits = lits + bucket->size;
711 unsigned replacement;
712 signed char replacement_value = -1;
713 unsigned *r;
714 for (r = lits + 2; r != end_of_lits; r++) {
715 replacement = *r;
716 if (replacement == other)
717 continue;
718 if (replacement == not_lit)
719 continue;
720 replacement_value = values[replacement];
721 if (replacement_value >= 0)
722 break;
723 }
724 if (replacement_value >= 0) {
725 lits[0] = other;
726 lits[1] = replacement;
727 *r = not_lit;
728 LOGLINE3 ("checker unwatching %u in", not_lit);
729 watch_checker_literal (solver, checker, bucket, replacement);
730 q--;
731 } else if (other_value < 0) {
732 LOGLINE3 ("checker conflict");
733 res = false;
734 } else
735 checker_assign (solver, checker, other, bucket);
736 }
737 SET_END_OF_STACK (*buckets, q);
738 }
739 checker->propagations += propagated - checker->propagated;
740 checker->propagated = propagated;
741 return res;
742}
743
744static bool bucket_redundant (kissat *solver, checker *checker,
745 size_t size) {
746 if (!checker_propagate (solver, checker)) {
747 LOG3 ("root level checker unit propagations leads to conflict");
748 LOG2 ("checker becomes inconsistent");
749 checker->inconsistent = true;
750 return true;
751 }
752 if (checker->inconsistent) {
753 LOG3 ("skipping removal since checker already inconsistent");
754 return true;
755 }
756 if (!size)
757 kissat_fatal ("checker can not remove empty checker clause");
758 if (size == 1) {
759 const unsigned unit = PEEK_STACK (checker->imported, 0);
760 const signed char value = checker->values[unit];
761 if (value < 0 && !checker->inconsistent)
762 kissat_fatal ("consistent checker can not remove falsified unit %d",
763 export_checker (checker, unit));
764 if (!value)
765 kissat_fatal ("checker can not remove unassigned unit %d",
766 export_checker (checker, unit));
767 LOG3 ("checker skips removal of satisfied unit %u", unit);
768 return true;
769 } else if (satisfied_or_trivial_imported (solver, checker)) {
770 LOGIMPORTED3 ("satisfied imported checker");
771 return true;
772 } else
773 return false;
774}
775
776static void remove_line_if_not_redundant (kissat *solver,
777 checker *checker) {
778 size_t size = SIZE_STACK (checker->imported);
779 if (!bucket_redundant (solver, checker, size))
780 remove_line (solver, checker, size);
781}
782
783static void checker_backtrack (checker *checker, unsigned saved) {
784 unsigned *begin = BEGIN_STACK (checker->trail) + saved;
785 unsigned *p = END_STACK (checker->trail);
786 signed char *values = checker->values;
787 while (p != begin) {
788 const unsigned lit = *--p;
789 KISSAT_assert (VALID_CHECKER_LIT (lit));
790 const unsigned not_lit = lit ^ 1;
791 KISSAT_assert (values[lit] > 0);
792 KISSAT_assert (values[not_lit] < 0);
793 values[lit] = values[not_lit] = 0;
794 }
795 checker->propagated = saved;
796 SET_END_OF_STACK (checker->trail, begin);
797}
798
799static bool checker_blocked_literal (kissat *solver, checker *checker,
800 unsigned lit) {
801 signed char *values = checker->values;
802 KISSAT_assert (values[lit] < 0);
803 const unsigned not_lit = lit ^ 1;
804 if (checker->large[not_lit])
805 return false;
806 buckets_ *buckets = checker_watches (checker, not_lit);
807 bucket *const *const begin_of_lines = BEGIN_STACK (*buckets);
808 bucket *const *const end_of_lines = END_STACK (*buckets);
809 bucket *const *p = begin_of_lines;
810 while (p != end_of_lines) {
811 bucket *bucket = *p++;
812 const unsigned *const lits = bucket->lits;
813 const unsigned *const end_of_lits = lits + bucket->size;
814 const unsigned *l = lits;
815 while (l != end_of_lits) {
816 const unsigned other = *l++;
817 if (other == not_lit)
818 continue;
819 if (values[other] > 0)
820 goto CONTINUE_WITH_NEXT_BUCKET;
821 }
822 return false;
823 CONTINUE_WITH_NEXT_BUCKET:;
824 }
825#ifdef LOGGING
826 LOG3 ("blocked literal %u", lit);
827#else
828 (void) solver;
829#endif
830 return true;
831}
832
833static bool checker_blocked_imported (kissat *solver, checker *checker) {
834 for (all_stack (unsigned, lit, checker->imported))
835 if (checker_blocked_literal (solver, checker, lit))
836 return true;
837 return false;
838}
839
840static void check_line (kissat *solver, checker *checker) {
841 checker->checked++;
842 if (checker->inconsistent)
843 return;
844 if (!checker_propagate (solver, checker)) {
845 LOG3 ("root level checker unit propagations leads to conflict");
846 LOG2 ("checker becomes inconsistent");
847 checker->inconsistent = true;
848 return;
849 }
850 const unsigned saved = SIZE_STACK (checker->trail);
851 signed char *values = checker->values;
852 bool satisfied = false, pure = false;
853 unsigned decisions = 0, prev = INVALID_LIT;
854 for (all_stack (unsigned, lit, checker->imported)) {
855 KISSAT_assert (prev != lit);
856 prev = lit;
857 signed char lit_value = values[lit];
858 if (lit_value < 0)
859 continue;
860 if (lit_value > 0) {
861 LOG3 ("found satisfied literal %u", lit);
862 checker->satisfied++;
863 satisfied = true;
864 break;
865 }
866 const unsigned not_lit = lit ^ 1;
867 bool used = checker->used[not_lit];
868 if (!used) {
869 LOG3 ("found pure literal %u", lit);
870 checker->pure++;
871 pure = true;
872 break;
873 }
874 checker_assign (solver, checker, not_lit, &decision_line);
875 decisions++;
876 }
877 checker->decisions += decisions;
878 if (!satisfied && !pure) {
879 if (!checker_propagate (solver, checker))
880 LOG3 ("checker imported clause unit implied");
881 else if (checker_blocked_imported (solver, checker)) {
882 LOG3 ("checker imported clause binary blocked");
883 checker->blocked++;
884 } else {
886 fputs ("failed to check clause:\n", stderr);
887 for (all_stack (unsigned, lit, checker->imported))
888 fprintf (stderr, "%d ", export_checker (checker, lit));
889 fputs ("0\n", stderr);
890 fflush (stderr);
891 kissat_abort ();
892 }
893 }
894 checker_backtrack (checker, saved);
895}
896
897void kissat_add_unchecked_external (kissat *solver, size_t size,
898 const int *elits) {
899 LOGINTS3 (size, elits, "adding unchecked external checker");
900 checker *checker = solver->checker;
901 checker->unchecked++;
902 import_external_literals (solver, checker, size, elits);
903 insert_imported_if_not_simplified (solver, checker);
904}
905
906void kissat_add_unchecked_internal (kissat *solver, size_t size,
907 unsigned *lits) {
908 LOGUNSIGNEDS3 (size, lits, "adding unchecked internal checker");
909 checker *checker = solver->checker;
910 checker->unchecked++;
911 KISSAT_assert (size <= UINT_MAX);
912 import_internal_literals (solver, checker, size, lits);
913 insert_imported_if_not_simplified (solver, checker);
914}
915
916void kissat_check_and_add_binary (kissat *solver, unsigned a, unsigned b) {
917 LOGBINARY3 (a, b, "checking and adding internal checker");
918 checker *checker = solver->checker;
921 import_binary (solver, checker, a, b);
922 check_line (solver, checker);
923 insert_imported_if_not_simplified (solver, checker);
924}
925
926void kissat_check_and_add_clause (kissat *solver, clause *clause) {
927 LOGCLS3 (clause, "checking and adding internal checker");
928 checker *checker = solver->checker;
929 import_clause (solver, checker, clause);
930 check_line (solver, checker);
931 insert_imported_if_not_simplified (solver, checker);
932}
933
934void kissat_check_and_add_empty (kissat *solver) {
935 LOG3 ("checking and adding empty checker clause");
936 checker *checker = solver->checker;
937 CLEAR_STACK (checker->imported);
938 check_line (solver, checker);
939 insert_imported_if_not_simplified (solver, checker);
940}
941
942void kissat_check_and_add_internal (kissat *solver, size_t size,
943 const unsigned *lits) {
944 LOGUNSIGNEDS3 (size, lits, "checking and adding internal checker");
945 checker *checker = solver->checker;
946 import_internal_literals (solver, checker, size, lits);
947 check_line (solver, checker);
948 insert_imported_if_not_simplified (solver, checker);
949}
950
951void kissat_check_and_add_unit (kissat *solver, unsigned a) {
952 LOG3 ("checking and adding internal checker internal unit %u", a);
953 checker *checker = solver->checker;
955 import_internal_unit (solver, checker, a);
956 check_line (solver, checker);
957 insert_imported_if_not_simplified (solver, checker);
958}
959
960void kissat_check_shrink_clause (kissat *solver, clause *c, unsigned remove,
961 unsigned keep) {
962 LOGCLS3 (c, "checking and shrinking by %u internal checker", remove);
963 checker *checker = solver->checker;
964 CLEAR_STACK (checker->imported);
965 const value *const values = solver->values;
966 for (all_literals_in_clause (ilit, c)) {
967 if (ilit == remove)
968 continue;
969 if (ilit != keep && values[ilit] < 0 && !LEVEL (ilit))
970 continue;
971 const unsigned lit = import_internal_checker (solver, checker, ilit);
972 PUSH_STACK (checker->imported, lit);
973 }
974 LOGIMPORTED3 ("checker imported internal");
975 check_line (solver, checker);
976 insert_imported_if_not_simplified (solver, checker);
977 import_clause (solver, checker, c);
978 remove_line_if_not_redundant (solver, checker);
979}
980
981void kissat_remove_checker_binary (kissat *solver, unsigned a, unsigned b) {
982 LOGBINARY3 (a, b, "removing internal checker");
983 checker *checker = solver->checker;
986 import_binary (solver, checker, a, b);
987 remove_line_if_not_redundant (solver, checker);
988}
989
990void kissat_remove_checker_clause (kissat *solver, clause *clause) {
991 LOGCLS3 (clause, "removing internal checker");
992 checker *checker = solver->checker;
993 import_clause (solver, checker, clause);
994 remove_line_if_not_redundant (solver, checker);
995}
996
997bool kissat_checker_contains_clause (kissat *solver, clause *clause) {
998 checker *checker = solver->checker;
999 import_clause (solver, checker, clause);
1000 size_t size = SIZE_STACK (checker->imported);
1001 if (bucket_redundant (solver, checker, size))
1002 return true;
1003 return find_line (solver, checker, size, false);
1004}
1005
1006void kissat_remove_checker_external (kissat *solver, size_t size,
1007 const int *elits) {
1008 LOGINTS3 (size, elits, "removing external checker");
1009 checker *checker = solver->checker;
1010 import_external_literals (solver, checker, size, elits);
1011 remove_line_if_not_redundant (solver, checker);
1012}
1013
1014void kissat_remove_checker_internal (kissat *solver, size_t size,
1015 const unsigned *ilits) {
1016 LOGUNSIGNEDS3 (size, ilits, "removing internal checker");
1017 checker *checker = solver->checker;
1018 import_internal_literals (solver, checker, size, ilits);
1019 remove_line_if_not_redundant (solver, checker);
1020}
1021
1022void dump_line (bucket *bucket) {
1023 printf ("bucket[%p]", (void *) bucket);
1024 for (unsigned i = 0; i < bucket->size; i++)
1025 printf (" %u", bucket->lits[i]);
1026 fputc ('\n', stdout);
1027}
1028
1029void dump_checker (kissat *solver) {
1030 checker *checker = solver->checker;
1031 printf ("%s\n", checker->inconsistent ? "inconsistent" : "consistent");
1032 printf ("vars %u\n", checker->vars);
1033 printf ("size %u\n", checker->size);
1034 printf ("buckets %u\n", checker->buckets);
1035 printf ("hashed %u\n", checker->hashed);
1036 for (unsigned i = 0; i < SIZE_STACK (checker->trail); i++)
1037 printf ("trail[%u] %u\n", i, PEEK_STACK (checker->trail, i));
1038 for (unsigned h = 0; h < checker->hashed; h++)
1039 for (bucket *bucket = checker->table[h]; bucket; bucket = bucket->next)
1040 dump_line (bucket);
1041}
1042
1044
1045#else
1049#endif
1050
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
Definition allocate.c:49
void * kissat_calloc(kissat *solver, size_t n, size_t size)
Definition allocate.c:97
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
void * kissat_realloc(kissat *solver, void *p, size_t old_bytes, size_t new_bytes)
Definition allocate.c:123
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
Definition allocate.c:114
#define LEVEL(LIT)
Definition assign.h:34
ABC_NAMESPACE_HEADER_START typedef uint64_t generator
Definition random.h:12
#define BEGIN_STACK(S)
Definition stack.h:46
#define REMOVE_STACK(T, S, E)
Definition stack.h:77
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define SET_END_OF_STACK(S, P)
Definition stack.h:62
#define RELEASE_STACK(S)
Definition stack.h:71
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define PEEK_STACK(S, N)
Definition stack.h:29
#define STACK(TYPE)
Definition stack.h:10
#define END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
ABC_NAMESPACE_IMPL_START int kissat_check_dummy_to_avoid_warning
Definition check.c:1047
void kissat_fatal_message_start(void)
Definition error.c:40
void kissat_abort(void)
Definition error.c:19
void kissat_fatal(const char *fmt,...)
Definition error.c:58
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
int kissat_value(kissat *solver, int elit)
Definition internal.c:498
#define all_literals_in_clause(LIT, C)
Definition clause.h:47
#define KISSAT_assert(ignore)
Definition global.h:13
#define SORT_STACK(TYPE, S, LESS)
Definition sort.h:148
#define solver
Definition kitten.c:211
#define LOG2(...)
Definition logging.h:352
#define LOGINTS3(...)
Definition logging.h:397
#define LOG3(...)
Definition logging.h:355
#define LOGCLS3(...)
Definition logging.h:421
#define LOGBINARY3(...)
Definition logging.h:448
#define LOGUNSIGNEDS3(...)
Definition logging.h:403
unsigned long long size
Definition giaNewBdd.h:39
unsigned short var
Definition giaNewBdd.h:35
int lit
Definition satVec.h:130
#define VALID_INTERNAL_LITERAL(LIT)
Definition literal.h:23
unsigned lits[3]
Definition clause.h:39
unsigned size
Definition clause.h:37
char * memcpy()
char * memset()
long random()
#define ABS(a)
Definition util_old.h:250
#define SWAP(TYPE, A, B)
Definition utilities.h:151
vector watches
Definition watch.h:49