ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
congruence.c
Go to the documentation of this file.
1#include "congruence.h"
2#include "dense.h"
3#include "fifo.h"
4#include "inline.h"
5#include "inlinevector.h"
6#include "internal.h"
7#include "logging.h"
8#include "print.h"
9#include "proprobe.h"
10#include "rank.h"
11#include "reference.h"
12#include "report.h"
13#include "sort.h"
14#include "terminate.h"
15#include "trail.h"
16#include "utilities.h"
17
18#include <stddef.h>
19#include <stdint.h>
20#include <string.h>
21
23
24// #define INDEX_LARGE_CLAUSES
25// #define INDEX_BINARY_CLAUSES
26#define MERGE_CONDITIONAL_EQUIVALENCES
27
28#define AND_GATE 0
29#define XOR_GATE 1
30#define ITE_GATE 2
31
32#define LD_MAX_ARITY 26
33#define MAX_ARITY ((1 << LD_MAX_ARITY) - 1)
34
35struct gate {
36#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
37 size_t id;
38#endif
39 unsigned lhs;
40 unsigned hash;
41 unsigned tag : 2;
42 bool garbage : 1;
43 bool indexed : 1;
44 bool marked : 1;
45 bool shrunken : 1;
46 unsigned arity : LD_MAX_ARITY;
47 unsigned rhs[];
48};
49
50typedef struct gate gate;
51typedef STACK (gate *) gates;
52
53struct gate_hash_table {
54 gate **table;
55 size_t size;
56 size_t entries;
57};
58
60
61#define REMOVED ((gate *) (~(uintptr_t) 0))
62
63#define BEGIN_RHS(G) ((G)->rhs)
64#define END_RHS(G) (BEGIN_RHS (G) + (G)->arity)
65
66#define all_rhs_literals_in_gate(LIT, G) \
67 unsigned LIT, \
68 *LIT##_PTR = BEGIN_RHS (G), *const LIT##_END = END_RHS (G); \
69 LIT##_PTR != LIT##_END && ((LIT = *LIT##_PTR), true); \
70 ++LIT##_PTR
71
72#ifdef INDEX_BINARY_CLAUSES
73
74struct binary_clause {
75 unsigned lits[2];
76};
77
78typedef struct binary_clause binary_clause;
79
80struct binary_hash_table {
81 binary_clause *table;
82 size_t size, size2, count;
83};
84
85typedef struct binary_hash_table binary_hash_table;
86
87#endif
88
89struct hash_ref {
90 unsigned hash;
92};
93
94#ifdef INDEX_LARGE_CLAUSES
95
96typedef struct hash_ref hash_ref;
97
98struct large_clause_hash_table {
99 hash_ref *table;
100 size_t size, size2, count;
101};
102
103typedef struct large_clause_hash_table large_clause_hash_table;
104
105#endif
106
107#define SIZE_NONCES 16
108
109struct closure {
113 gates garbage;
114 unsigneds lits;
115 unsigneds rhs;
116 unsigneds unsimplified;
117 litpairs binaries;
119 unsigned *repr;
122 unsigned *units;
123 unsigned *equivalences;
124 unsigned *negbincount;
125 unsigned *largecount;
126 litpairs condbin[2];
127 litpairs condeq[2];
128#ifdef INDEX_BINARY_CLAUSES
129 binary_hash_table bintab;
130#endif
131#ifdef INDEX_LARGE_CLAUSES
132 large_clause_hash_table clauses;
133#endif
134#ifdef CHECKING_OR_PROVING
135 unsigneds chain;
136#endif
137#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
138 size_t gates_added;
139#endif
140#ifndef KISSAT_NDEBUG
141 unsigneds implied;
142#endif
143};
144
145typedef struct closure closure;
146
147static void init_closure (kissat *solver, closure *closure) {
149 CALLOC (bool, closure->scheduled, VARS);
150 CALLOC (gates, closure->occurrences, LITS);
157
158 NALLOC (unsigned, closure->repr, LITS);
159 for (all_literals (lit))
160 closure->repr[lit] = lit;
161
162 closure->hash.table = 0;
163 closure->hash.size = closure->hash.entries = 0;
164
165 generator random = solver->random;
166 for (size_t i = 0; i != SIZE_NONCES; i++)
167 closure->nonces[i] = 1 | kissat_next_random64 (&random);
168
169#ifdef CHECKING_OR_PROVING
170 INIT_STACK (closure->chain);
171#endif
172#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
173 closure->gates_added = 0;
174#endif
175#ifndef KISSAT_NDEBUG
176 INIT_STACK (closure->implied);
177#endif
178}
179
180static size_t bytes_gate (size_t arity) {
181 return sizeof (gate) + arity * sizeof (unsigned);
182}
183
184static unsigned actual_gate_arity (gate *g) {
185 unsigned res = g->arity;
186 if (!g->shrunken)
187 return res;
188 while (g->rhs[res++] != INVALID_LIT)
189 ;
190 return res;
191}
192
193#define CLOGANDGATE(G, ...) \
194 do { \
195 KISSAT_assert ((G)->tag == AND_GATE); \
196 LOGANDGATE ((G)->id, closure->repr, (G)->lhs, (G)->arity, (G)->rhs, \
197 __VA_ARGS__); \
198 } while (0)
199
200#define CLOGXORGATE(G, ...) \
201 do { \
202 KISSAT_assert ((G)->tag == XOR_GATE); \
203 LOGXORGATE ((G)->id, closure->repr, (G)->lhs, (G)->arity, (G)->rhs, \
204 __VA_ARGS__); \
205 } while (0)
206
207#define CLOGITEGATE(G, ...) \
208 do { \
209 KISSAT_assert ((G)->tag == ITE_GATE); \
210 LOGITEGATE ((G)->id, closure->repr, (G)->lhs, (G)->rhs[0], \
211 (G)->rhs[1], (G)->rhs[2], __VA_ARGS__); \
212 } while (0)
213
214#define CLOGREPR(L) LOGREPR ((L), closure->repr)
215
216#define LOGATE(G, ...) \
217 do { \
218 if ((G)->tag == AND_GATE) \
219 CLOGANDGATE (G, __VA_ARGS__); \
220 else if ((G)->tag == XOR_GATE) \
221 CLOGXORGATE (G, __VA_ARGS__); \
222 else { \
223 KISSAT_assert ((G)->tag == ITE_GATE); \
224 CLOGITEGATE (G, __VA_ARGS__); \
225 } \
226 } while (0)
227
228static void delete_gate (closure *closure, gate *g) {
229 kissat *const solver = closure->solver;
230 LOGATE (g, "delete");
231 unsigned actual_arity = actual_gate_arity (g);
232 size_t actual_bytes = bytes_gate (actual_arity);
233 kissat_free (solver, g, actual_bytes);
234}
235
237 kissat *const solver = closure->solver;
238 gate **table = closure->hash.table;
239 for (size_t pos = 0; pos != closure->hash.size; pos++) {
240 gate *g = table[pos];
241 if (g && g != REMOVED && !g->garbage)
242 delete_gate (closure, g);
243 }
244 DEALLOC (table, closure->hash.size);
245}
246
247static void reset_closure (closure *closure) {
248 kissat *const solver = closure->solver;
249
251 for (all_literals (lit))
254
256 for (all_pointers (gate, g, closure->garbage))
257 delete_gate (closure, g);
258
266#ifdef CHECKING_OR_PROVING
267 RELEASE_STACK (closure->chain);
268#endif
269#ifndef KISSAT_NDEBUG
270 RELEASE_STACK (closure->implied);
271#endif
272
273 if (!solver->inconsistent && solver->unflushed)
275}
276
277static unsigned reset_repr (closure *closure) {
278 kissat *const solver = closure->solver;
279 unsigned res = 0, *repr = closure->repr;
280 for (all_variables (idx)) {
281 unsigned lit = LIT (idx);
282 if (!VALUE (lit) && repr[lit] != lit)
283 res++;
284 }
285 DEALLOC (repr, LITS);
286 return res;
287}
288
289#ifndef KISSAT_NDEBUG
290
291static void check_lits_sorted (size_t size, const unsigned *lits) {
292 unsigned prev = INVALID_LIT;
293 const unsigned *const end_lits = lits + size;
294 for (const unsigned *p = lits; p != end_lits; p++) {
295 const unsigned lit = *p;
296 if (prev != INVALID_LIT) {
297 KISSAT_assert (prev != lit);
298 const unsigned not_lit = lit ^ 1;
299 KISSAT_assert (prev != not_lit);
300 KISSAT_assert (prev < lit);
301 }
302 prev = lit;
303 }
304}
305
306static void check_and_lits_normalized (size_t arity, const unsigned *lits) {
307 KISSAT_assert (arity > 1);
308 check_lits_sorted (arity, lits);
309}
310
311static void check_xor_lits_normalized (const unsigned arity,
312 const unsigned *lits) {
313 KISSAT_assert (arity > 1);
314 check_lits_sorted (arity, lits);
315 for (size_t i = 1; i != arity; i++)
316 KISSAT_assert (lits[i - 1] < lits[i]);
317}
318
320 const unsigned *lits) {
321 KISSAT_assert (!NEGATED (lits[0]));
322 KISSAT_assert (!NEGATED (lits[1]));
323 KISSAT_assert (lits[0] != lits[1]);
324 KISSAT_assert (lits[0] != lits[2]);
325 KISSAT_assert (lits[1] != lits[2]);
326 KISSAT_assert (lits[0] != NOT (lits[1]));
327 KISSAT_assert (lits[0] != NOT (lits[2]));
328 KISSAT_assert (lits[1] != NOT (lits[2]));
329}
330
331#else
332
333#define check_lits_sorted(...) \
334 do { \
335 } while (0)
336
337#define check_and_lits_normalized check_lits_sorted
338#define check_xor_lits_normalized check_lits_sorted
339#define check_ite_lits_normalized check_lits_sorted
340
341#endif
342
343#define LESS_LIT(A, B) ((A) < (B))
344
345static void sort_lits (kissat *solver, size_t arity, unsigned *lits) {
346 SORT (unsigned, arity, lits, LESS_LIT);
347 check_lits_sorted (arity, lits);
348}
349
350static unsigned hash_lits (closure *closure, unsigned tag, size_t arity,
351 const unsigned *lits) {
352#ifndef KISSAT_NDEBUG
353 if (tag == AND_GATE)
355 else if (tag == XOR_GATE)
357 else {
358 KISSAT_assert (tag == ITE_GATE);
360 }
361#endif
362 const unsigned *end_lits = lits + arity;
363 const uint64_t *const nonces = closure->nonces;
364 const uint64_t *const end_nonces = nonces + SIZE_NONCES;
365 const uint64_t *n = nonces + tag;
366 uint64_t hash = 0;
367 KISSAT_assert (n < end_nonces);
368 for (const unsigned *l = lits; l != end_lits; l++) {
369 hash += *l;
370 hash *= *n++;
371 hash = (hash << 4) | (hash >> 60);
372 if (n == end_nonces)
373 n = nonces;
374 }
375 hash ^= hash >> 32;
376 return hash;
377}
378
379#ifndef KISSAT_NDEBUG
380static bool is_power_of_two (size_t n) { return n && ~(n & (n - 1)); }
381#endif
382
383static size_t reduce_hash (unsigned hash, size_t size, size_t size2) {
384 KISSAT_assert (size <= size2);
385 KISSAT_assert (size2 <= 2 * size);
386 KISSAT_assert (is_power_of_two (size2));
387 unsigned res = hash;
388 res &= size2 - 1;
389 if (res >= size)
390 res -= size;
391 KISSAT_assert (res < size);
392 return res;
393}
394
395#define MAX_HASH_TABLE_SIZE ((size_t) 1 << 32)
396
397static bool closure_hash_table_is_full (closure *closure) {
398 if (closure->hash.size == MAX_HASH_TABLE_SIZE)
399 return false;
400 if (2 * closure->hash.entries < closure->hash.size)
401 return false;
402 return true;
403}
404
405static bool match_lits (gate *g, unsigned tag, unsigned hash, size_t size,
406 const unsigned *lits) {
408 if (g->tag != tag)
409 return false;
410 if (g->hash != hash)
411 return false;
412 if (g->arity != size)
413 return false;
414 const unsigned *p = lits;
416 if (lit != *p++)
417 return false;
418 return true;
419}
420
421static void resize_gate_hash_table (closure *closure) {
424 const size_t old_size = hash->size;
425 const size_t new_size = old_size ? 2 * old_size : 1;
426 const size_t old_entries = hash->entries;
428 solver,
429 "resizing gate table of size %zu filled with %zu entries %.0f%%",
430 old_size, old_entries, kissat_percent (old_entries, old_size));
431 gate **old_table = hash->table, **new_table;
432 CALLOC (gate*, new_table, new_size);
433 size_t flushed = 0;
434 for (size_t old_pos = 0; old_pos != old_size; old_pos++) {
435 gate *g = old_table[old_pos];
436 if (!g)
437 continue;
438 if (g == REMOVED) {
439 flushed++;
440 continue;
441 }
442 size_t new_pos = reduce_hash (g->hash, new_size, new_size);
443 while (new_table[new_pos]) {
444 KISSAT_assert (new_table[new_pos] != REMOVED);
445 if (++new_pos == new_size)
446 new_pos = 0;
447 }
448 new_table[new_pos] = g;
449 }
451 solver, "flushed %zu entries %.0f%% resizing table of size %zu",
452 flushed, kissat_percent (flushed, old_size), old_size);
453 DEALLOC (old_table, old_size);
454 KISSAT_assert (flushed <= old_entries);
455 const size_t new_entries = old_entries - flushed;
456 hash->table = new_table;
457 hash->size = new_size;
458 hash->entries = new_entries;
460 solver, "resized gate table to %zu with %zu entries %.0f%%", new_size,
461 new_entries, kissat_percent (new_entries, new_size));
462}
463
464static bool remove_gate (closure *closure, gate *g) {
465 if (!g->indexed)
466 return false;
468 KISSAT_assert (!solver->inconsistent);
469 const size_t hash_size = closure->hash.size;
470 size_t pos = reduce_hash (g->hash, hash_size, hash_size);
471 gate **table = closure->hash.table;
472 INC (congruent_lookups);
473 INC (congruent_lookups_removed);
474 unsigned collisions = 0;
475 while (table[pos] != g) {
476 collisions++;
477 if (++pos == hash_size)
478 pos = 0;
479 }
480 ADD (congruent_collisions_removed, collisions);
481 ADD (congruent_collisions, collisions);
482 table[pos] = REMOVED;
483 LOGATE (g, "removing from hash table");
484 g->indexed = false;
485 return true;
486}
487
488static gate *find_gate (closure *closure, unsigned tag, unsigned hash,
489 size_t size, const unsigned *lits, gate *except) {
490 KISSAT_assert (!except || !except->garbage);
491 if (!closure->hash.entries)
492 return 0;
494 KISSAT_assert (!solver->inconsistent);
495 KISSAT_assert (hash == hash_lits (closure, tag, size, lits));
496 const size_t hash_size = closure->hash.size;
497 size_t start_pos = reduce_hash (hash, hash_size, hash_size);
498 gate **table = closure->hash.table, *g;
499 INC (congruent_lookups);
500 INC (congruent_lookups_find);
501 size_t pos = start_pos;
502 unsigned collisions = 0;
503 gate *res = 0;
504 while ((g = table[pos])) {
505 if (g == REMOVED)
506 ;
507 else if (g->garbage) {
509 g->indexed = false;
510 table[pos] = REMOVED;
511 } else if (g != except && match_lits (g, tag, hash, size, lits)) {
512 INC (congruent_matched);
513 res = g;
514 break;
515 }
516 collisions++;
517 if (++pos == hash_size)
518 pos = 0;
519 if (pos == start_pos)
520 break;
521 }
522 ADD (congruent_collisions_find, collisions);
523 ADD (congruent_collisions, collisions);
524 return res;
525}
526
527static void index_gate (closure *closure, gate *g) {
530 KISSAT_assert (!solver->inconsistent);
531 KISSAT_assert (g->arity > 1);
532 if (closure_hash_table_is_full (closure))
533 resize_gate_hash_table (closure);
534 LOGATE (g, "adding to hash table");
535 INC (congruent_indexed);
536 KISSAT_assert (g->hash == hash_lits (closure, g->tag, g->arity, g->rhs));
537 const size_t hash_size = closure->hash.size;
538 size_t pos = reduce_hash (g->hash, hash_size, hash_size);
539 gate **table = closure->hash.table, *h;
540 unsigned collisions = 0;
541 while ((h = table[pos]) && h != REMOVED) {
542 collisions++;
543 if (++pos == hash_size)
544 pos = 0;
545 }
546 ADD (congruent_collisions_index, collisions);
547 ADD (congruent_collisions, collisions);
548 table[pos] = g;
549 closure->hash.entries++;
550 g->indexed = true;
551}
552
553static unsigned parity_lits (kissat *solver, unsigneds *lits) {
554 unsigned res = 0;
555 for (all_stack (unsigned, lit, *lits))
556 res ^= NEGATED (lit);
557#ifdef KISSAT_NDEBUG
558 (void) solver;
559#endif
560 return res;
561}
562
563static void inc_lits (kissat *solver, unsigneds *lits) {
564 unsigned *p = BEGIN_STACK (*lits);
565 unsigned *end = END_STACK (*lits);
566 unsigned carry = 1;
567 while (carry && p != end) {
568 unsigned lit = *p;
569 unsigned not_lit = NOT (lit);
570 carry = !NEGATED (not_lit);
571 *p++ = not_lit;
572 }
573#ifdef KISSAT_NDEBUG
574 (void) solver;
575#endif
576}
577
578#ifndef KISSAT_NDEBUG
579
580#define LESS_LITERAL(A, B) ((A) < (B))
581
582static void check_implied (closure *closure) {
583 kissat *const solver = closure->solver;
584 unsigneds *implied = &closure->implied;
585 SORT_STACK (unsigned, *implied, LESS_LITERAL);
586 unsigned *q = BEGIN_STACK (*implied);
587 const unsigned *const end = END_STACK (*implied);
588 unsigned prev = INVALID_LIT;
589 bool tautological = false;
590 for (const unsigned *p = q; p != end; p++) {
591 const unsigned lit = *p;
592 if (prev == lit)
593 continue;
594 const unsigned not_lit = NOT (lit);
595 if (prev == not_lit) {
596 tautological = true;
597 break;
598 }
599 *q++ = prev = lit;
600 }
601 if (!tautological) {
602 SET_END_OF_STACK (*implied, q);
603 CHECK_AND_ADD_STACK (*implied);
604 REMOVE_CHECKER_STACK (*implied);
605 }
606 CLEAR_STACK (*implied);
607}
608
609static void check_clause (closure *closure) {
610 kissat *const solver = closure->solver;
611 unsigneds *implied = &closure->implied;
612 unsigneds *clause = &solver->clause;
613 for (all_stack (unsigned, lit, *clause))
614 PUSH_STACK (*implied, lit);
615 check_implied (closure);
616}
617
618static void check_binary_implied (closure *closure, unsigned a,
619 unsigned b) {
620 kissat *const solver = closure->solver;
621 unsigneds *implied = &closure->implied;
622 KISSAT_assert (EMPTY_STACK (*implied));
623 PUSH_STACK (*implied, a);
624 PUSH_STACK (*implied, b);
625 check_implied (closure);
626}
627
628static void check_and_gate_implied (closure *closure, gate *g) {
629 KISSAT_assert (g->tag == AND_GATE);
630 kissat *const solver = closure->solver;
631 if (GET_OPTION (check) < 2)
632 return;
633 CLOGANDGATE (g, "checking implied");
634 const unsigned lhs = g->lhs;
635 const unsigned not_lhs = NOT (lhs);
636 for (all_rhs_literals_in_gate (other, g))
637 check_binary_implied (closure, not_lhs, other);
638 unsigneds *implied = &closure->implied;
639 KISSAT_assert (EMPTY_STACK (*implied));
640 PUSH_STACK (*implied, lhs);
641 for (all_rhs_literals_in_gate (other, g)) {
642 const unsigned not_other = NOT (other);
643 PUSH_STACK (*implied, not_other);
644 }
645 check_implied (closure);
646}
647
648static void check_xor_gate_implied (closure *closure, gate *g) {
649 KISSAT_assert (g->tag == XOR_GATE);
650 kissat *const solver = closure->solver;
651 if (GET_OPTION (check) < 2)
652 return;
653 CLOGXORGATE (g, "checking implied");
654 const unsigned lhs = g->lhs;
655 const unsigned not_lhs = NOT (lhs);
656 unsigneds *clause = &solver->clause;
658 PUSH_STACK (*clause, not_lhs);
659 for (all_rhs_literals_in_gate (other, g)) {
660 KISSAT_assert (!NEGATED (other));
661 PUSH_STACK (*clause, other);
662 }
663 unsigned arity = g->arity;
664 unsigned end = 1u << arity;
665 unsigned parity = NEGATED (not_lhs);
666 KISSAT_assert (parity == parity_lits (solver, clause));
667 for (unsigned i = 0; i != end; i++) {
668 while (i && parity_lits (solver, clause) != parity)
669 inc_lits (solver, clause);
670 check_clause (closure);
671 inc_lits (solver, clause);
672 }
674}
675
676static void check_ternary (closure *closure, unsigned a, unsigned b,
677 unsigned c) {
678 kissat *const solver = closure->solver;
679 if (GET_OPTION (check) < 2)
680 return;
681 unsigneds *implied = &closure->implied;
682 PUSH_STACK (*implied, a);
683 PUSH_STACK (*implied, b);
684 PUSH_STACK (*implied, c);
685 check_implied (closure);
686}
687
688static void check_ite_implied (closure *closure, unsigned lhs,
689 unsigned cond, unsigned then_lit,
690 unsigned else_lit) {
691 kissat *const solver = closure->solver;
692 if (GET_OPTION (check) < 2)
693 return;
694 LOG ("checking implied ITE gate %s := %s ? %s : %s", LOGLIT (lhs),
695 LOGLIT (cond), LOGLIT (then_lit), LOGLIT (else_lit));
696 const unsigned not_lhs = NOT (lhs);
697 const unsigned not_cond = NOT (cond);
698 const unsigned not_then_lit = NOT (then_lit);
699 const unsigned not_else_lit = NOT (else_lit);
700 check_ternary (closure, cond, not_else_lit, lhs);
701 check_ternary (closure, cond, else_lit, not_lhs);
702 check_ternary (closure, not_cond, not_then_lit, lhs);
703 check_ternary (closure, not_cond, then_lit, not_lhs);
704}
705
706static void check_ite_gate_implied (closure *closure, gate *g) {
707 KISSAT_assert (g->tag == ITE_GATE);
708 KISSAT_assert (g->arity == 3);
709#ifndef KISSAT_NOPTIONS
710 kissat *const solver = closure->solver;
711#endif
712 if (GET_OPTION (check) < 2)
713 return;
714 const unsigned lhs = g->lhs;
715 const unsigned cond = g->rhs[0];
716 const unsigned then_lit = g->rhs[1];
717 const unsigned else_lit = g->rhs[2];
718 check_ite_implied (closure, lhs, cond, then_lit, else_lit);
719}
720
721#else
722
723#define check_and_gate_implied(...) \
724 do { \
725 } while (0)
726
727#define check_xor_gate_implied check_and_gate_implied
728#define check_ternary check_and_gate_implied
729#define check_ite_implied check_and_gate_implied
730#define check_ite_gate_implied check_and_gate_implied
731
732#endif
733
734static inline unsigned find_repr (closure *closure, unsigned lit) {
735 const unsigned *const repr = closure->repr;
736 unsigned res = lit, next = repr[res];
737 while (res != next)
738 res = next, next = repr[res];
739 return res;
740}
741
742#ifndef MERGE_CONDITIONAL_EQUIVALENCES
743
744static clause *find_other_two (kissat *solver, watches *watches, unsigned a,
745 unsigned b, unsigned ignore) {
746 KISSAT_assert (!solver->watching);
747 const value *const values = solver->values;
748 const watch *const begin_watches = BEGIN_WATCHES (*watches);
749 const watch *const end_watches = END_WATCHES (*watches);
750 const watch *p = begin_watches;
751 while (p != end_watches) {
752 const watch watch = *p++;
754 const reference ref = watch.large.ref;
755 clause *c = kissat_dereference_clause (solver, ref);
757 unsigned found = 0;
758 for (all_literals_in_clause (lit, c)) {
759 if (values[lit])
760 continue;
761 if (lit == ignore)
762 continue;
763 if (lit == a || lit == b) {
764 found++;
765 continue;
766 }
767 goto CONTINUE_WITH_NEXT_WATCH;
768 }
769 KISSAT_assert (found <= 2);
770 if (found == 2)
771 return c;
772 CONTINUE_WITH_NEXT_WATCH:;
773 }
774 return 0;
775}
776
777static clause *find_ternary_clause (kissat *solver, unsigned a, unsigned b,
778 unsigned c) {
779 KISSAT_assert (!solver->watching);
780 watches *const a_watches = &WATCHES (a);
781 watches *const b_watches = &WATCHES (b);
782 watches *const c_watches = &WATCHES (c);
783 const size_t size_a = SIZE_WATCHES (*a_watches);
784 const size_t size_b = SIZE_WATCHES (*b_watches);
785 const size_t size_c = SIZE_WATCHES (*c_watches);
786 if (size_a <= size_b && size_a <= size_b)
787 return find_other_two (solver, a_watches, b, c, a);
788 if (size_b <= size_a && size_b <= size_c)
789 return find_other_two (solver, b_watches, a, c, b);
790 KISSAT_assert (size_c <= size_a && size_c <= size_b);
791 return find_other_two (solver, c_watches, a, b, c);
792}
793
794#endif
795
796static bool learn_congruence_unit (closure *closure, unsigned unit) {
797 kissat *const solver = closure->solver;
798 KISSAT_assert (!solver->inconsistent);
799 const value value = solver->values[unit];
800 if (value > 0)
801 return true;
802 INC (congruent_units);
803 if (value < 0) {
804 solver->inconsistent = 1;
805 LOG ("inconsistent congruence unit %s", LOGLIT (unit));
808 return false;
809 }
810 LOG ("learning congruence unit %s", LOGLIT (unit));
812 clause *conflict = kissat_probing_propagate (solver, 0, false);
813 if (!conflict)
814 return true;
815 KISSAT_assert (solver->inconsistent);
816 LOG ("propagating congruence unit %s yields conflict", LOGLIT (unit));
817 return false;
818}
819
820static void add_binary_clause (closure *closure, unsigned a, unsigned b) {
821 kissat *const solver = closure->solver;
822 if (solver->inconsistent)
823 return;
824 if (a == NOT (b))
825 return;
826 value a_value = VALUE (a);
827 if (a_value > 0)
828 return;
829 value b_value = VALUE (b);
830 if (b_value > 0)
831 return;
832 unsigned unit = INVALID_LIT;
833 if (a == b)
834 unit = a;
835 else if (a_value < 0 && !b_value)
836 unit = b;
837 else if (!a_value && b_value < 0)
838 unit = a;
839 if (unit != INVALID_LIT) {
840 (void) !learn_congruence_unit (closure, unit);
841 return;
842 }
843 KISSAT_assert (!a_value), KISSAT_assert (!b_value);
844 LOGBINARY (a, b, "adding representative");
845 if (solver->watching)
847 else {
849 litpair litpair = {.lits = {a < b ? a : b, a < b ? b : a}};
851 }
852}
853
854static void schedule_literal (closure *closure, unsigned lit) {
855 kissat *const solver = closure->solver;
856 unsigned idx = IDX (lit);
857 bool *scheduled = closure->scheduled + idx;
858 if (*scheduled)
859 return;
860 *scheduled = true;
861 ENQUEUE_FIFO (unsigned, closure->schedule, lit);
862 LOG ("scheduled propagation of merged %s", CLOGREPR (lit));
863}
864
865static unsigned dequeue_next_scheduled_literal (closure *closure) {
866 unsigned res;
868#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
869 kissat *const solver = closure->solver;
870#endif
871 unsigned idx = IDX (res);
872 bool *scheduled = closure->scheduled + idx;
874 *scheduled = false;
875 LOG ("dequeued from schedule %s", CLOGREPR (res));
876 return res;
877}
878
879static bool merge_literals (closure *closure, unsigned lit,
880 unsigned other) {
881 kissat *const solver = closure->solver;
882 KISSAT_assert (!solver->inconsistent);
883 unsigned repr_lit = find_repr (closure, lit);
884 unsigned repr_other = find_repr (closure, other);
885 unsigned *const repr = closure->repr;
886 if (repr_lit == repr_other) {
887 LOG ("already merged %s and %s", LOGREPR (lit, repr),
888 LOGREPR (other, repr));
889 return false;
890 }
891 const value *const values = solver->values;
892 const value lit_value = values[lit];
893 const value other_value = values[other];
894 KISSAT_assert (lit_value == values[repr_lit]);
895 KISSAT_assert (other_value == values[repr_other]);
896 if (lit_value) {
897 if (lit_value == other_value) {
898 LOG ("not merging %s and %s assigned to the same value",
899 LOGREPR (lit, repr), LOGREPR (other, repr));
900 return false;
901 }
902 if (lit_value == -other_value) {
903 LOG ("merging inconsistently assigned %s and %s", LOGREPR (lit, repr),
904 LOGREPR (other, repr));
905 solver->inconsistent = true;
908 return false;
909 }
910 KISSAT_assert (!other_value);
911 LOG ("merging assigned %s and unassigned %s", LOGREPR (lit, repr),
912 LOGREPR (other, repr));
913 const unsigned unit = (lit_value < 0) ? NOT (other) : other;
914 (void) learn_congruence_unit (closure, unit);
915 return false;
916 }
917 if (!lit_value && other_value) {
918 LOG ("merging unassigned %s and assigned %s", LOGREPR (lit, repr),
919 LOGREPR (other, repr));
920 const unsigned unit = (other_value < 0) ? NOT (lit) : lit;
921 (void) learn_congruence_unit (closure, unit);
922 return false;
923 }
924 unsigned smaller = repr_lit;
925 unsigned larger = repr_other;
926 if (smaller > larger)
927 SWAP (unsigned, smaller, larger);
929 KISSAT_assert (repr[larger] > smaller);
930 if (repr_lit == NOT (repr_other)) {
931 LOG ("merging clashing %s and %s", LOGREPR (lit, repr),
932 LOGREPR (other, repr));
934 solver->inconsistent = true;
937 return false;
938 }
939 LOG ("merging %s and %s", LOGREPR (lit, repr), LOGREPR (other, repr));
940 const unsigned not_smaller = NOT (smaller);
941 const unsigned not_larger = NOT (larger);
942 repr[larger] = smaller;
943 repr[not_larger] = not_smaller;
944 LOG ("congruence repr[%s] = %s", LOGLIT (larger), LOGLIT (smaller));
945 LOG ("congruence repr[%s] = %s", LOGLIT (not_larger),
946 LOGLIT (not_smaller));
947 add_binary_clause (closure, not_larger, smaller);
948 add_binary_clause (closure, larger, not_smaller);
949 schedule_literal (closure, larger);
950 INC (congruent);
951 return true;
952}
953
954static void connect_occurrence (closure *closure, unsigned lit, gate *g) {
955 gates *const occurrences = closure->occurrences;
956 kissat *const solver = closure->solver;
958 LOG ("connected %s to gate[%zu]", LOGLIT (lit), g->id);
959}
960
961static gate *new_gate (closure *closure, unsigned tag, unsigned hash,
962 unsigned lhs, unsigned arity, const unsigned *lits) {
963 kissat *const solver = closure->solver;
964 const size_t bytes = bytes_gate (arity);
965 gate *g = (gate*)kissat_malloc (solver, bytes);
966#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
967 g->id = closure->gates_added++;
968#endif
969 g->tag = tag;
970 g->hash = hash;
971 g->lhs = lhs;
972 g->arity = arity;
973 g->garbage = false;
974 g->indexed = false;
975 g->marked = false;
976 g->shrunken = false;
977 memcpy (g->rhs, lits, arity * sizeof *lits);
979 connect_occurrence (closure, lit, g);
980 LOGATE (g, "new");
981 index_gate (closure, g);
982 ADD (congruent_arity, arity);
983 INC (congruent_gates);
984 return g;
985}
986
987static gate *find_and_lits (closure *closure, unsigned *hash_ptr,
988 unsigned arity, unsigned *lits, gate *except) {
989 kissat *const solver = closure->solver;
990 sort_lits (solver, arity, lits);
991 const unsigned hash = hash_lits (closure, AND_GATE, arity, lits);
992 gate *g = find_gate (closure, AND_GATE, hash, arity, lits, except);
993 *hash_ptr = hash;
994 if (g) {
995 CLOGANDGATE (g, "found matching");
996 INC (congruent_matched_ands);
997 } else
998 LOGANDGATE (INVALID_GATE_ID, closure->repr, INVALID_LIT, arity, lits,
999 "could not find matching");
1000 return g;
1001}
1002
1003static gate *find_and_gate (closure *closure, unsigned *h, gate *g) {
1004 return find_and_lits (closure, h, g->arity, g->rhs, g);
1005}
1006
1007static gate *new_and_gate (closure *closure, unsigned lhs) {
1008 kissat *const solver = closure->solver;
1009 unsigneds *all_lits = &closure->lits;
1010 unsigneds *rhs_stack = &closure->rhs;
1011 CLEAR_STACK (*rhs_stack);
1012 for (all_stack (unsigned, lit, *all_lits))
1013 if (lhs != lit) {
1014 unsigned not_lit = NOT (lit);
1015 KISSAT_assert (lhs != not_lit);
1016 PUSH_STACK (*rhs_stack, not_lit);
1017 }
1018 const unsigned arity = SIZE_STACK (*rhs_stack);
1019 unsigned *rhs_lits = BEGIN_STACK (*rhs_stack);
1020 KISSAT_assert (arity + 1 == SIZE_STACK (*all_lits));
1021 unsigned hash;
1022 gate *g = find_and_lits (closure, &hash, arity, rhs_lits, 0);
1023 if (g) {
1024 if (merge_literals (closure, g->lhs, lhs))
1025 INC (congruent_ands);
1026 return 0;
1027 }
1028 g = new_gate (closure, AND_GATE, hash, lhs, arity, rhs_lits);
1030 ADD (congruent_arity_ands, arity);
1031 INC (congruent_gates_ands);
1032 return g;
1033}
1034
1035#ifdef CHECKING_OR_PROVING
1036
1037static void copy_literals (kissat *solver, unsigneds *dst,
1038 const unsigneds *src) {
1039 for (all_stack (unsigned, lit, *src))
1040 PUSH_STACK (*dst, lit);
1041 PUSH_STACK (*dst, INVALID_LIT);
1042}
1043
1044static void simplify_and_add_to_proof_chain (kissat *solver, mark *marks,
1045 unsigneds *unsimplified,
1046 unsigneds *clause,
1047 unsigneds *chain) {
1049#ifndef KISSAT_NDEBUG
1050 for (all_stack (unsigned, lit, *unsimplified))
1051 KISSAT_assert (!(marks[lit] & 4));
1052#endif
1053 bool trivial = false;
1054 for (all_stack (unsigned, lit, *unsimplified)) {
1055 mark lit_mark = marks[lit];
1056 if (lit_mark & 4)
1057 continue;
1058 const unsigned not_lit = NOT (lit);
1059 const mark not_lit_mark = marks[not_lit];
1060 if (not_lit_mark & 4) {
1061 trivial = true;
1062 break;
1063 }
1064 lit_mark |= 4;
1065 marks[lit] = lit_mark;
1066 PUSH_STACK (*clause, lit);
1067 }
1068 for (all_stack (unsigned, lit, *clause)) {
1069 mark mark = marks[lit];
1070 KISSAT_assert (mark & 4);
1071 mark &= ~4u;
1072 marks[lit] = mark;
1073 }
1074 if (!trivial) {
1077 copy_literals (solver, chain, clause);
1078 }
1080}
1081
1082#define SIMPLIFY_AND_ADD_TO_PROOF_CHAIN() \
1083 simplify_and_add_to_proof_chain (solver, marks, unsimplified, clause, \
1084 chain)
1085
1087 unsigned lhs1, unsigned lhs2) {
1088 if (lhs1 == lhs2)
1089 return;
1090 kissat *const solver = closure->solver;
1091 if (!kissat_checking_or_proving (solver))
1092 return;
1093 LOG ("starting XOR matching proof chain");
1094 unsigneds *const unsimplified = &closure->unsimplified;
1095 unsigneds *const clause = &solver->clause;
1096 unsigneds *const chain = &closure->chain;
1097 mark *const marks = solver->marks;
1099 KISSAT_assert (EMPTY_STACK (*chain));
1100 KISSAT_assert (g->arity > 1);
1101 const unsigned reduced_arity = g->arity - 1;
1102 for (unsigned i = 0; i != reduced_arity; i++)
1103 PUSH_STACK (*unsimplified, g->rhs[i]);
1104 const unsigned not_lhs1 = NOT (lhs1);
1105 const unsigned not_lhs2 = NOT (lhs2);
1106 do {
1107 const size_t size = SIZE_STACK (*unsimplified);
1108 KISSAT_assert (size < 32);
1109 for (unsigned i = 0; i != 1u << size; i++) {
1110 PUSH_STACK (*unsimplified, not_lhs1);
1111 PUSH_STACK (*unsimplified, lhs2);
1112 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1113 unsimplified->end -= 2;
1114 PUSH_STACK (*unsimplified, lhs1);
1115 PUSH_STACK (*unsimplified, not_lhs2);
1116 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1117 unsimplified->end -= 2;
1118 inc_lits (solver, unsimplified);
1119 }
1121 unsimplified->end--;
1122 } while (!EMPTY_STACK (*unsimplified));
1123 LOG ("finished XOR matching proof chain");
1124}
1125
1126static void delete_proof_chain (closure *closure) {
1127 kissat *const solver = closure->solver;
1128 unsigneds *chain = &closure->chain;
1129 if (!kissat_checking_or_proving (solver)) {
1130 KISSAT_assert (EMPTY_STACK (*chain));
1131 return;
1132 }
1133 if (EMPTY_STACK (*chain))
1134 return;
1135 LOG ("starting deletion of proof chain");
1136 unsigneds *clause = &solver->clause;
1138 const unsigned *start = BEGIN_STACK (*chain);
1139 const unsigned *end = END_STACK (*chain);
1140 const unsigned *p = start;
1141 while (p != end) {
1142 const unsigned lit = *p;
1143 if (lit == INVALID_LIT) {
1144 while (start != p) {
1145 const unsigned other = *start++;
1146 PUSH_STACK (*clause, other);
1147 }
1151 start++;
1152 }
1153 p++;
1154 }
1156 KISSAT_assert (start == end);
1157 CLEAR_STACK (*chain);
1158 LOG ("finished deletion of proof chain");
1159}
1160
1161#else
1162
1163#define add_xor_matching_proof_chain(...) \
1164 do { \
1165 } while (0)
1166
1167#define delete_proof_chain(...) \
1168 do { \
1169 } while (0)
1170
1171#endif
1172
1173static gate *find_xor_lits (closure *closure, unsigned *hash_ptr,
1174 unsigned arity, unsigned *lits, gate *except) {
1175 kissat *const solver = closure->solver;
1176 sort_lits (solver, arity, lits);
1177 const unsigned hash = hash_lits (closure, XOR_GATE, arity, lits);
1178 gate *g = find_gate (closure, XOR_GATE, hash, arity, lits, except);
1179 *hash_ptr = hash;
1180 if (g) {
1181 CLOGXORGATE (g, "found matching");
1182 INC (congruent_matched_xors);
1183 } else
1184 LOGXORGATE (INVALID_GATE_ID, closure->repr, INVALID_LIT, arity, lits,
1185 "tried but did not find matching");
1186 return g;
1187}
1188
1189static gate *find_xor_gate (closure *closure, unsigned *h, gate *g) {
1190 return find_xor_lits (closure, h, g->arity, g->rhs, g);
1191}
1192
1193static gate *new_xor_gate (closure *closure, unsigned lhs) {
1194 kissat *const solver = closure->solver;
1195 unsigneds *all_lits = &closure->lits;
1196 unsigneds *rhs_stack = &closure->rhs;
1197 CLEAR_STACK (*rhs_stack);
1198 const unsigned not_lhs = NOT (lhs);
1199 for (all_stack (unsigned, lit, *all_lits))
1200 if (lit != lhs && lit != not_lhs) {
1202 PUSH_STACK (*rhs_stack, lit);
1203 }
1204 const unsigned arity = SIZE_STACK (*rhs_stack);
1205 unsigned *rhs_lits = BEGIN_STACK (*rhs_stack);
1206 KISSAT_assert (arity + 1 == SIZE_STACK (*all_lits));
1207 unsigned hash;
1208 gate *g = find_xor_lits (closure, &hash, arity, rhs_lits, 0);
1209 if (g) {
1211 if (merge_literals (closure, g->lhs, lhs))
1212 INC (congruent_xors);
1213 if (!solver->inconsistent)
1215 return 0;
1216 }
1217 g = new_gate (closure, XOR_GATE, hash, lhs, arity, rhs_lits);
1219 ADD (congruent_arity_xors, arity);
1220 INC (congruent_gates_xors);
1221 return g;
1222}
1223
1224#ifdef CHECKING_OR_PROVING
1225
1227 unsigned lhs1, unsigned lhs2) {
1228 if (lhs1 == lhs2)
1229 return;
1230 kissat *const solver = closure->solver;
1231 if (!kissat_checking_or_proving (solver))
1232 return;
1233 LOG ("starting ITE matching proof chain");
1234 unsigneds *const unsimplified = &closure->unsimplified;
1235 unsigneds *clause = &solver->clause;
1236 mark *const marks = solver->marks;
1237 unsigneds *chain = &closure->chain;
1239 KISSAT_assert (EMPTY_STACK (*chain));
1240 const unsigned *rhs = g->rhs;
1241 const unsigned cond = rhs[0];
1242 const unsigned not_cond = NOT (cond);
1243 const unsigned not_lhs1 = NOT (lhs1);
1244 const unsigned not_lhs2 = NOT (lhs2);
1245 PUSH_STACK (*unsimplified, lhs1);
1246 PUSH_STACK (*unsimplified, not_lhs2);
1247 PUSH_STACK (*unsimplified, cond);
1248 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1249 unsimplified->end--;
1250 PUSH_STACK (*unsimplified, not_cond);
1251 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1252 unsimplified->end--;
1255 copy_literals (solver, chain, unsimplified);
1257 PUSH_STACK (*unsimplified, not_lhs1);
1258 PUSH_STACK (*unsimplified, lhs2);
1259 PUSH_STACK (*unsimplified, cond);
1260 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1261 unsimplified->end--;
1262 PUSH_STACK (*unsimplified, not_cond);
1263 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1264 unsimplified->end--;
1265 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1267 LOG ("finished ITE matching proof chain");
1268}
1269
1271 kissat *const solver = closure->solver;
1272 if (!kissat_checking_or_proving (solver))
1273 return;
1274 LOG ("starting ITE turned AND supporting binary clauses");
1275 unsigneds *const unsimplified = &closure->unsimplified;
1276 unsigneds *clause = &solver->clause;
1277 unsigneds *chain = &closure->chain;
1278 mark *const marks = solver->marks;
1280 KISSAT_assert (EMPTY_STACK (*chain));
1281 const unsigned not_lhs = NOT (g->lhs);
1282 const unsigned *rhs = g->rhs;
1283 PUSH_STACK (*unsimplified, not_lhs);
1285 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1286 unsimplified->end--;
1288 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1290}
1291
1292#else
1293
1294#define add_ite_matching_proof_chain(...) \
1295 do { \
1296 } while (0)
1297
1298#define add_ite_turned_and_binary_clauses add_ite_matching_proof_chain
1299
1300#endif
1301
1302static bool normalize_ite_lits (kissat *solver, unsigned *lits) {
1303#ifdef KISSAT_NDEBUG
1304 (void) solver;
1305#endif
1306 if (NEGATED (lits[0])) {
1307 lits[0] = NOT (lits[0]);
1308 SWAP (unsigned, lits[1], lits[2]);
1309 }
1310 if (!NEGATED (lits[1]))
1311 return false;
1312 lits[1] = NOT (lits[1]);
1313 lits[2] = NOT (lits[2]);
1314 return true;
1315}
1316
1317static gate *find_ite_lits (closure *closure, unsigned *hash_ptr,
1318 bool *negate_lhs_ptr, unsigned arity,
1319 unsigned *lits, gate *except) {
1320 kissat *const solver = closure->solver;
1321 KISSAT_assert (arity == 3);
1322 LOGITEGATE (INVALID_GATE_ID, closure->repr, INVALID_LIT, lits[0], lits[1],
1323 lits[2], "finding not yet normalized");
1324 bool negate_lhs = normalize_ite_lits (solver, lits);
1325#ifdef LOGGING
1326 if (negate_lhs)
1327 LOG ("normalization forces negation of LHS");
1328 LOGITEGATE (INVALID_GATE_ID, closure->repr, INVALID_LIT, lits[0], lits[1],
1329 lits[2], "normalized");
1330#endif
1331 *negate_lhs_ptr = negate_lhs;
1332 const unsigned hash = hash_lits (closure, ITE_GATE, arity, lits);
1333 gate *g = find_gate (closure, ITE_GATE, hash, arity, lits, except);
1334 *hash_ptr = hash;
1335 if (g) {
1336 CLOGITEGATE (g, "found matching");
1337 INC (congruent_matched_ites);
1338 } else
1339 LOGITEGATE (INVALID_GATE_ID, closure->repr, INVALID_LIT, lits[0],
1340 lits[1], lits[2], "tried but did not find matching");
1341 return g;
1342}
1343
1344static gate *find_ite_gate (closure *closure, unsigned *h,
1345 bool *negate_lhs_ptr, gate *g) {
1346 return find_ite_lits (closure, h, negate_lhs_ptr, g->arity, g->rhs, g);
1347}
1348
1349static gate *new_ite_gate (closure *closure, unsigned lhs, unsigned cond,
1350 unsigned then_lit, unsigned else_lit) {
1351 kissat *const solver = closure->solver;
1352 const unsigned not_then_lit = NOT (then_lit);
1353 if (else_lit == not_then_lit) {
1354#ifdef LOGGING
1355 if (NEGATED (then_lit))
1356 LOG ("skipping ternary XOR gate %s := %s ^ %s", LOGLIT (lhs),
1357 LOGLIT (cond), LOGLIT (not_then_lit));
1358 else
1359 LOG ("skipping ternary XOR gate %s := %s ^ %s", LOGLIT (NOT (lhs)),
1360 LOGLIT (cond), LOGLIT (then_lit));
1361#endif
1362 return 0;
1363 }
1364 if (else_lit == then_lit) {
1365 LOG ("found trivial ITE gate %s := %s ? %s : %s", LOGLIT (lhs),
1366 LOGLIT (cond), LOGLIT (then_lit), LOGLIT (else_lit));
1367 if (merge_literals (closure, lhs, then_lit))
1368 INC (congruent_trivial_ite);
1369 return 0;
1370 }
1371 unsigneds *rhs_stack = &closure->rhs;
1372 CLEAR_STACK (*rhs_stack);
1373 PUSH_STACK (*rhs_stack, cond);
1374 PUSH_STACK (*rhs_stack, then_lit);
1375 PUSH_STACK (*rhs_stack, else_lit);
1376 KISSAT_assert (SIZE_STACK (*rhs_stack) == 3);
1377 const unsigned arity = 3;
1378 unsigned *rhs_lits = BEGIN_STACK (*rhs_stack);
1379 bool negate_lhs;
1380 unsigned hash;
1381 gate *g = find_ite_lits (closure, &hash, &negate_lhs, arity, rhs_lits, 0);
1382 if (g) {
1383 if (negate_lhs)
1384 lhs = NOT (lhs);
1386 if (merge_literals (closure, g->lhs, lhs))
1387 INC (congruent_ites);
1388 if (!solver->inconsistent)
1390 return 0;
1391 }
1392 if (negate_lhs)
1393 lhs = NOT (lhs);
1394 g = new_gate (closure, ITE_GATE, hash, lhs, arity, rhs_lits);
1396 INC (congruent_gates_ites);
1397 return g;
1398}
1399
1400static void mark_gate_as_garbage (closure *closure, gate *g) {
1401 kissat *const solver = closure->solver;
1402 KISSAT_assert (!g->garbage);
1403 g->garbage = true;
1404 LOGATE (g, "marked as garbage");
1406}
1407
1408static void shrink_gate (closure *closure, gate *g,
1409 const unsigned *new_end_rhs) {
1410 unsigned *const rhs = g->rhs;
1411 const unsigned old_arity = g->arity;
1412 unsigned *const old_end_rhs = rhs + old_arity;
1413 KISSAT_assert (rhs <= new_end_rhs);
1414 KISSAT_assert (new_end_rhs <= old_end_rhs);
1415 if (new_end_rhs == old_end_rhs)
1416 return;
1417 const unsigned new_arity = new_end_rhs - rhs;
1418 if (!g->shrunken) {
1419 KISSAT_assert (old_end_rhs[-1] != INVALID_LIT);
1420 old_end_rhs[-1] = INVALID_LIT;
1421 g->shrunken = true;
1422 }
1423 g->arity = new_arity;
1424#ifdef LOGGING
1425 kissat *const solver = closure->solver;
1426 LOGATE (g, "shrunken");
1427#else
1428 (void) closure;
1429#endif
1430}
1431
1432static bool skip_and_gate (closure *closure, gate *g) {
1433 KISSAT_assert (g->tag == AND_GATE);
1434 if (g->garbage)
1435 return true;
1436 kissat *const solver = closure->solver;
1437 const value *const values = solver->values;
1438 const unsigned lhs = g->lhs;
1439 const value value_lhs = values[lhs];
1440 if (value_lhs > 0) {
1441 mark_gate_as_garbage (closure, g);
1442 return true;
1443 }
1444 KISSAT_assert (g->arity > 1);
1445 return false;
1446}
1447
1448static bool gate_contains (gate *g, unsigned lit) {
1449 for (all_rhs_literals_in_gate (other, g))
1450 if (lit == other)
1451 return true;
1452 return false;
1453}
1454
1455static bool rewriting_lhs (closure *closure, gate *g, unsigned dst) {
1456#ifndef KISSAT_NDEBUG
1457 kissat *const solver = closure->solver;
1458#endif
1459 if (dst != g->lhs && dst != NOT (g->lhs))
1460 return false;
1461 mark_gate_as_garbage (closure, g);
1462 return true;
1463}
1464
1465static void shrink_and_gate (closure *closure, gate *g,
1466 unsigned *new_end_rhs, unsigned falsifies,
1467 unsigned clashing) {
1468 KISSAT_assert (g->tag == AND_GATE);
1469#ifndef KISSAT_NDEBUG
1470 kissat *const solver = closure->solver;
1471#endif
1472 if (falsifies != INVALID_LIT) {
1473 KISSAT_assert (g->arity);
1474 g->rhs[0] = falsifies;
1475 new_end_rhs = g->rhs + 1;
1476 } else if (clashing != INVALID_LIT) {
1477 KISSAT_assert (1 < g->arity);
1478 g->rhs[0] = clashing;
1479 g->rhs[1] = NOT (clashing);
1480 new_end_rhs = g->rhs + 2;
1481 }
1482 shrink_gate (closure, g, new_end_rhs);
1483}
1484
1485static void update_and_gate (closure *closure, gate *g, unsigned falsifies,
1486 unsigned clashing) {
1487 KISSAT_assert (g->tag == AND_GATE);
1488 bool garbage = true;
1489 kissat *const solver = closure->solver;
1490 if (falsifies != INVALID_LIT || clashing != INVALID_LIT)
1491 (void) learn_congruence_unit (closure, NOT (g->lhs));
1492 else if (g->arity == 1) {
1493 const value value_lhs = VALUE (g->lhs);
1494 if (value_lhs > 0)
1495 (void) learn_congruence_unit (closure, g->rhs[0]);
1496 else if (value_lhs < 0)
1497 (void) learn_congruence_unit (closure, NOT (g->rhs[0]));
1498 else if (merge_literals (closure, g->lhs, g->rhs[0])) {
1499 INC (congruent_unary_ands);
1500 INC (congruent_unary);
1501 }
1502 } else {
1503 unsigned hash;
1504 gate *h = find_and_gate (closure, &hash, g);
1505 if (h) {
1507 if (merge_literals (closure, g->lhs, h->lhs))
1508 INC (congruent_ands);
1509 } else {
1510 remove_gate (closure, g);
1511 g->hash = hash;
1512 index_gate (closure, g);
1513 garbage = false;
1514 }
1515 }
1516 if (garbage && !solver->inconsistent)
1517 mark_gate_as_garbage (closure, g);
1518}
1519
1520static void simplify_and_gate (closure *closure, gate *g) {
1521 if (skip_and_gate (closure, g))
1522 return;
1523 kissat *const solver = closure->solver;
1524 const value *const values = solver->values;
1525 CLOGANDGATE (g, "simplifying");
1526 const unsigned old_arity = g->arity;
1527 unsigned *const rhs = g->rhs;
1528 unsigned *const end_of_rhs = rhs + old_arity;
1529 const unsigned *p = rhs;
1530 unsigned *q = rhs;
1531 unsigned falsifies = INVALID_LIT;
1532 while (p != end_of_rhs) {
1533 const unsigned lit = *p++;
1534 const value value = values[lit];
1535 if (value > 0)
1536 continue;
1537 if (value < 0) {
1538 LOG ("found falsifying literal %s", LOGLIT (lit));
1539 falsifies = lit;
1540 continue;
1541 }
1542 *q++ = lit;
1543 }
1544 shrink_and_gate (closure, g, q, falsifies, INVALID_LIT);
1545 CLOGANDGATE (g, "simplified");
1547 update_and_gate (closure, g, falsifies, INVALID_LIT);
1548 INC (congruent_simplified);
1549 INC (congruent_simplified_ands);
1550}
1551
1552static void rewrite_and_gate (closure *closure, gate *g, unsigned dst,
1553 unsigned src) {
1554 if (skip_and_gate (closure, g))
1555 return;
1556 if (!gate_contains (g, src))
1557 return;
1558 KISSAT_assert (src != INVALID_LIT);
1559 KISSAT_assert (dst != INVALID_LIT);
1560 kissat *const solver = closure->solver;
1561 const value *const values = solver->values;
1562 KISSAT_assert (values[src] == values[dst]);
1563 CLOGANDGATE (g, "rewriting %s by %s in", CLOGREPR (src), CLOGREPR (dst));
1564 const unsigned old_arity = g->arity;
1565 const unsigned not_lhs = NOT (g->lhs);
1566 unsigned *const rhs = g->rhs;
1567 unsigned *const end_of_rhs = rhs + old_arity;
1568 const unsigned *p = rhs;
1569 unsigned *q = rhs;
1570 unsigned falsifies = INVALID_LIT;
1571 unsigned clashing = INVALID_LIT;
1572 const unsigned not_dst = NOT (dst);
1573 unsigned dst_count = 0, not_dst_count = 0;
1574 while (p != end_of_rhs) {
1575 unsigned lit = *p++;
1576 if (lit == src)
1577 lit = dst;
1578 if (lit == not_lhs) {
1579 LOG ("found negated LHS literal %s", LOGLIT (lit));
1580 clashing = lit;
1581 break;
1582 }
1583 const value value = values[lit];
1584 if (value > 0)
1585 continue;
1586 if (value < 0) {
1587 LOG ("found falsifying literal %s", LOGLIT (lit));
1588 falsifies = lit;
1589 break;
1590 }
1591 if (lit == dst) {
1592 if (not_dst_count) {
1593 LOG ("clashing literals %s and %s", LOGLIT (not_dst), LOGLIT (dst));
1594 clashing = not_dst;
1595 break;
1596 }
1597 if (dst_count++)
1598 continue;
1599 }
1600 if (lit == not_dst) {
1601 if (dst_count) {
1602 KISSAT_assert (!not_dst_count);
1603 LOG ("clashing literals %s and %s", LOGLIT (dst), LOGLIT (not_dst));
1604 clashing = dst;
1605 break;
1606 }
1607 KISSAT_assert (!not_dst_count);
1608 not_dst_count++;
1609 }
1610 *q++ = lit;
1611 }
1612 KISSAT_assert (dst_count <= 2);
1613 KISSAT_assert (not_dst_count <= 1);
1614 shrink_and_gate (closure, g, q, falsifies, clashing);
1615 CLOGANDGATE (g, "rewritten");
1617 update_and_gate (closure, g, falsifies, clashing);
1618 INC (congruent_rewritten);
1619 INC (congruent_rewritten_ands);
1620}
1621
1622static bool skip_xor_gate (gate *g) {
1623 KISSAT_assert (g->tag == XOR_GATE);
1624 if (g->garbage)
1625 return true;
1626 KISSAT_assert (g->arity > 1);
1627 return false;
1628}
1629
1630#ifdef CHECKING_OR_PROVING
1631
1633 unsigned pivot) {
1634 kissat *const solver = closure->solver;
1635 if (!kissat_checking_or_proving (solver))
1636 return;
1637 LOG ("starting XOR shrinking proof chain");
1638 unsigneds *clause = &solver->clause;
1640 for (unsigned i = 0; i != g->arity; i++) {
1641 unsigned lit = g->rhs[i];
1642 PUSH_STACK (*clause, lit);
1643 }
1644 const unsigned lhs = g->lhs;
1645 const unsigned not_lhs = NOT (lhs);
1646 PUSH_STACK (*clause, not_lhs);
1647 const unsigned parity = NEGATED (not_lhs);
1648 KISSAT_assert (parity == parity_lits (solver, clause));
1649 const unsigned not_pivot = NOT (pivot);
1650 const size_t size = SIZE_STACK (*clause);
1651 KISSAT_assert (size < 32);
1652 const unsigned end = 1u << size;
1653 for (unsigned i = 0; i != end; i++) {
1654 while (i && parity != parity_lits (solver, clause))
1655 inc_lits (solver, clause);
1656 PUSH_STACK (*clause, pivot);
1659 clause->end--;
1660 PUSH_STACK (*clause, not_pivot);
1663 clause->end--;
1666 PUSH_STACK (*clause, pivot);
1669 clause->end--;
1670 PUSH_STACK (*clause, not_pivot);
1673 clause->end--;
1674 inc_lits (solver, clause);
1675 }
1677 LOG ("finished XOR shrinking proof chain");
1678}
1679
1680#else
1681
1682#define add_xor_shrinking_proof_chain(...) \
1683 do { \
1684 } while (0)
1685#endif
1686
1687static void shrink_xor_gate (closure *closure, gate *g,
1688 unsigned *new_end_rhs) {
1689 KISSAT_assert (g->tag == XOR_GATE);
1690 shrink_gate (closure, g, new_end_rhs);
1691}
1692
1693static void update_xor_gate (closure *closure, gate *g) {
1694 KISSAT_assert (g->tag == XOR_GATE);
1695 kissat *const solver = closure->solver;
1696 bool garbage = true;
1697 if (g->arity == 0)
1698 (void) learn_congruence_unit (closure, NOT (g->lhs));
1699 else if (g->arity == 1) {
1700 const value value_lhs = VALUE (g->lhs);
1701 if (value_lhs > 0)
1702 (void) learn_congruence_unit (closure, g->rhs[0]);
1703 else if (value_lhs < 0)
1704 (void) learn_congruence_unit (closure, NOT (g->rhs[0]));
1705 else if (merge_literals (closure, g->lhs, g->rhs[0])) {
1706 INC (congruent_unary_xors);
1707 INC (congruent_unary);
1708 }
1709 } else {
1710 KISSAT_assert (g->arity > 1);
1711 unsigned hash;
1712 gate *h = find_xor_gate (closure, &hash, g);
1713 if (h) {
1716 if (merge_literals (closure, g->lhs, h->lhs))
1717 INC (congruent_xors);
1718 if (!solver->inconsistent)
1720 } else {
1721 remove_gate (closure, g);
1722 g->hash = hash;
1723 index_gate (closure, g);
1724 garbage = false;
1725 }
1726 }
1727 if (garbage && !solver->inconsistent)
1728 mark_gate_as_garbage (closure, g);
1729}
1730
1731static void simplify_xor_gate (closure *closure, gate *g) {
1732 if (skip_xor_gate (g))
1733 return;
1734 kissat *const solver = closure->solver;
1735 const value *const values = solver->values;
1736 CLOGXORGATE (g, "simplifying");
1737 unsigned *q = g->rhs, *const end_of_rhs = q + g->arity;
1738 unsigned negate = 0;
1739 for (const unsigned *p = q; p != end_of_rhs; p++) {
1740 const unsigned lit = *p;
1742 const value value = values[lit];
1743 if (value > 0)
1744 negate ^= 1;
1745 if (!value)
1746 *q++ = lit;
1747 }
1748 if (negate) {
1749 LOG ("flipping LHS literal %s", LOGLIT (g->lhs));
1750 g->lhs = NOT (g->lhs);
1751 }
1752 shrink_xor_gate (closure, g, q);
1753 update_xor_gate (closure, g);
1754 CLOGXORGATE (g, "simplified");
1756 INC (congruent_simplified);
1757 INC (congruent_simplified_xors);
1758}
1759
1760static void rewrite_xor_gate (closure *closure, gate *g, unsigned dst,
1761 unsigned src) {
1762 if (skip_xor_gate (g))
1763 return;
1764 if (rewriting_lhs (closure, g, dst))
1765 return;
1766 if (!gate_contains (g, src))
1767 return;
1768 kissat *const solver = closure->solver;
1769 CLOGXORGATE (g, "rewriting %s by %s in", CLOGREPR (src), CLOGREPR (dst));
1770 const value *const values = solver->values;
1771 unsigned *q = g->rhs, *end_of_rhs = q + g->arity;
1772 unsigned original_dst_negated = NEGATED (dst);
1773 unsigned negate = original_dst_negated;
1774 unsigned dst_count = 0;
1775 dst = STRIP (dst);
1776 for (const unsigned *p = q; p != end_of_rhs; p++) {
1777 unsigned lit = *p;
1779 if (lit == src)
1780 lit = dst;
1781 const value value = values[lit];
1782 if (value > 0)
1783 negate ^= 1;
1784 if (value)
1785 continue;
1786 if (lit == dst)
1787 dst_count++;
1788 *q++ = lit;
1789 }
1790 if (negate) {
1791 LOG ("flipping LHS literal %s", LOGLIT (g->lhs));
1792 g->lhs = NOT (g->lhs);
1793 }
1794 KISSAT_assert (dst_count <= 2);
1795 if (dst_count == 2) {
1796 CLOGXORGATE (g, "literals %s and %s were both in", LOGLIT (src),
1797 LOGLIT (dst));
1798 end_of_rhs = q;
1799 q = g->rhs;
1800 for (const unsigned *p = q; p != end_of_rhs; p++) {
1801 const unsigned lit = *p;
1802 if (lit != dst)
1803 *q++ = lit;
1804 }
1805 KISSAT_assert (q + 2 == end_of_rhs);
1806 }
1807 shrink_xor_gate (closure, g, q);
1808 CLOGXORGATE (g, "rewritten");
1809 if (dst_count > 1)
1811 update_xor_gate (closure, g);
1812 if (!g->garbage && !solver->inconsistent && original_dst_negated &&
1813 dst_count == 1) {
1814 KISSAT_assert (!NEGATED (dst));
1815 connect_occurrence (closure, dst, g);
1816 }
1818 INC (congruent_rewritten);
1819 INC (congruent_rewritten_xors);
1820}
1821
1822static bool skip_ite_gate (gate *g) {
1823 KISSAT_assert (g->tag == ITE_GATE);
1824 if (g->garbage)
1825 return true;
1826 return false;
1827}
1828
1829static void simplify_ite_gate (closure *closure, gate *g) {
1830 if (skip_ite_gate (g))
1831 return;
1832 kissat *const solver = closure->solver;
1833 const value *const values = solver->values;
1834 CLOGITEGATE (g, "simplifying");
1835 KISSAT_assert (g->arity == 3);
1836 bool garbage = true;
1837 const unsigned lhs = g->lhs;
1838 unsigned *const rhs = g->rhs;
1839 const unsigned cond = rhs[0];
1840 const unsigned then_lit = rhs[1];
1841 const unsigned else_lit = rhs[2];
1842 const value cond_value = values[cond];
1843 if (cond_value > 0) {
1844 if (merge_literals (closure, lhs, then_lit)) {
1845 INC (congruent_unary_ites);
1846 INC (congruent_unary);
1847 }
1848 } else if (cond_value < 0) {
1849 if (merge_literals (closure, lhs, else_lit)) {
1850 INC (congruent_unary_ites);
1851 INC (congruent_unary);
1852 }
1853 } else {
1854 const value then_value = values[then_lit];
1855 const value else_value = values[else_lit];
1856 const unsigned not_lhs = NOT (lhs);
1857 KISSAT_assert (then_value || else_value);
1858 if (then_value > 0 && else_value > 0)
1859 learn_congruence_unit (closure, lhs);
1860 else if (then_value < 0 && else_value < 0)
1861 learn_congruence_unit (closure, not_lhs);
1862 else if (then_value > 0 && else_value < 0) {
1863 if (merge_literals (closure, lhs, cond)) {
1864 INC (congruent_unary_ites);
1865 INC (congruent_unary);
1866 }
1867 } else if (then_value < 0 && else_value > 0) {
1868 const unsigned not_cond = NOT (cond);
1869 if (merge_literals (closure, lhs, not_cond)) {
1870 INC (congruent_unary_ites);
1871 INC (congruent_unary);
1872 }
1873 } else {
1874 KISSAT_assert (!!else_value + !!then_value == 1);
1875 if (then_value > 0) {
1876 KISSAT_assert (!else_value);
1877 g->lhs = not_lhs;
1878 rhs[0] = NOT (cond);
1879 rhs[1] = NOT (else_lit);
1880 } else if (then_value < 0) {
1881 KISSAT_assert (!else_value);
1882 rhs[0] = NOT (cond);
1883 rhs[1] = else_lit;
1884 } else if (else_value > 0) {
1885 KISSAT_assert (!then_value);
1886 g->lhs = not_lhs;
1887 rhs[0] = NOT (then_lit);
1888 rhs[1] = cond;
1889 } else {
1890 KISSAT_assert (else_value < 0);
1891 KISSAT_assert (!then_value);
1892 rhs[0] = cond;
1893 rhs[1] = then_lit;
1894 }
1895 if (rhs[0] > rhs[1])
1896 SWAP (unsigned, rhs[0], rhs[1]);
1897 KISSAT_assert (!g->shrunken);
1898 g->shrunken = true;
1899 rhs[2] = INVALID_LIT;
1900 g->arity = 2;
1901 g->tag = AND_GATE;
1902 KISSAT_assert (rhs[0] < rhs[1]);
1903 KISSAT_assert (rhs[0] != NOT (rhs[1]));
1904 CLOGANDGATE (g, "simplified");
1906 unsigned hash;
1907 gate *h = find_and_gate (closure, &hash, g);
1908 if (h) {
1910 if (merge_literals (closure, g->lhs, h->lhs))
1911 INC (congruent_ands);
1912 } else {
1913 remove_gate (closure, g);
1914 g->hash = hash;
1915 index_gate (closure, g);
1916 garbage = false;
1917 for (all_rhs_literals_in_gate (lit, g))
1918 if (lit != cond && lit != then_lit && lit != else_lit)
1919 connect_occurrence (closure, lit, g);
1920 }
1921 }
1922 }
1923 if (garbage && !solver->inconsistent)
1924 mark_gate_as_garbage (closure, g);
1925 INC (congruent_simplified);
1926 INC (congruent_simplified_ites);
1927}
1928
1929static void rewrite_ite_gate (closure *closure, gate *g, unsigned dst,
1930 unsigned src) {
1931 if (skip_ite_gate (g))
1932 return;
1933 if (!gate_contains (g, src))
1934 return;
1935 kissat *const solver = closure->solver;
1936 CLOGITEGATE (g, "rewriting %s by %s in", CLOGREPR (src), CLOGREPR (dst));
1937 unsigned *const rhs = g->rhs;
1938 KISSAT_assert (g->arity == 3);
1939 const unsigned lhs = g->lhs;
1940 const unsigned cond = rhs[0];
1941 const unsigned then_lit = rhs[1];
1942 const unsigned else_lit = rhs[2];
1943 const unsigned not_lhs = NOT (lhs);
1944 const unsigned not_dst = NOT (dst);
1945 const unsigned not_cond = NOT (cond);
1946 const unsigned not_then_lit = NOT (then_lit);
1947 const unsigned not_else_lit = NOT (else_lit);
1948 unsigned new_tag = AND_GATE;
1949 bool garbage = false;
1950 bool shrink = true;
1951 if (src == cond) {
1952 if (dst == then_lit) {
1953 // then_lit ? then_lit : else_lit
1954 // then_lit & then_lit | !then_lit & else_lit
1955 // then_lit | !then_lit & else_lit
1956 // then_lit | else_lit
1957 // !(!then_lit & !else_lit)
1958 g->lhs = not_lhs;
1959 rhs[0] = not_then_lit;
1960 rhs[1] = not_else_lit;
1961 } else if (not_dst == then_lit) {
1962 // !then_lit ? then_lit : else_lit
1963 // !then_lit & then_lit | then_lit & else_lit
1964 // then_lit & else_lit
1965 rhs[0] = else_lit;
1966 KISSAT_assert (rhs[1] == then_lit);
1967 } else if (dst == else_lit) {
1968 // else_list ? then_lit : else_lit
1969 // else_list & then_lit | !else_list & else_lit
1970 // else_list & then_lit
1971 rhs[0] = else_lit;
1972 KISSAT_assert (rhs[1] == then_lit);
1973 } else if (not_dst == else_lit) {
1974 // !else_list ? then_lit : else_lit
1975 // !else_list & then_lit | else_lit & else_lit
1976 // !else_list & then_lit | else_lit
1977 // then_lit | else_lit
1978 // !(!then_lit & !else_lit)
1979 g->lhs = not_lhs;
1980 rhs[0] = not_then_lit;
1981 rhs[1] = not_else_lit;
1982 } else {
1983 shrink = false;
1984 rhs[0] = dst;
1985 }
1986 } else if (src == then_lit) {
1987 if (dst == cond) {
1988 // cond ? cond : else_lit
1989 // cond & cond | !cond & else_lit
1990 // cond | !cond & else_lit
1991 // cond | else_lit
1992 // !(!cond & !else_lit)
1993 g->lhs = not_lhs;
1994 rhs[0] = not_cond;
1995 rhs[1] = not_else_lit;
1996 } else if (not_dst == cond) {
1997 // cond ? !cond : else_lit
1998 // cond & !cond | !cond & else_lit
1999 // !cond & else_lit
2000 rhs[0] = not_cond;
2001 rhs[1] = else_lit;
2002 } else if (dst == else_lit) {
2003 // cond ? else_lit : else_lit
2004 // else_lit
2005 if (merge_literals (closure, lhs, else_lit)) {
2006 INC (congruent_unary_ites);
2007 INC (congruent_unary);
2008 }
2009 garbage = true;
2010 } else if (not_dst == else_lit) {
2011 // cond ? !else_lit : else_lit
2012 // cond & !else_lit | !cond & else_lit
2013 // cond ^ else_lit
2014 new_tag = XOR_GATE;
2015 KISSAT_assert (rhs[0] == cond);
2016 rhs[1] = else_lit;
2017 } else {
2018 shrink = false;
2019 rhs[1] = dst;
2020 }
2021 } else {
2022 KISSAT_assert (src == else_lit);
2023 if (dst == cond) {
2024 // cond ? then_lit : cond
2025 // cond & then_lit | !cond & cond
2026 // cond & then_lit
2027 KISSAT_assert (rhs[0] == cond);
2028 KISSAT_assert (rhs[1] == then_lit);
2029 } else if (not_dst == cond) {
2030 // cond ? then_lit : !cond
2031 // cond & then_lit | !cond & !cond
2032 // cond & then_lit | !cond
2033 // then_lit | !cond
2034 // !(!then_lit & cond)
2035 g->lhs = not_lhs;
2036 KISSAT_assert (rhs[0] == cond);
2037 rhs[1] = not_then_lit;
2038 } else if (dst == then_lit) {
2039 // cond ? then_lit : then_lit
2040 // then_lit
2041 if (merge_literals (closure, lhs, then_lit)) {
2042 INC (congruent_unary_ites);
2043 INC (congruent_unary);
2044 }
2045 garbage = true;
2046 } else if (not_dst == then_lit) {
2047 // cond ? then_lit : !then_lit
2048 // cond & then_lit | !cond & !then_lit
2049 // !(cond ^ then_lit)
2050 new_tag = XOR_GATE;
2051 g->lhs = not_lhs;
2052 KISSAT_assert (rhs[0] == cond);
2053 KISSAT_assert (rhs[1] == then_lit);
2054 } else {
2055 shrink = false;
2056 rhs[2] = dst;
2057 }
2058 }
2059 if (!garbage) {
2060 if (shrink) {
2061 if (rhs[0] > rhs[1])
2062 SWAP (unsigned, rhs[0], rhs[1]);
2063 if (new_tag == XOR_GATE) {
2064 bool negate_lhs = false;
2065 if (NEGATED (rhs[0])) {
2066 rhs[0] = NOT (rhs[0]);
2067 negate_lhs = !negate_lhs;
2068 }
2069 if (NEGATED (rhs[1])) {
2070 rhs[1] = NOT (rhs[1]);
2071 negate_lhs = !negate_lhs;
2072 }
2073 if (negate_lhs)
2074 g->lhs = NOT (g->lhs);
2075 }
2076 KISSAT_assert (!g->shrunken);
2077 g->shrunken = true;
2078 rhs[2] = INVALID_LIT;
2079 g->arity = 2;
2080 g->tag = new_tag;
2081 KISSAT_assert (rhs[0] < rhs[1]);
2082 KISSAT_assert (rhs[0] != NOT (rhs[1]));
2083 LOGATE (g, "rewritten");
2084 gate *h;
2085 unsigned hash;
2086 if (new_tag == AND_GATE) {
2088 h = find_and_gate (closure, &hash, g);
2089 } else {
2090 KISSAT_assert (new_tag == XOR_GATE);
2092 h = find_xor_gate (closure, &hash, g);
2093 }
2094 if (h) {
2095 garbage = true;
2096 if (new_tag == XOR_GATE)
2098 else
2100 if (merge_literals (closure, g->lhs, h->lhs))
2101 INC (congruent_ands);
2102 if (!solver->inconsistent)
2104 } else {
2105 garbage = false;
2106 remove_gate (closure, g);
2107 g->hash = hash;
2108 index_gate (closure, g);
2109 KISSAT_assert (g->arity == 2);
2110 for (all_rhs_literals_in_gate (lit, g))
2111 if (lit != dst)
2112 if (lit != cond && lit != then_lit && lit != else_lit)
2113 connect_occurrence (closure, lit, g);
2114 if (g->tag == AND_GATE)
2115 for (all_rhs_literals_in_gate (lit, g))
2116 add_binary_clause (closure, NOT (g->lhs), lit);
2117 }
2118 } else {
2119 CLOGITEGATE (g, "rewritten");
2120 KISSAT_assert (rhs[0] != rhs[1]);
2121 KISSAT_assert (rhs[0] != rhs[2]);
2122 KISSAT_assert (rhs[1] != rhs[2]);
2123 KISSAT_assert (rhs[0] != NOT (rhs[1]));
2124 KISSAT_assert (rhs[0] != NOT (rhs[2]));
2125 KISSAT_assert (rhs[1] != NOT (rhs[2]));
2127 unsigned hash;
2128 bool negate_lhs;
2129 gate *h = find_ite_gate (closure, &hash, &negate_lhs, g);
2130 KISSAT_assert (lhs == g->lhs);
2131 KISSAT_assert (not_lhs == NOT (g->lhs));
2132 if (h) {
2133 garbage = true;
2134 unsigned normalized_lhs = negate_lhs ? not_lhs : lhs;
2135 add_ite_matching_proof_chain (closure, h, h->lhs, normalized_lhs);
2136 if (merge_literals (closure, h->lhs, normalized_lhs))
2137 INC (congruent_ites);
2138 if (!solver->inconsistent)
2140 } else {
2141 garbage = false;
2142 remove_gate (closure, g);
2143 if (negate_lhs)
2144 g->lhs = not_lhs;
2145 CLOGITEGATE (g, "normalized");
2146 g->hash = hash;
2147 index_gate (closure, g);
2148 KISSAT_assert (g->arity == 3);
2149 for (all_rhs_literals_in_gate (lit, g))
2150 if (lit != dst)
2151 if (lit != cond && lit != then_lit && lit != else_lit)
2152 connect_occurrence (closure, lit, g);
2153 }
2154 }
2155 }
2156 if (garbage && !solver->inconsistent)
2157 mark_gate_as_garbage (closure, g);
2158 INC (congruent_rewritten);
2159 INC (congruent_rewritten_ites);
2160}
2161
2162static bool simplify_gate (closure *closure, gate *g) {
2163 if (g->tag == AND_GATE)
2164 simplify_and_gate (closure, g);
2165 else if (g->tag == XOR_GATE)
2166 simplify_xor_gate (closure, g);
2167 else
2168 simplify_ite_gate (closure, g);
2169 return !closure->solver->inconsistent;
2170}
2171
2172static bool rewrite_gate (closure *closure, gate *g, unsigned dst,
2173 unsigned src) {
2174 if (g->tag == AND_GATE)
2175 rewrite_and_gate (closure, g, dst, src);
2176 else if (g->tag == XOR_GATE)
2177 rewrite_xor_gate (closure, g, dst, src);
2178 else
2179 rewrite_ite_gate (closure, g, dst, src);
2180 return !closure->solver->inconsistent;
2181}
2182
2184 unsigned offset, size;
2185};
2186
2187typedef struct offsetsize offsetsize;
2188
2189#define RANK_OTHER(A) ((A).lits[1])
2190#define LESS_OTHER(A, B) (RANK_OTHER (A) < RANK_OTHER (B))
2191
2192static bool find_binary (kissat *solver, litpair *binaries,
2193 offsetsize *offsetsize, unsigned lit,
2194 unsigned other) {
2195 KISSAT_assert (lit != other);
2196 if (lit > other)
2197 SWAP (unsigned, lit, other);
2198 size_t l = offsetsize[lit].offset;
2199 size_t r = l + offsetsize[lit].size;
2200 while (l < r) {
2201 const size_t m = (l + r) / 2;
2202 const unsigned tmp = binaries[m].lits[1];
2203 if (tmp < other)
2204 l = m + 1;
2205 else if (tmp > other)
2206 r = m;
2207 else {
2208 KISSAT_assert (binaries[m].lits[0] == lit);
2209 KISSAT_assert (binaries[m].lits[1] == other);
2210#ifdef LOGGING
2211 LOGBINARY (lit, other, "found");
2212#else
2213 (void) solver;
2214#endif
2215 return true;
2216 }
2217 }
2218 return false;
2219}
2220
2221static uint64_t rank_litpair (litpair p) {
2222 uint64_t res = p.lits[0];
2223 res <<= 32;
2224 res += p.lits[1];
2225 return res;
2226}
2227
2228static void extract_binaries (closure *closure) {
2229 kissat *const solver = closure->solver;
2230 if (!GET_OPTION (congruencebinaries))
2231 return;
2232 START (extractbinaries);
2233 litpair *binaries = BEGIN_STACK (closure->binaries);
2235 CALLOC (struct offsetsize, offsetsize, LITS);
2236 {
2238 litpair *p = binaries;
2239 while (p != end) {
2240 litpair *q = p + 1;
2241 const unsigned lit = p->lits[0];
2242 while (q != end && q->lits[0] == lit)
2243 q++;
2244 const size_t size = q - p;
2245 KISSAT_assert (size), KISSAT_assert (size <= UINT_MAX);
2246 const size_t offset = p - binaries;
2247 if (size < 32)
2249 else
2250 RADIX_SORT (litpair, unsigned, size, p, RANK_OTHER);
2253 p = q;
2254 }
2255 }
2256 clause *last_irredundant = kissat_last_irredundant_clause (solver);
2257 const size_t before = SIZE_STACK (closure->binaries);
2258 size_t extracted = 0, duplicated = 0;
2259 const value *const values = solver->values;
2260 for (all_clauses (d)) {
2261 if (d->garbage)
2262 continue;
2263 if (last_irredundant && last_irredundant < d)
2264 break;
2265 if (d->redundant)
2266 continue;
2267 if (d->size != 3)
2268 continue;
2269 const unsigned *lits = d->lits;
2270 const unsigned a = lits[0];
2271 if (values[a])
2272 continue;
2273 const unsigned b = lits[1];
2274 if (values[b])
2275 continue;
2276 const unsigned c = lits[2];
2277 if (values[c])
2278 continue;
2279 const unsigned not_a = NOT (a);
2280 const unsigned not_b = NOT (b);
2281 const unsigned not_c = NOT (c);
2282 unsigned l = INVALID_LIT, k = INVALID_LIT;
2283 if (find_binary (solver, binaries, offsetsize, not_a, b) ||
2284 find_binary (solver, binaries, offsetsize, not_a, c))
2285 l = b, k = c;
2286 else if (find_binary (solver, binaries, offsetsize, not_b, a) ||
2287 find_binary (solver, binaries, offsetsize, not_b, c))
2288 l = a, k = c;
2289 else if (find_binary (solver, binaries, offsetsize, not_c, a) ||
2290 find_binary (solver, binaries, offsetsize, not_c, b))
2291 l = a, k = b;
2292 else
2293 continue;
2294 LOGCLS (d, "strengthening");
2295 if (!find_binary (solver, binaries, offsetsize, l, k)) {
2296 LOGBINARY (l, k, "strengthened");
2297 add_binary_clause (closure, l, k);
2298 binaries = BEGIN_STACK (closure->binaries);
2299 extracted++;
2300 }
2301 }
2303 {
2305 litpair *added = binaries + before;
2306#ifndef KISSAT_NDEBUG
2307 const size_t after = end - binaries;
2308 KISSAT_assert (after - before == extracted);
2309#endif
2310 RADIX_SORT (litpair, uint64_t, extracted, added, rank_litpair);
2311 litpair *q = added;
2312 unsigned prev_lit = INVALID_LIT;
2313 unsigned prev_other = INVALID_LIT;
2314 for (const litpair *p = q; p != end; p++) {
2315 const litpair pair = *p;
2316 const unsigned lit = pair.lits[0];
2317 const unsigned other = pair.lits[1];
2318 if (p == added || lit != prev_lit || other != prev_other) {
2319 q->lits[0] = lit;
2320 q->lits[1] = other;
2321 prev_lit = lit;
2322 prev_other = other;
2323 q++;
2324 } else {
2325 duplicated++;
2326 LOGBINARY (lit, other, "removing duplicated");
2328 }
2329 }
2331 }
2332 ADD (congruent_binaries, extracted - duplicated);
2333 kissat_verbose (solver, "extracted %zu binaries (plus %zu duplicated)",
2334 extracted, duplicated);
2335 STOP (extractbinaries);
2336}
2337
2338#ifndef INDEX_BINARY_CLAUSES
2339
2340static gate *find_first_and_gate (closure *closure, unsigned lhs,
2341 unsigneds *lits) {
2342 kissat *const solver = closure->solver;
2343 KISSAT_assert (!solver->watching);
2344 mark *const marks = solver->marks;
2345
2346 const unsigned not_lhs = NOT (lhs);
2347 LOG ("trying to find AND gate with first LHS %s", LOGLIT (lhs));
2348 LOG ("negated LHS %s occurs in %u binary clauses", LOGLIT (not_lhs),
2349 closure->negbincount[lhs]);
2350
2351 unsigneds *const marked = &solver->analyzed;
2352 KISSAT_assert (EMPTY_STACK (*marked));
2353
2354 const unsigned arity = SIZE_STACK (*lits) - 1;
2355 unsigned matched = 0;
2356 KISSAT_assert (1 < arity);
2357
2358 watches *watches = &WATCHES (not_lhs);
2359 const watch *const end = END_WATCHES (*watches);
2360 const watch *p = BEGIN_WATCHES (*watches);
2361
2362 while (p != end) {
2363 const watch watch = *p++;
2365 const unsigned other = watch.binary.lit;
2366 const mark tmp = marks[other];
2367 if (tmp) {
2368 matched++;
2369 KISSAT_assert (~(tmp & 2));
2370 marks[other] |= 2;
2371 PUSH_STACK (*marked, other);
2372 }
2373 }
2374
2375 LOG ("found %zu initial LHS candidates", SIZE_STACK (*marked));
2376 if (matched < arity)
2377 return 0;
2378
2379 return new_and_gate (closure, lhs);
2380}
2381
2382static gate *find_remaining_and_gate (closure *closure, unsigned lhs,
2383 unsigneds *lits) {
2384 kissat *const solver = closure->solver;
2385 KISSAT_assert (!solver->watching);
2386 mark *const marks = solver->marks;
2387 const unsigned not_lhs = NOT (lhs);
2388
2389 if (marks[not_lhs] < 2) {
2390 LOG ("skipping no-candidate LHS %s", LOGLIT (lhs));
2391 return NULL;
2392 }
2393
2394 LOG ("trying to find AND gate with remaining LHS %s", LOGLIT (lhs));
2395 LOG ("negated LHS %s occurs times in %u binary clauses", LOGLIT (not_lhs),
2396 closure->negbincount[lhs]);
2397
2398 const unsigned arity = SIZE_STACK (*lits) - 1;
2399 unsigned matched = 0;
2400 KISSAT_assert (1 < arity);
2401
2402 {
2403 watches *watches = &WATCHES (not_lhs);
2404 const watch *const end_watches = END_WATCHES (*watches);
2405 const watch *p = BEGIN_WATCHES (*watches);
2406 while (p != end_watches) {
2407 const watch watch = *p++;
2409 const unsigned other = watch.binary.lit;
2410 mark mark = marks[other];
2411 if (!mark)
2412 continue;
2413 matched++;
2414 if (!(mark & 2))
2415 continue;
2416 KISSAT_assert (!(mark & 4));
2417 marks[other] = mark | 4;
2418 }
2419 }
2420
2421 {
2422 unsigneds *const marked = &solver->analyzed;
2423 KISSAT_assert (!EMPTY_STACK (*marked));
2424 unsigned *const begin_marked = BEGIN_STACK (*marked);
2425 const unsigned *const end_marked = END_STACK (*marked);
2426 unsigned *q = begin_marked;
2427 const unsigned *p = q;
2428 KISSAT_assert (marks[not_lhs] == 3);
2429 while (p != end_marked) {
2430 const unsigned lit = *p++;
2431 if (lit == not_lhs) {
2432 marks[not_lhs] = 1;
2433 continue;
2434 }
2435 mark mark = marks[lit];
2436 KISSAT_assert ((mark & 3) == 3);
2437 if (mark & 4) {
2438 mark = 3;
2439 *q++ = lit;
2440 LOG2 ("keeping LHS candidate %s", LOGLIT (NOT (lit)));
2441 } else {
2442 LOG2 ("dropping LHS candidate %s", LOGLIT (NOT (lit)));
2443 mark = 1;
2444 }
2445 marks[lit] = mark;
2446 }
2447 KISSAT_assert (q != end_marked);
2448 KISSAT_assert (marks[not_lhs] == 1);
2449 SET_END_OF_STACK (*marked, q);
2450 LOG ("after filtering %zu LHS candidates remain", SIZE_STACK (*marked));
2451 }
2452
2453 if (matched < arity)
2454 return 0;
2455
2456 return new_and_gate (closure, lhs);
2457}
2458
2459#endif
2460
2461static inline bool smaller_negated_bin_count (const unsigned *negbincount,
2462 unsigned a, unsigned b) {
2463 unsigned c = negbincount[a];
2464 unsigned d = negbincount[b];
2465 if (c < d)
2466 return true;
2467 if (c > d)
2468 return false;
2469 return a < b;
2470}
2471
2472#define SMALLER_NEGATED_BIN_COUNT(A, B) \
2473 smaller_negated_bin_count (negbincount, A, B)
2474
2475static void sort_lits_by_negbincount (closure *closure, size_t size,
2476 unsigned *lits) {
2477 const unsigned *const negbincount = closure->negbincount;
2478 kissat *const solver = closure->solver;
2479 SORT (unsigned, size, lits, SMALLER_NEGATED_BIN_COUNT);
2480}
2481
2482#ifdef INDEX_BINARY_CLAUSES
2483
2484static unsigned hash_binary (closure *closure, binary_clause *binary) {
2485 return hash_lits (closure, 0, 2, binary->lits);
2486}
2487
2488static bool indexed_binary (closure *closure, unsigned lit,
2489 unsigned other) {
2490 KISSAT_assert (lit != other);
2491#ifdef LOGGING
2492 kissat *const solver = closure->solver;
2493#endif
2494 binary_hash_table *bintab = &closure->bintab;
2495 if (!bintab->count) {
2496 LOG ("did not find binary %s %s", LOGLIT (lit), LOGLIT (other));
2497 return false;
2498 }
2499 KISSAT_assert (bintab->size);
2500 SWAP (unsigned, lit, other);
2501 if (lit > other)
2502 SWAP (unsigned, lit, other);
2503 binary_clause binary = {.lits = {lit, other}};
2504 const unsigned hash = hash_binary (closure, &binary);
2505 const size_t size = bintab->size;
2506 const size_t size2 = bintab->size2;
2507 size_t pos = reduce_hash (hash, size, size2);
2508 binary_clause *table = bintab->table;
2509 unsigned lit0, lit1;
2510 while ((lit1 = table[pos].lits[1])) {
2511 if (lit1 == other) {
2512 lit0 = table[pos].lits[0];
2513 KISSAT_assert (lit0 < other);
2514 if (lit0 == lit) {
2515 LOG ("found binary %s %s", LOGLIT (lit), LOGLIT (other));
2516 return true;
2517 }
2518 }
2519 if (++pos == size)
2520 pos = 0;
2521 }
2522 LOG ("did not find binary %s %s", LOGLIT (lit), LOGLIT (other));
2523 return false;
2524}
2525
2526#endif
2527
2528static void extract_and_gates_with_base_clause (closure *closure,
2529 clause *c) {
2530 KISSAT_assert (!c->garbage);
2531 kissat *const solver = closure->solver;
2532 KISSAT_assert (!solver->inconsistent);
2533 value *values = solver->values;
2534 unsigned arity_limit = MIN (GET_OPTION (congruenceandarity), MAX_ARITY);
2535 const unsigned size_limit = arity_limit + 1;
2536 const unsigned *const negbincount = closure->negbincount;
2537 unsigneds *lits = &closure->lits;
2538 unsigned size = 0, max_negbincount = 0;
2539 CLEAR_STACK (*lits);
2540 for (all_literals_in_clause (lit, c)) {
2541 value value = values[lit];
2542 if (value < 0)
2543 continue;
2544 if (value > 0) {
2545 KISSAT_assert (!solver->level);
2546 LOGCLS (c, "found satisfied %s in", LOGLIT (lit));
2548 return;
2549 }
2550 if (++size > size_limit) {
2551 LOGCLS (c, "too large actual size %u thus skipping", size);
2552 return;
2553 }
2554 const unsigned count = negbincount[lit];
2555 if (!count) {
2556 LOGCLS (c,
2557 "%s negated does not occur in any binary clause "
2558 "thus skipping",
2559 LOGLIT (lit));
2560 return;
2561 }
2562 if (count > max_negbincount)
2563 max_negbincount = count;
2564 PUSH_STACK (*lits, lit);
2565 }
2566 if (size < 3) {
2567 LOGCLS (c, "actual size %u too small thus skipping", size);
2568 return;
2569 }
2570 const unsigned arity = size - 1;
2571 if (max_negbincount < arity) {
2572 LOGCLS (c,
2573 "all literals have less than %u negated occurrences "
2574 "thus skipping",
2575 arity);
2576 return;
2577 }
2578 unsigned *begin_lits = BEGIN_STACK (*lits), *reduced_lits = begin_lits;
2579 LOGCOUNTEDLITS (size, begin_lits, negbincount,
2580 "counted candidate arity %u AND gate base clause", arity);
2581 const unsigned *const end_lits = END_STACK (*lits);
2582#ifndef INDEX_BINARY_CLAUSES
2583 mark *const marks = solver->marks;
2584 unsigneds *marked = &solver->analyzed;
2585 KISSAT_assert (EMPTY_STACK (*marked));
2586#endif
2587 for (unsigned *p = begin_lits; p != end_lits; p++) {
2588 const unsigned lit = *p, count = negbincount[lit];
2589#ifndef INDEX_BINARY_CLAUSES
2590 const unsigned not_lit = NOT (lit);
2591 marks[not_lit] = 1;
2592#endif
2593 if (count < arity) {
2594 if (reduced_lits < p)
2595 *p = *reduced_lits, *reduced_lits++ = lit;
2596 else if (reduced_lits == p)
2597 reduced_lits++;
2598 }
2599 }
2600 KISSAT_assert (reduced_lits < end_lits);
2601 const size_t reduced_size = end_lits - reduced_lits;
2602 KISSAT_assert (reduced_size);
2603 LOGCLS (c, "trying as base arity %u AND gate", arity);
2604 sort_lits_by_negbincount (closure, reduced_size, reduced_lits);
2605#ifdef LOGGING
2606 if (begin_lits < reduced_lits) {
2607 LOGCOUNTEDLITS (reduced_lits - begin_lits, begin_lits, negbincount,
2608 "skipping low occurrence");
2609 LOGCOUNTEDLITS (reduced_size, reduced_lits, negbincount,
2610 "remaining LHS candidate");
2611 } else
2612 LOGCOUNTEDLITS (reduced_size, reduced_lits, negbincount,
2613 "all remain LHS candidate");
2614#endif
2615#ifdef LOGGING
2616 unsigned extracted = 0;
2617#endif
2618#ifndef INDEX_BINARY_CLAUSES
2619 bool first = true;
2620#endif
2621 for (unsigned *p = reduced_lits; p != end_lits; p++) {
2622 if (solver->inconsistent)
2623 break;
2624 if (c->garbage)
2625 break;
2626 const unsigned lhs = *p;
2627 LOG ("trying LHS candidate literal %s with %u negated occurrences",
2628 LOGLIT (lhs), negbincount[lhs]);
2629 KISSAT_assert (arity <= negbincount[lhs]);
2630#ifdef INDEX_BINARY_CLAUSES
2631 const unsigned not_lhs = NOT (lhs);
2632 for (const unsigned *q = begin_lits; q != end_lits; q++)
2633 if (p != q) {
2634 const unsigned rhs = *q, not_rhs = NOT (rhs);
2635 if (!indexed_binary (closure, not_lhs, not_rhs))
2636 goto CONTINUE_WITH_NEXT_LHS;
2637 }
2638 (void) new_and_gate (closure, lhs);
2639#ifdef LOGGING
2640 extracted++;
2641#endif
2642 CONTINUE_WITH_NEXT_LHS:;
2643#else
2644 if (first) {
2645 first = false;
2646 KISSAT_assert (EMPTY_STACK (*marked));
2647 if (find_first_and_gate (closure, lhs, lits)) {
2648#ifdef LOGGING
2649 extracted++;
2650#endif
2651 }
2652 } else if (EMPTY_STACK (*marked)) {
2653 LOG ("early abort AND gate search");
2654 break;
2655 } else if (find_remaining_and_gate (closure, lhs, lits)) {
2656#ifdef LOGGING
2657 extracted++;
2658#endif
2659 }
2660#endif
2661 }
2662#ifndef INDEX_BINARY_CLAUSES
2663 for (const unsigned *p = begin_lits; p != end_lits; p++) {
2664 const unsigned lit = *p, not_lit = NOT (lit);
2665 marks[not_lit] = 0;
2666 }
2667 CLEAR_STACK (*marked);
2668#endif
2669#ifdef LOGGING
2670 if (extracted)
2671 LOGCLS (c, "extracted %u with arity %u AND base", extracted, arity);
2672#endif
2673}
2674
2675#ifdef INDEX_LARGE_CLAUSES
2676
2677static bool valid_large_clause (hash_ref *clause) {
2678 return clause->hash || clause->ref;
2679}
2680
2681static clause *find_indexed_large_clause (closure *closure,
2682 unsigneds *lits) {
2683 kissat *const solver = closure->solver;
2684 size_t size_lits = SIZE_STACK (*lits);
2685 KISSAT_assert (size_lits > 2);
2686#ifdef LOGGING
2687 {
2688 unsigned *begin = BEGIN_STACK (*lits);
2689 unsigned arity = size_lits - 1;
2690 LOGCOUNTEDLITS (size_lits, begin, closure->largecount,
2691 "trying to find arity %u XOR side clause", arity);
2692 }
2693#endif
2694 large_clause_hash_table *clauses = &closure->clauses;
2695 if (!clauses->count)
2696 return 0;
2697 const value *const values = solver->values;
2698 mark *const marks = solver->marks;
2699 unsigneds *sorted = &solver->clause;
2700 KISSAT_assert (EMPTY_STACK (*sorted));
2701 for (all_stack (unsigned, lit, *lits)) {
2702 KISSAT_assert (!values[lit]);
2703 PUSH_STACK (*sorted, lit);
2704 marks[lit] = 1;
2705 }
2706 KISSAT_assert (size_lits == SIZE_STACK (*sorted));
2707 unsigned *begin_sorted = BEGIN_STACK (*sorted);
2708 sort_lits (solver, size_lits, begin_sorted);
2709 const unsigned hash = hash_lits (closure, 0, size_lits, begin_sorted);
2710 const size_t hash_size = clauses->size;
2711 const size_t hash_size2 = clauses->size2;
2712 size_t pos = reduce_hash (hash, hash_size, hash_size2);
2713 hash_ref *table = clauses->table, *hash_ref;
2714 clause *res = 0;
2715 while (valid_large_clause (hash_ref = table + pos)) {
2716 if (hash_ref->hash == hash) {
2718 if (ref == INVALID_REF) {
2719 KISSAT_assert (!hash);
2720 ref = 0;
2721 }
2722 clause *c = kissat_dereference_clause (solver, ref);
2723 for (all_literals_in_clause (other, c))
2724 if (!values[other] && !marks[other])
2725 goto CONTINUE_WITH_NEXT_HASH_BUCKET;
2726 res = c;
2727 break;
2728 }
2729 CONTINUE_WITH_NEXT_HASH_BUCKET:
2730 if (++pos == hash_size)
2731 pos = 0;
2732 }
2733 while (!EMPTY_STACK (*sorted)) {
2734 const unsigned lit = POP_STACK (*sorted);
2735 marks[lit] = 0;
2736 }
2737 if (res)
2738 LOGCLS (res, "found indexed matching XOR side clause");
2739 else
2740 LOG ("no matching XOR side clause found");
2741 return res;
2742}
2743
2744#else
2745
2746static clause *find_large_xor_side_clause (closure *closure,
2747 unsigneds *lits) {
2748 kissat *const solver = closure->solver;
2749 KISSAT_assert (!solver->watching);
2750 const unsigned *const largecount = closure->largecount;
2751 unsigned least_occurring_literal = INVALID_LIT;
2752 unsigned count_least_occurring = UINT_MAX;
2753 mark *marks = solver->marks;
2754 const size_t size_lits = SIZE_STACK (*lits);
2755#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
2756 const unsigned arity = size_lits - 1;
2757#endif
2758#ifndef KISSAT_NDEBUG
2759 const unsigned count_limit = 1u << (arity - 1);
2760#endif
2761 const value *const values = solver->values;
2762 LOGCOUNTEDLITS (size_lits, BEGIN_STACK (*lits), largecount,
2763 "trying to find arity %u XOR side clause", arity);
2764 for (all_stack (unsigned, lit, *lits)) {
2765 KISSAT_assert (!values[lit]);
2766 marks[lit] = 1;
2767 unsigned count = largecount[lit];
2768 KISSAT_assert (count_limit <= count);
2769 if (count >= count_least_occurring)
2770 continue;
2771 count_least_occurring = count;
2772 least_occurring_literal = lit;
2773 }
2774 clause *res = 0;
2775 KISSAT_assert (least_occurring_literal != INVALID_LIT);
2776 LOG ("searching XOR side clause watched by %s#%u",
2777 LOGLIT (least_occurring_literal), count_least_occurring);
2778 watches *const watches = &WATCHES (least_occurring_literal);
2780 const watch *const end = END_WATCHES (*watches);
2781 while (p != end) {
2782 const watch watch = *p++;
2783 if (watch.type.binary)
2784 break;
2785 const reference ref = watch.large.ref;
2786 clause *const c = kissat_dereference_clause (solver, ref);
2787 if (c->garbage)
2788 continue;
2789 if (c->size < size_lits)
2790 continue;
2791 size_t found = 0;
2792 for (all_literals_in_clause (other, c)) {
2793 const value value = values[other];
2794 if (value < 0)
2795 continue;
2796 if (value > 0) {
2797 LOGCLS (c, "found satisfied %s in", LOGLIT (other));
2800 break;
2801 }
2802 if (marks[other])
2803 found++;
2804 else {
2805 found = UINT_MAX;
2806 break;
2807 }
2808 }
2809 if (found < UINT_MAX && !c->garbage) {
2810 res = c;
2811 break;
2812 }
2813 }
2814 for (all_stack (unsigned, lit, *lits))
2815 marks[lit] = 0;
2816 if (res)
2817 LOGCLS (res, "found matching XOR side");
2818 else
2819 LOG ("no matching XOR side clause found");
2820 return res;
2821}
2822
2823#endif
2824
2825static void extract_xor_gates_with_base_clause (closure *closure,
2826 clause *c) {
2827 KISSAT_assert (!c->garbage);
2828 kissat *const solver = closure->solver;
2829 KISSAT_assert (!solver->inconsistent);
2830 const value *const values = solver->values;
2831 unsigned smallest = INVALID_LIT, largest = INVALID_LIT;
2832 const unsigned arity_limit =
2833 MIN (GET_OPTION (congruencexorarity), MAX_ARITY);
2834 const unsigned size_limit = arity_limit + 1;
2835 unsigned negated = 0, size = 0;
2836 unsigneds *lits = &closure->lits;
2837 CLEAR_STACK (*lits);
2838 bool first = true;
2839 for (all_literals_in_clause (lit, c)) {
2840 const value value = values[lit];
2841 if (value < 0)
2842 continue;
2843 if (value > 0) {
2844 LOGCLS (c, "found satisfied %s in", LOGLIT (lit));
2846 return;
2847 }
2848 if (size == size_limit) {
2849 LOGCLS (c, "size limit %u for XOR base clause exceeded in",
2850 size_limit);
2851 return;
2852 }
2853 if (first) {
2854 largest = smallest = lit;
2855 first = false;
2856 } else {
2857 KISSAT_assert (smallest != INVALID_LIT);
2858 KISSAT_assert (largest != INVALID_LIT);
2859 if (lit < smallest)
2860 smallest = lit;
2861 if (lit > largest) {
2862 if (NEGATED (largest)) {
2863 LOGCLS (c, "not largest literal %s occurs negated in XOR base",
2864 LOGLIT (largest));
2865 return;
2866 }
2867 largest = lit;
2868 }
2869 }
2870 if (NEGATED (lit) && lit < largest) {
2871 LOGCLS (c, "negated literal %s not largest in XOR base",
2872 LOGLIT (lit));
2873 return;
2874 }
2875 if (NEGATED (lit) && negated++) {
2876 LOGCLS (c, "more than one negated literal in XOR base");
2877 return;
2878 }
2879 PUSH_STACK (*lits, lit);
2880 size++;
2881 }
2882 KISSAT_assert (size == SIZE_STACK (*lits));
2883 if (size < 3) {
2884 LOGCLS (c, "short XOR base clause");
2885 return;
2886 }
2887 const unsigned arity = size - 1;
2888 const unsigned needed_clauses = 1u << (arity - 1);
2889 const unsigned *const largecount = closure->largecount;
2890 for (all_stack (unsigned, lit, *lits))
2891 for (unsigned sign = 0; sign != 2; sign++, lit = NOT (lit)) {
2892 unsigned count = largecount[lit];
2893 if (count >= needed_clauses)
2894 continue;
2895 LOGCLS (c,
2896 "literal %s in XOR base clause only occurs "
2897 "%u times in large clauses thus skipping",
2898 LOGLIT (lit), count);
2899 return;
2900 }
2901 LOGCLS (c, "trying arity %u XOR base", arity);
2902 KISSAT_assert (smallest != INVALID_LIT);
2903 KISSAT_assert (largest != INVALID_LIT);
2904 const unsigned end = 1u << arity;
2905 KISSAT_assert (negated == parity_lits (solver, lits));
2906#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
2907 unsigned found = 0;
2908#endif
2909 for (unsigned i = 0; i != end; i++) {
2910 while (i && parity_lits (solver, lits) != negated)
2911 inc_lits (solver, lits);
2912 if (i) {
2913#ifdef INDEX_LARGE_CLAUSES
2914 clause *d = find_indexed_large_clause (closure, lits);
2915#else
2916 clause *d = find_large_xor_side_clause (closure, lits);
2917#endif
2918 if (!d)
2919 return;
2921 } else
2923 inc_lits (solver, lits);
2924#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
2925 found++;
2926#endif
2927 }
2928 while (parity_lits (solver, lits) != negated)
2929 inc_lits (solver, lits);
2930 LOGUNSIGNEDS2 (size, BEGIN_STACK (*lits), "back to original");
2931 LOG ("found all needed %u matching clauses:", found);
2932 KISSAT_assert (found == 1u << arity);
2933 if (negated) {
2934 unsigned *p = BEGIN_STACK (*lits), lit;
2935 while (!NEGATED (lit = *p))
2936 p++;
2937 LOG ("flipping RHS literal %s", LOGLIT (lit));
2938 *p = NOT (lit);
2939 }
2940 unsigned extracted = 0;
2941 for (all_stack (unsigned, lhs, *lits)) {
2942 if (!negated)
2943 lhs = NOT (lhs);
2944 gate *g = new_xor_gate (closure, lhs);
2945 if (g)
2946 extracted++;
2947 if (solver->inconsistent)
2948 break;
2949 }
2950 if (!extracted)
2951 LOG ("no arity %u XOR gate extracted", arity);
2952}
2953
2954#ifdef INDEX_BINARY_CLAUSES
2955
2956static void init_bintab (closure *closure) {
2957 kissat *const solver = closure->solver;
2958 size_t limit = BINARY_CLAUSES;
2959 size_t size = 2 * limit;
2960 size_t size2 = 1;
2961 while (size > size2)
2962 size2 *= 2;
2963 KISSAT_assert (!limit || size2 <= 2 * size);
2964 binary_hash_table *bintab = &closure->bintab;
2965 CALLOC (binary_hash_table, bintab->table, size);
2966 bintab->count = 0;
2967 bintab->size = size;
2968 bintab->size2 = size2;
2970 solver, "allocated binary clause hash table of size %zu", size);
2971}
2972
2973#ifndef KISSAT_NDEBUG
2974
2975static bool binaries_hash_table_is_full (binary_hash_table *bintab) {
2976 if (bintab->size == MAX_HASH_TABLE_SIZE)
2977 return false;
2978 if (2 * bintab->count < bintab->size)
2979 return false;
2980 return true;
2981}
2982
2983#endif
2984
2985static void index_binary (closure *closure, unsigned lit, unsigned other) {
2986 KISSAT_assert (lit < other);
2987 binary_hash_table *bintab = &closure->bintab;
2988 KISSAT_assert (!binaries_hash_table_is_full (bintab));
2989 binary_clause binary = {.lits = {lit, other}};
2990 const unsigned hash = hash_binary (closure, &binary);
2991 const size_t size = bintab->size;
2992 const size_t size2 = bintab->size2;
2993 size_t pos = reduce_hash (hash, size, size2);
2994 binary_clause *table = bintab->table;
2995 while (table[pos].lits[1])
2996 if (++pos == size)
2997 pos = 0;
2998 table[pos] = binary;
2999 bintab->count++;
3000#ifdef LOGGING
3001 kissat *const solver = closure->solver;
3002 LOG ("indexed binary %s %s", LOGLIT (lit), LOGLIT (other));
3003#endif
3004}
3005
3006static void reset_bintab (closure *closure) {
3007 kissat *const solver = closure->solver;
3008 binary_hash_table *bintab = &closure->bintab;
3009 DEALLOC (bintab->table, bintab->size);
3010}
3011
3012#endif
3013
3014static void init_and_gate_extraction (closure *closure) {
3015 kissat *const solver = closure->solver;
3016 KISSAT_assert (!solver->watching);
3017 unsigned *negbincount;
3018 CALLOC (unsigned, negbincount, LITS);
3019 litpairs *binaries = &closure->binaries;
3020#ifdef INDEX_BINARY_CLAUSES
3021 init_bintab (closure);
3022#endif
3023 for (all_stack (litpair, pair, *binaries)) {
3024 const unsigned lit = pair.lits[0], other = pair.lits[1];
3025 const unsigned not_lit = NOT (lit), not_other = NOT (other);
3026 negbincount[not_lit]++, negbincount[not_other]++;
3027 kissat_watch_binary (solver, lit, other);
3028#ifdef INDEX_BINARY_CLAUSES
3029 index_binary (closure, lit, other);
3030#endif
3031 }
3032#ifndef KISSAT_QUIET
3033 size_t connected = SIZE_STACK (*binaries);
3034 kissat_very_verbose (solver, "connected %zu binary clauses", connected);
3035#endif
3036 closure->negbincount = negbincount;
3037}
3038
3039static void reset_and_gate_extraction (closure *closure) {
3040 kissat *const solver = closure->solver;
3043#ifdef INDEX_BINARY_CLAUSES
3044 reset_bintab (closure);
3045#endif
3046}
3047
3048#ifdef INDEX_LARGE_CLAUSES
3049
3050static void init_large_clauses (closure *closure, size_t expected) {
3051 kissat *const solver = closure->solver;
3052 size_t size = 2 * expected;
3053 size_t size2 = 1;
3054 while (size > size2)
3055 size2 *= 2;
3056 KISSAT_assert (!expected || size2 <= 2 * size);
3057 large_clause_hash_table *clauses = &closure->clauses;
3058 CALLOC (large_clause_hash_table, clauses->table, size);
3059 clauses->count = 0;
3060 clauses->size = size;
3061 clauses->size2 = size2;
3063 solver, "allocated large clause hash table of size %zu", size);
3064}
3065
3066#ifndef KISSAT_NDEBUG
3067
3068static bool large_clause_hash_table_is_full (closure *closure) {
3069 if (closure->clauses.size == MAX_HASH_TABLE_SIZE)
3070 return false;
3071 if (2 * closure->clauses.count < closure->clauses.size)
3072 return false;
3073 return true;
3074}
3075
3076#endif
3077
3078static void index_large_clause (closure *closure, reference ref) {
3079 KISSAT_assert (!large_clause_hash_table_is_full (closure));
3080 kissat *const solver = closure->solver;
3081 clause *c = kissat_dereference_clause (solver, ref);
3082 const value *const values = solver->values;
3083 unsigneds *lits = &closure->lits;
3084 CLEAR_STACK (*lits);
3085 for (all_literals_in_clause (lit, c))
3086 if (!values[lit])
3087 PUSH_STACK (*lits, lit);
3088 const size_t size_lits = SIZE_STACK (*lits);
3089 unsigned *begin_lits = BEGIN_STACK (*lits);
3090 KISSAT_assert (3 <= size_lits);
3091 sort_lits (solver, size_lits, begin_lits);
3092 const unsigned hash = hash_lits (closure, 0, size_lits, begin_lits);
3093 large_clause_hash_table *clauses = &closure->clauses;
3094 if (!hash && !ref) {
3095 ref = INVALID_REF;
3096 KISSAT_assert (ref);
3097 }
3098 const size_t hash_size = clauses->size;
3099 const size_t hash_size2 = clauses->size2;
3100 size_t pos = reduce_hash (hash, hash_size, hash_size2);
3101 hash_ref *table = clauses->table, *clause;
3102 while (valid_large_clause (clause = table + pos))
3103 if (++pos == hash_size)
3104 pos = 0;
3105 clause->hash = hash;
3106 clause->ref = ref;
3107 KISSAT_assert (valid_large_clause (clause));
3108 clauses->count++;
3109 LOGCLS (c, "indexed");
3110}
3111
3112static void reset_large_clauses (closure *closure) {
3113 large_clause_hash_table *clauses = &closure->clauses;
3114 kissat *const solver = closure->solver;
3115 DEALLOC (clauses->table, clauses->size);
3116}
3117
3118#endif
3119
3120static void init_xor_gate_extraction (closure *closure,
3121 references *candidates) {
3122 KISSAT_assert (EMPTY_STACK (*candidates));
3123 kissat *const solver = closure->solver;
3124 KISSAT_assert (!solver->watching);
3125 const unsigned arity_limit = GET_OPTION (congruencexorarity);
3126 const unsigned size_limit = arity_limit + 1;
3127 clause *last_irredundant = kissat_last_irredundant_clause (solver);
3128 const value *const values = solver->values;
3129 unsigned *largecount;
3130 CALLOC (unsigned, largecount, LITS);
3131 for (all_clauses (c)) {
3132 if (c->garbage)
3133 continue;
3134 if (last_irredundant && last_irredundant < c)
3135 break;
3136 if (c->redundant)
3137 continue;
3138 unsigned size = 0;
3139 int continue_counting_next_clause = 0;
3140 for (all_literals_in_clause (lit, c)) {
3141 const value value = values[lit];
3142 if (value < 0)
3143 continue;
3144 if (value > 0) {
3145 LOGCLS (c, "satisfied %s in", LOGLIT (lit));
3147 continue_counting_next_clause = 1;
3148 break;
3149 }
3150 if (size == size_limit) {
3151 continue_counting_next_clause = 1;
3152 break;
3153 }
3154 size++;
3155 }
3156 if(continue_counting_next_clause) {
3157 continue;
3158 }
3159 if (size < 3)
3160 continue;
3161 for (all_literals_in_clause (lit, c))
3162 if (!values[lit])
3163 largecount[lit]++;
3164 reference ref = kissat_reference_clause (solver, c);
3165 PUSH_STACK (*candidates, ref);
3166 }
3167#ifndef KISSAT_QUIET
3168 size_t considered_clauses = IRREDUNDANT_CLAUSES;
3169 size_t original_candidates = SIZE_STACK (*candidates);
3171 solver,
3172 "%zu original candidate XOR base clauses "
3173 "(%.0f%% of %zu irredundant clauses)",
3174 original_candidates,
3175 kissat_percent (original_candidates, considered_clauses),
3176 considered_clauses);
3177#endif
3178 const unsigned counting_rounds = GET_OPTION (congruencexorcounts);
3179 for (unsigned round = 1; round <= counting_rounds; round++) {
3180 size_t removed = 0;
3181 unsigned *new_largecount;
3182 CALLOC (unsigned, new_largecount, LITS);
3183 const reference *const end_candidates = END_STACK (*candidates);
3184 reference *q = BEGIN_STACK (*candidates), *p = q;
3185 while (p != end_candidates) {
3186 const reference ref = *p++;
3187 clause *c = kissat_dereference_clause (solver, ref);
3188 unsigned size = 0;
3189 for (all_literals_in_clause (lit, c))
3190 if (!values[lit])
3191 size++;
3192 KISSAT_assert (3 <= size);
3193 KISSAT_assert (size <= size_limit);
3194 const unsigned arity = size - 1;
3195 const unsigned needed_clauses = 1u << (arity - 1);
3196 for (all_literals_in_clause (lit, c))
3197 if (largecount[lit] < needed_clauses) {
3198 removed++;
3199 goto CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE;
3200 }
3201 for (all_literals_in_clause (lit, c))
3202 if (!values[lit])
3203 new_largecount[lit]++;
3204 *q++ = ref;
3205 CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE:;
3206 }
3207 DEALLOC (largecount, LITS);
3208 largecount = new_largecount;
3209 SET_END_OF_STACK (*candidates, q);
3210 if (!removed)
3211 break;
3212#ifndef KISSAT_QUIET
3213 size_t remaining_candidates = SIZE_STACK (*candidates);
3214 const char *how_often;
3215 char buffer[64];
3216 if (round == 1)
3217 how_often = "once";
3218 else if (round == 2)
3219 how_often = "twice";
3220 else {
3221 sprintf (buffer, "%u times", round);
3222 how_often = buffer;
3223 }
3225 solver,
3226 "%zu XOR base clause candidates remain (%.0f%% "
3227 "original candidates)"
3228 " after counting %s",
3229 remaining_candidates,
3230 kissat_percent (remaining_candidates, original_candidates),
3231 how_often);
3232#endif
3233 }
3234 closure->largecount = largecount;
3235#ifdef INDEX_LARGE_CLAUSES
3236 init_large_clauses (closure, SIZE_STACK (*candidates));
3237#endif
3238 for (all_stack (reference, ref, *candidates)) {
3240#ifdef INDEX_LARGE_CLAUSES
3241 index_large_clause (closure, ref);
3242#endif
3243 }
3244#ifndef KISSAT_QUIET
3245 size_t connected = SIZE_STACK (*candidates);
3246 kissat_very_verbose (solver, "connected %zu large clauses %.0f%%",
3247 connected,
3248 kissat_percent (connected, IRREDUNDANT_CLAUSES));
3249#endif
3250}
3251
3252static void reset_xor_gate_extraction (closure *closure) {
3253 kissat *const solver = closure->solver;
3256#ifdef INDEX_LARGE_CLAUSES
3257 reset_large_clauses (closure);
3258#endif
3259}
3260
3261static void init_ite_gate_extraction (closure *closure,
3262 references *candidates) {
3263 KISSAT_assert (EMPTY_STACK (*candidates));
3264 kissat *const solver = closure->solver;
3265 clause *last_irredundant = kissat_last_irredundant_clause (solver);
3266 const value *const values = solver->values;
3267 unsigned *largecount;
3268 CALLOC (unsigned, largecount, LITS);
3269 references ternary;
3270 INIT_STACK (ternary);
3271 for (all_clauses (c)) {
3272 if (c->garbage)
3273 continue;
3274 if (last_irredundant && last_irredundant < c)
3275 break;
3276 if (c->redundant)
3277 continue;
3278 unsigned size = 0;
3279 int continue_counting_next_clause = 0;
3280 for (all_literals_in_clause (lit, c)) {
3281 const value value = values[lit];
3282 if (value < 0)
3283 continue;
3284 if (value > 0) {
3285 LOGCLS (c, "satisfied %s in", LOGLIT (lit));
3287 continue_counting_next_clause = 1;
3288 break;
3289 }
3290 if (size == 3) {
3291 continue_counting_next_clause = 1;
3292 break;
3293 }
3294 size++;
3295 }
3296 if(continue_counting_next_clause) {
3297 continue;
3298 }
3299 if (size < 3)
3300 continue;
3301 KISSAT_assert (size == 3);
3302 const reference ref = kissat_reference_clause (solver, c);
3303 PUSH_STACK (ternary, ref);
3304 LOGCLS (c, "counting original ITE gate base");
3305 for (all_literals_in_clause (lit, c))
3306 if (!values[lit])
3307 largecount[lit]++;
3308 }
3309#ifndef KISSAT_QUIET
3310 size_t counted = SIZE_STACK (ternary);
3312 "counted %zu ternary ITE clauses "
3313 "(%.0f%% of %" PRIu64 " irredundant clauses)",
3314 counted,
3315 kissat_percent (counted, IRREDUNDANT_CLAUSES),
3317 size_t connected = 0;
3318#endif
3319 for (all_stack (reference, ref, ternary)) {
3320 clause *c = kissat_dereference_clause (solver, ref);
3321 KISSAT_assert (!c->garbage);
3322 unsigned positive = 0, negative = 0, twice = 0;
3323 for (all_literals_in_clause (lit, c)) {
3324 if (values[lit])
3325 continue;
3326 const unsigned not_lit = NOT (lit);
3327 const unsigned count_not_lit = largecount[not_lit];
3328 if (!count_not_lit)
3329 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
3330 const unsigned count_lit = largecount[lit];
3331 KISSAT_assert (count_lit);
3332 if (count_lit > 1 && count_not_lit > 1)
3333 twice++;
3334 if (NEGATED (lit))
3335 negative++;
3336 else
3337 positive++;
3338 }
3339 if (twice < 2)
3340 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
3341#ifndef KISSAT_QUIET
3342 connected++;
3343#endif
3345 if (positive && negative)
3346 PUSH_STACK (*candidates, ref);
3347 CONTINUE_WITH_NEXT_TERNARY_CLAUSE:;
3348 }
3349 RELEASE_STACK (ternary);
3350#ifndef KISSAT_QUIET
3352 "connected %zu ITE clauses "
3353 "(%.0f%% of %" PRIu64 " counted clauses)",
3354 connected, kissat_percent (connected, counted),
3356 size_t size_candidates = SIZE_STACK (*candidates);
3358 "%zu candidates ITE base clauses "
3359 "(%.0f%% of %zu connected)",
3360 size_candidates,
3361 kissat_percent (size_candidates, connected),
3362 connected);
3363#endif
3364 closure->largecount = largecount;
3369}
3370
3371static void reset_ite_gate_extraction (closure *closure) {
3372 kissat *const solver = closure->solver;
3379}
3380
3381static void unmark_all (unsigneds *marked, signed char *marks) {
3382 for (all_stack (unsigned, lit, *marked))
3383 marks[lit] = 0;
3384 CLEAR_STACK (*marked);
3385}
3386
3387#ifdef MERGE_CONDITIONAL_EQUIVALENCES
3388
3389static void copy_conditional_equivalences (kissat *solver, unsigned lit,
3391 litpairs *condbin) {
3392 KISSAT_assert (EMPTY_STACK (*condbin));
3393 const value *const values = solver->values;
3394 const watch *const begin_watches = BEGIN_WATCHES (*watches);
3395 const watch *const end_watches = END_WATCHES (*watches);
3396 for (const watch *p = begin_watches; p != end_watches; p++) {
3397 const watch watch = *p;
3398 if (watch.type.binary)
3399 break;
3400 const unsigned ref = watch.large.ref;
3401 clause *c = kissat_dereference_clause (solver, ref);
3402 unsigned first = INVALID_LIT, second = INVALID_LIT;
3403 for (all_literals_in_clause (other, c)) {
3404 if (values[other])
3405 continue;
3406 if (other == lit)
3407 continue;
3408 if (first == INVALID_LIT)
3409 first = other;
3410 else {
3411 KISSAT_assert (second == INVALID_LIT);
3412 second = other;
3413 }
3414 }
3415 KISSAT_assert (first != INVALID_LIT);
3416 KISSAT_assert (second != INVALID_LIT);
3417 litpair pair;
3418 if (first < second)
3419 pair = (litpair){.lits = {first, second}};
3420 else {
3421 KISSAT_assert (second < first);
3422 pair = (litpair){.lits = {second, first}};
3423 }
3424 LOG ("literal %s conditional binary clause %s %s", LOGLIT (lit),
3425 LOGLIT (first), LOGLIT (second));
3426 PUSH_STACK (*condbin, pair);
3427 }
3428}
3429
3430static bool less_litpair (litpair p, litpair q) {
3431 const unsigned a = p.lits[0], b = q.lits[0];
3432 if (a < b)
3433 return true;
3434 if (a > b)
3435 return false;
3436 const unsigned c = p.lits[1], d = q.lits[1];
3437 return c < d;
3438}
3439
3440#define RADIDX_SORT_PAIR_LIMIT 32
3441
3442static void sort_pairs (kissat *solver, litpairs *pairs) {
3443 const size_t size = SIZE_STACK (*pairs);
3444 if (size < 32)
3445 SORT_STACK (litpair, *pairs, less_litpair);
3446 else
3447 for (int i = 1; i >= 0; i--)
3448 RADIX_STACK (litpair, uint64_t, *pairs, rank_litpair);
3449}
3450
3451static bool find_litpair_second_literal (unsigned lit, const litpair *begin,
3452 const litpair *end) {
3453 const litpair *l = begin, *r = end;
3454 while (l != r) {
3455 const litpair *m = l + (r - l) / 2;
3456 KISSAT_assert (begin <= m), KISSAT_assert (m < end);
3457 unsigned other = m->lits[1];
3458 if (other < lit)
3459 l = m + 1;
3460 else if (other > lit)
3461 r = m;
3462 else
3463 return true;
3464 }
3465 return false;
3466}
3467
3468static void search_condeq (closure *closure, unsigned lit, unsigned pos_lit,
3469 const litpair *pos_begin, const litpair *pos_end,
3470 unsigned neg_lit, const litpair *neg_begin,
3471 const litpair *neg_end, litpairs *condeq) {
3472 kissat *const solver = closure->solver;
3473 KISSAT_assert (neg_lit == NOT (pos_lit));
3474 KISSAT_assert (pos_begin < pos_end);
3475 KISSAT_assert (neg_begin < neg_end);
3476 KISSAT_assert (pos_begin->lits[0] == pos_lit);
3477 KISSAT_assert (neg_begin->lits[0] == neg_lit);
3478 KISSAT_assert (pos_end <= neg_begin || neg_end <= pos_begin);
3479 for (const litpair *p = pos_begin; p != pos_end; p++) {
3480 const unsigned other = p->lits[1];
3481 const unsigned not_other = NOT (other);
3482 if (find_litpair_second_literal (not_other, neg_begin, neg_end)) {
3483 unsigned first, second;
3484 if (NEGATED (pos_lit))
3485 first = neg_lit, second = other;
3486 else
3487 first = pos_lit, second = not_other;
3488 LOG ("found conditional %s equivalence %s = %s", LOGLIT (lit),
3489 LOGLIT (first), LOGLIT (second));
3490 KISSAT_assert (!NEGATED (first));
3491 KISSAT_assert (first < second);
3492 check_ternary (closure, lit, first, NOT (second));
3493 check_ternary (closure, lit, NOT (first), second);
3494 litpair equivalence = {.lits = {first, second}};
3495 PUSH_STACK (*condeq, equivalence);
3496 if (NEGATED (second)) {
3497 litpair inverse_equivalence = {.lits = {NOT (second), NOT (first)}};
3498 PUSH_STACK (*condeq, inverse_equivalence);
3499 } else {
3500 litpair inverse_equivalence = {.lits = {second, first}};
3501 PUSH_STACK (*condeq, inverse_equivalence);
3502 }
3503 }
3504 }
3505#ifndef LOGGING
3506 (void) lit;
3507#endif
3508}
3509
3510static void extract_condeq_pairs (closure *closure, unsigned lit,
3511 litpairs *condbin, litpairs *condeq) {
3512#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
3513 kissat *const solver = closure->solver;
3514#endif
3515 const litpair *const begin = BEGIN_STACK (*condbin);
3516 const litpair *const end = END_STACK (*condbin);
3517 const litpair *pos_begin = begin;
3518 unsigned next_lit;
3519 for (;;) {
3520 if (pos_begin == end)
3521 return;
3522 next_lit = pos_begin->lits[0];
3523 if (!NEGATED (next_lit))
3524 break;
3525 pos_begin++;
3526 }
3527 for (;;) {
3528 KISSAT_assert (pos_begin != end);
3529 KISSAT_assert (next_lit == pos_begin->lits[0]);
3530 KISSAT_assert (!NEGATED (next_lit));
3531 const unsigned pos_lit = next_lit;
3532 const litpair *pos_end = pos_begin + 1;
3533 for (;;) {
3534 if (pos_end == end)
3535 return;
3536 next_lit = pos_end->lits[0];
3537 if (next_lit != pos_lit)
3538 break;
3539 pos_end++;
3540 }
3541 KISSAT_assert (pos_end != end);
3542 KISSAT_assert (next_lit == pos_end->lits[0]);
3543 const unsigned neg_lit = NOT (pos_lit);
3544 if (next_lit != neg_lit) {
3545 if (NEGATED (next_lit)) {
3546 pos_begin = pos_end + 1;
3547 for (;;) {
3548 if (pos_begin == end)
3549 return;
3550 next_lit = pos_begin->lits[0];
3551 if (!NEGATED (next_lit))
3552 break;
3553 pos_begin++;
3554 }
3555 } else
3556 pos_begin = pos_end;
3557 continue;
3558 }
3559 const litpair *const neg_begin = pos_end;
3560 const litpair *neg_end = neg_begin + 1;
3561 while (neg_end != end) {
3562 next_lit = neg_end->lits[0];
3563 if (next_lit != neg_lit)
3564 break;
3565 neg_end++;
3566 }
3567#ifdef LOGGING
3568 if (kissat_logging (solver)) {
3569 for (const litpair *p = pos_begin; p != pos_end; p++)
3570 LOG ("conditional %s binary clause %s %s with positive %s",
3571 LOGLIT (lit), LOGLIT (p->lits[0]), LOGLIT (p->lits[1]),
3572 LOGLIT (pos_lit));
3573 for (const litpair *p = neg_begin; p != neg_end; p++)
3574 LOG ("conditional %s binary clause %s %s with negative %s",
3575 LOGLIT (lit), LOGLIT (p->lits[0]), LOGLIT (p->lits[1]),
3576 LOGLIT (neg_lit));
3577 }
3578#endif
3579 const size_t pos_size = pos_end - pos_begin;
3580 const size_t neg_size = neg_end - neg_begin;
3581 if (pos_size <= neg_size) {
3582 LOG ("searching negation of %zu conditional binary clauses "
3583 "with positive %s in %zu conditional binary clauses with %s",
3584 pos_size, LOGLIT (pos_lit), neg_size, LOGLIT (neg_lit));
3585 search_condeq (closure, lit, pos_lit, pos_begin, pos_end, neg_lit,
3586 neg_begin, neg_end, condeq);
3587 } else {
3588 LOG ("searching negation of %zu conditional binary clauses "
3589 "with negative %s in %zu conditional binary clauses with %s",
3590 neg_size, LOGLIT (neg_lit), pos_size, LOGLIT (pos_lit));
3591 search_condeq (closure, lit, neg_lit, neg_begin, neg_end, pos_lit,
3592 pos_begin, pos_end, condeq);
3593 }
3594 if (neg_end == end)
3595 return;
3596 KISSAT_assert (next_lit == neg_end->lits[0]);
3597 if (NEGATED (next_lit)) {
3598 pos_begin = neg_end + 1;
3599 for (;;) {
3600 if (pos_begin == end)
3601 return;
3602 next_lit = pos_begin->lits[0];
3603 if (!NEGATED (next_lit))
3604 break;
3605 pos_begin++;
3606 }
3607 } else
3608 pos_begin = neg_end;
3609 }
3610}
3611
3612static void find_conditional_equivalences (closure *closure, unsigned lit,
3614 litpairs *condbin,
3615 litpairs *condeq) {
3616 KISSAT_assert (EMPTY_STACK (*condbin));
3617 KISSAT_assert (EMPTY_STACK (*condeq));
3619 kissat *const solver = closure->solver;
3620 copy_conditional_equivalences (solver, lit, watches, condbin);
3621 sort_pairs (solver, condbin);
3622#ifdef LOGGING
3623 if (kissat_logging (solver)) {
3624 for (all_stack (litpair, pair, *condbin))
3625 LOG ("sorted conditional %s binary clause %s %s", LOGLIT (lit),
3626 LOGLIT (pair.lits[0]), LOGLIT (pair.lits[1]));
3627 LOG ("found %zu conditional %s binary clauses", SIZE_STACK (*condbin),
3628 LOGLIT (lit));
3629 }
3630#endif
3631 extract_condeq_pairs (closure, lit, condbin, condeq);
3632 sort_pairs (solver, condeq);
3633#ifdef LOGGING
3634 if (kissat_logging (solver)) {
3635 for (all_stack (litpair, pair, *condeq))
3636 LOG ("sorted conditional %s equivalence %s = %s", LOGLIT (lit),
3637 LOGLIT (pair.lits[0]), LOGLIT (pair.lits[1]));
3638 LOG ("found %zu conditional %s equivalences", SIZE_STACK (*condeq),
3639 LOGLIT (lit));
3640 }
3641#endif
3642}
3643
3644static void merge_condeq (closure *closure, unsigned cond, litpairs *condeq,
3645 litpairs *not_condeq) {
3647 KISSAT_assert (!NEGATED (cond));
3648 const litpair *const begin_condeq = BEGIN_STACK (*condeq);
3649 const litpair *const end_condeq = END_STACK (*condeq);
3650 const litpair *const begin_not_condeq = BEGIN_STACK (*not_condeq);
3651 const litpair *const end_not_condeq = END_STACK (*not_condeq);
3652 const litpair *p = begin_condeq;
3653 const litpair *q = begin_not_condeq;
3654 while (p != end_condeq) {
3655 litpair cond_pair = *p++;
3656 const unsigned lhs = cond_pair.lits[0];
3657 const unsigned then_lit = cond_pair.lits[1];
3658 KISSAT_assert (!NEGATED (lhs));
3659 while (q != end_not_condeq && q->lits[0] < lhs)
3660 q++;
3661 while (q != end_not_condeq && q->lits[0] == lhs) {
3662 litpair not_cond_pair = *q++;
3663 const unsigned else_lit = not_cond_pair.lits[1];
3664 new_ite_gate (closure, lhs, cond, then_lit, else_lit);
3665 if (solver->inconsistent)
3666 return;
3667 }
3668 }
3669}
3670
3671static void extract_ite_gates_of_literal (closure *closure, unsigned lit,
3672 unsigned not_lit,
3673 watches *lit_watches,
3674 watches *not_lit_watches) {
3675#ifndef KISSAT_NDEBUG
3677#endif
3678 litpairs *condbin = closure->condbin;
3679 litpairs *condeq = closure->condeq;
3680 find_conditional_equivalences (closure, lit, lit_watches, condbin + 0,
3681 condeq + 0);
3682 if (EMPTY_STACK (condeq[0]))
3683 goto CLEAN_UP;
3684 find_conditional_equivalences (closure, not_lit, not_lit_watches,
3685 condbin + 1, condeq + 1);
3686 if (EMPTY_STACK (condeq[1]))
3687 goto CLEAN_UP;
3688 if (NEGATED (lit))
3689 merge_condeq (closure, not_lit, condeq + 0, condeq + 1);
3690 else
3691 merge_condeq (closure, lit, condeq + 1, condeq + 0);
3692CLEAN_UP:
3693 CLEAR_STACK (condbin[0]);
3694 CLEAR_STACK (condbin[1]);
3695 CLEAR_STACK (condeq[0]);
3696 CLEAR_STACK (condeq[1]);
3697}
3698
3699static void extract_ite_gates_of_variable (closure *closure, unsigned idx) {
3700 kissat *const solver = closure->solver;
3701 const unsigned lit = LIT (idx);
3702 const unsigned not_lit = NOT (lit);
3703 watches *lit_watches = &WATCHES (lit);
3704 watches *not_lit_watches = &WATCHES (not_lit);
3705 const size_t size_lit_watches = SIZE_WATCHES (*lit_watches);
3706 const size_t size_not_lit_watches = SIZE_WATCHES (*not_lit_watches);
3707 if (size_lit_watches <= size_not_lit_watches) {
3708 if (size_lit_watches > 1)
3709 extract_ite_gates_of_literal (closure, lit, not_lit, lit_watches,
3710 not_lit_watches);
3711 } else {
3712 if (size_not_lit_watches > 1)
3713 extract_ite_gates_of_literal (closure, not_lit, lit, not_lit_watches,
3714 lit_watches);
3715 }
3716}
3717
3718#else
3719
3720static void mark_third_literal_in_ternary_clauses (
3721 kissat *solver, const value *const values, unsigneds *marked,
3722 mark *marks, unsigned a, unsigned b) {
3723 KISSAT_assert (!solver->watching);
3724 KISSAT_assert (EMPTY_STACK (*marked));
3725 watches *a_watches = &WATCHES (a);
3726 watches *b_watches = &WATCHES (b);
3727 const size_t size_a = SIZE_WATCHES (*a_watches);
3728 const size_t size_b = SIZE_WATCHES (*b_watches);
3729 watches *watches = size_a <= size_b ? a_watches : b_watches;
3730 const watch *const begin = BEGIN_WATCHES (*watches);
3731 const watch *const end = END_WATCHES (*watches);
3732 for (const watch *p = begin; p != end; p++) {
3733 const watch watch = *p;
3735 const reference ref = watch.large.ref;
3736 clause *c = kissat_dereference_clause (solver, ref);
3737 KISSAT_assert (!c->garbage);
3738 unsigned third = INVALID_LIT, found = 0;
3739 for (all_literals_in_clause (lit, c)) {
3740 if (values[lit])
3741 continue;
3742 if (lit == a || lit == b) {
3743 found++;
3744 continue;
3745 }
3746 if (third != INVALID_LIT)
3747 goto NEXT_WATCH;
3748 third = lit;
3749 }
3750 KISSAT_assert (found <= 2);
3751 if (found < 2)
3752 goto NEXT_WATCH;
3753 KISSAT_assert (third != INVALID_LIT);
3754 if (third == INVALID_LIT)
3755 goto NEXT_WATCH;
3756 if (marks[third])
3757 goto NEXT_WATCH;
3758 LOGCLS (c, "marking %s as third literal in", LOGLIT (third));
3759 PUSH_STACK (*marked, third);
3760 marks[third] = 1;
3761 NEXT_WATCH:;
3762 }
3763}
3764
3765static void extract_ite_gate (closure *closure, const value *const values,
3766 mark *const marks, unsigned lhs,
3767 unsigned cond, unsigned then_lit) {
3768 kissat *const solver = closure->solver;
3769 KISSAT_assert (!solver->watching);
3770 unsigned a = NOT (lhs), b = cond;
3771 watches *a_watches = &WATCHES (a);
3772 watches *b_watches = &WATCHES (b);
3773 const size_t size_a = SIZE_WATCHES (*a_watches);
3774 const size_t size_b = SIZE_WATCHES (*b_watches);
3775 watches *watches = size_a <= size_b ? a_watches : b_watches;
3776 const watch *const begin = BEGIN_WATCHES (*watches);
3777 const watch *const end = END_WATCHES (*watches);
3778 for (const watch *p = begin; p != end; p++) {
3779 const watch watch = *p;
3781 const reference ref = watch.large.ref;
3782 clause *c = kissat_dereference_clause (solver, ref);
3783 KISSAT_assert (!c->garbage);
3784 unsigned else_lit = INVALID_LIT, found = 0;
3785 for (all_literals_in_clause (lit, c)) {
3786 if (values[lit])
3787 continue;
3788 if (lit == a || lit == b) {
3789 found++;
3790 continue;
3791 }
3792 if (else_lit != INVALID_LIT)
3793 goto NEXT_WATCH;
3794 else_lit = lit;
3795 }
3796 KISSAT_assert (found <= 2);
3797 if (found < 2)
3798 goto NEXT_WATCH;
3799 KISSAT_assert (else_lit != INVALID_LIT);
3800 unsigned not_else_lit = NOT (else_lit);
3801 if (!marks[not_else_lit])
3802 goto NEXT_WATCH;
3803 LOGCLS (c, "found fourth matching");
3804 check_ite_implied (closure, lhs, cond, then_lit, else_lit);
3805 marks[not_else_lit] = 0;
3806 new_ite_gate (closure, lhs, cond, then_lit, else_lit);
3807 NEXT_WATCH:;
3808 }
3809 SWAP (unsigned, a, b);
3810}
3811
3812static void extract_ite_gates_with_base_clause (closure *closure,
3813 clause *c) {
3814 KISSAT_assert (!c->garbage);
3815 kissat *const solver = closure->solver;
3816 KISSAT_assert (!solver->inconsistent);
3817 const value *const values = solver->values;
3818 const unsigned *const largecount = closure->largecount;
3819 unsigneds *lits = &closure->lits;
3820 CLEAR_STACK (*lits);
3821 unsigned sum = 0;
3822 for (all_literals_in_clause (lit, c)) {
3823 const value value = values[lit];
3824 if (value < 0)
3825 continue;
3826 if (value > 0) {
3827 LOGCLS (c, "found satisfied %s in", LOGLIT (lit));
3829 return;
3830 }
3831 PUSH_STACK (*lits, lit);
3832 sum ^= lit;
3833 }
3834 const size_t size = SIZE_STACK (*lits);
3835 KISSAT_assert (size <= 3);
3836 if (size < 3)
3837 return;
3838 mark *const marks = solver->marks;
3839 unsigneds *marked = &solver->analyzed;
3840 for (all_stack (unsigned, lhs, *lits)) {
3841 if (NEGATED (lhs))
3842 continue;
3843 if (largecount[lhs] < 2)
3844 continue;
3845 const unsigned not_lhs = NOT (lhs);
3846 if (largecount[not_lhs] < 2)
3847 continue;
3848 for (all_stack (unsigned, not_cond, *lits)) {
3849 if (not_cond == lhs)
3850 continue;
3851 if (!NEGATED (not_cond))
3852 continue;
3853 if (largecount[not_cond] < 2)
3854 continue;
3855 const unsigned cond = NOT (not_cond);
3856 if (largecount[cond] < 2)
3857 continue;
3858 const unsigned not_then_lit = sum ^ lhs ^ not_cond;
3859 const unsigned then_lit = NOT (not_then_lit);
3860 if (!largecount[then_lit])
3861 continue;
3862 LOGCLS (c, "found first ITE gate '%s := %s ? %s : ...' gate base",
3863 LOGLIT (lhs), LOGLIT (cond), LOGLIT (then_lit));
3864 clause *d = find_ternary_clause (solver, not_lhs, not_cond, then_lit);
3865 if (!d)
3866 continue;
3867 LOGCLS (d, "found matching second ITE gate");
3868 mark_third_literal_in_ternary_clauses (solver, values, marked, marks,
3869 lhs, cond);
3870 extract_ite_gate (closure, values, marks, lhs, cond, then_lit);
3871 unmark_all (marked, marks);
3872 }
3873 }
3874}
3875
3876#endif
3877
3878static void extract_and_gates (closure *closure) {
3879 kissat *const solver = closure->solver;
3880 if (!GET_OPTION (congruenceands))
3881 return;
3882 START (extractands);
3883#ifndef KISSAT_QUIET
3884 const statistics *s = &solver->statistics_;
3885 const uint64_t matched_before = s->congruent_matched_ands;
3886 const uint64_t gates_before = s->congruent_gates_ands;
3887#endif
3888 init_and_gate_extraction (closure);
3889 clause *last_irredundant = kissat_last_irredundant_clause (solver);
3890 for (all_clauses (c)) {
3892 break;
3893 if (solver->inconsistent)
3894 break;
3895 if (last_irredundant && last_irredundant < c)
3896 break;
3897 if (c->redundant)
3898 continue;
3899 if (c->garbage)
3900 continue;
3901 extract_and_gates_with_base_clause (closure, c);
3902 }
3903 reset_and_gate_extraction (closure);
3904#ifndef KISSAT_QUIET
3905 const uint64_t matched = s->congruent_matched_ands - matched_before;
3906 const uint64_t extracted = s->congruent_gates_ands - gates_before;
3907 const uint64_t found = matched + extracted;
3908 kissat_phase (solver, "congruence", GET (closures),
3909 "found %" PRIu64 " AND gates (%" PRIu64
3910 " extracted %.0f%% + %" PRIu64 " matched %.0f%%)",
3911 found, extracted, kissat_percent (extracted, found),
3912 matched, kissat_percent (matched, found));
3913#endif
3914 STOP (extractands);
3915}
3916
3917static void extract_xor_gates (closure *closure) {
3918 kissat *const solver = closure->solver;
3919 if (!GET_OPTION (congruencexors))
3920 return;
3921 START (extractxors);
3922 references candidates;
3923 INIT_STACK (candidates);
3924 init_xor_gate_extraction (closure, &candidates);
3925 SHRINK_STACK (candidates);
3926#ifndef KISSAT_QUIET
3927 const statistics *s = &solver->statistics_;
3928 const uint64_t matched_before = s->congruent_matched_xors;
3929 const uint64_t gates_before = s->congruent_gates_xors;
3930#endif
3931 for (all_stack (reference, ref, candidates)) {
3933 break;
3934 if (solver->inconsistent)
3935 break;
3936 clause *c = kissat_dereference_clause (solver, ref);
3937 if (c->garbage)
3938 continue;
3939 extract_xor_gates_with_base_clause (closure, c);
3940 }
3941 reset_xor_gate_extraction (closure);
3942 RELEASE_STACK (candidates);
3943#ifndef KISSAT_QUIET
3944 const uint64_t matched = s->congruent_matched_xors - matched_before;
3945 const uint64_t extracted = s->congruent_gates_xors - gates_before;
3946 const uint64_t found = matched + extracted;
3947 kissat_phase (solver, "congruence", GET (closures),
3948 "found %" PRIu64 " XOR gates (%" PRIu64
3949 " extracted %.0f%% + %" PRIu64 " matched %.0f%%)",
3950 found, extracted, kissat_percent (extracted, found),
3951 matched, kissat_percent (matched, found));
3952#endif
3953 STOP (extractxors);
3954}
3955
3956static void extract_ite_gates (closure *closure) {
3957 kissat *const solver = closure->solver;
3958 if (!GET_OPTION (congruenceites))
3959 return;
3960 START (extractites);
3961 references candidates;
3962 INIT_STACK (candidates);
3963 init_ite_gate_extraction (closure, &candidates);
3964#ifndef KISSAT_QUIET
3965 const statistics *s = &solver->statistics_;
3966 const uint64_t matched_before = s->congruent_matched_ites;
3967 const uint64_t gates_before = s->congruent_gates_ites;
3968#endif
3969#ifdef MERGE_CONDITIONAL_EQUIVALENCES
3970 for (all_variables (idx))
3971 if (ACTIVE (idx)) {
3972 extract_ite_gates_of_variable (closure, idx);
3973 if (solver->inconsistent)
3974 break;
3975 }
3976#else
3977 for (all_stack (reference, ref, candidates)) {
3979 break;
3980 if (solver->inconsistent)
3981 break;
3982 clause *c = kissat_dereference_clause (solver, ref);
3983 if (c->garbage)
3984 continue;
3985 extract_ite_gates_with_base_clause (closure, c);
3986 }
3987#endif
3988 reset_ite_gate_extraction (closure);
3989 RELEASE_STACK (candidates);
3990#ifndef KISSAT_QUIET
3991 const uint64_t matched = s->congruent_matched_ites - matched_before;
3992 const uint64_t extracted = s->congruent_gates_ites - gates_before;
3993 const uint64_t found = matched + extracted;
3994 kissat_phase (solver, "congruence", GET (closures),
3995 "found %" PRIu64 " ITE gates (%" PRIu64
3996 " extracted %.0f%% + %" PRIu64 " matched %.0f%%)",
3997 found, extracted, kissat_percent (extracted, found),
3998 matched, kissat_percent (matched, found));
3999#endif
4000 STOP (extractites);
4001}
4002
4003static void init_extraction (closure *closure) {
4004 kissat *const solver = closure->solver;
4006}
4007
4008static void reset_extraction (closure *closure) {
4009 kissat *const solver = closure->solver;
4012}
4013
4014static void extract_gates (closure *closure) {
4015 kissat *const solver = closure->solver;
4016 START (extract);
4017 KISSAT_assert (!solver->level);
4018#ifndef KISSAT_QUIET
4019 const statistics *s = &solver->statistics_;
4020 const uint64_t before = s->congruent_gates + s->congruent_matched;
4021#endif
4022 init_extraction (closure);
4023 extract_binaries (closure);
4024 KISSAT_assert (!solver->inconsistent);
4025 extract_and_gates (closure);
4026 if (!solver->inconsistent && !TERMINATED (congruence_terminated_4)) {
4027 extract_xor_gates (closure);
4028 if (!solver->inconsistent && !TERMINATED (congruence_terminated_5))
4029 extract_ite_gates (closure);
4030 }
4031 reset_extraction (closure);
4032#ifndef KISSAT_QUIET
4033 const uint64_t after = s->congruent_gates + s->congruent_matched;
4034 const uint64_t found = after - before;
4035 kissat_phase (solver, "congruence", GET (closures),
4036 "found %" PRIu64 " gates (%.2f%% variables)", found,
4037 kissat_percent (found, solver->active));
4038#endif
4039 STOP (extract);
4040}
4041
4042static void find_units (closure *closure) {
4043 kissat *const solver = closure->solver;
4044 KISSAT_assert (solver->watching);
4045 KISSAT_assert (!solver->inconsistent);
4046 KISSAT_assert (kissat_propagated (solver));
4047 closure->units = solver->propagate;
4048 unsigneds *marked = &solver->analyzed;
4049 mark *const marks = solver->marks;
4050 size_t units = 0;
4051 for (all_variables (idx)) {
4052 RESTART:
4053 if (!ACTIVE (idx))
4054 continue;
4055 unsigned lit = LIT (idx);
4056 for (unsigned sign = 0; sign != 2; sign++, lit++) {
4057 watches *const watches = &WATCHES (lit);
4058 const watch *p = BEGIN_WATCHES (*watches);
4059 const watch *const end = END_WATCHES (*watches);
4060 KISSAT_assert (EMPTY_STACK (*marked));
4061 while (p != end) {
4062 const watch watch = *p++;
4063 if (!watch.type.binary)
4064 break;
4065 const unsigned other = watch.binary.lit;
4066 const unsigned not_other = NOT (other);
4067 if (marks[not_other]) {
4068 LOG ("binary clauses %s %s and %s %s yield unit %s", LOGLIT (lit),
4069 LOGLIT (other), LOGLIT (lit), LOGLIT (not_other),
4070 LOGLIT (lit));
4071 units++;
4072 bool failed = !learn_congruence_unit (closure, lit);
4073 unmark_all (marked, marks);
4074 if (failed)
4075 return;
4076 else
4077 goto RESTART;
4078 }
4079 if (marks[other])
4080 continue;
4081 marks[other] = 1;
4082 PUSH_STACK (*marked, other);
4083 }
4084 unmark_all (marked, marks);
4085 }
4086 }
4087 KISSAT_assert (EMPTY_STACK (*marked));
4088#ifndef KISSAT_QUIET
4089 kissat_very_verbose (solver, "found %zu units", units);
4090#else
4091 (void) units;
4092#endif
4093}
4094
4095static void find_equivalences (closure *closure) {
4096 kissat *const solver = closure->solver;
4097 KISSAT_assert (solver->watching);
4098 KISSAT_assert (!solver->inconsistent);
4099 unsigneds *const marked = &solver->analyzed;
4100 mark *const marks = solver->marks;
4101 KISSAT_assert (EMPTY_STACK (*marked));
4102 for (all_variables (idx)) {
4103 RESTART:
4104 if (!ACTIVE (idx))
4105 continue;
4106 const unsigned lit = LIT (idx);
4107 watches *lit_watches = &WATCHES (lit);
4108 const watch *p = BEGIN_WATCHES (*lit_watches);
4109 const watch *const end_lit_watches = END_WATCHES (*lit_watches);
4110 KISSAT_assert (EMPTY_STACK (*marked));
4111 while (p != end_lit_watches) {
4112 const watch watch = *p++;
4113 if (!watch.type.binary)
4114 break;
4115 const unsigned other = watch.binary.lit;
4116 if (lit > other)
4117 continue;
4118 if (marks[other])
4119 continue;
4120 marks[other] = 1;
4121 PUSH_STACK (*marked, other);
4122 }
4123 if (EMPTY_STACK (*marked))
4124 continue;
4125 const unsigned not_lit = NOT (lit);
4126 watches *not_lit_watches = &WATCHES (not_lit);
4127 p = BEGIN_WATCHES (*not_lit_watches);
4128 const watch *const end_not_lit_watches = END_WATCHES (*not_lit_watches);
4129 while (p != end_not_lit_watches) {
4130 const watch watch = *p++;
4131 if (!watch.type.binary)
4132 break;
4133 const unsigned other = watch.binary.lit;
4134 if (not_lit > other)
4135 continue;
4136 if (lit == other)
4137 continue;
4138 const unsigned not_other = NOT (other);
4139 if (marks[not_other]) {
4140 unsigned lit_repr = find_repr (closure, lit);
4141 unsigned other_repr = find_repr (closure, other);
4142 if (lit_repr != other_repr) {
4143 if (merge_literals (closure, lit, other))
4144 INC (congruent_equivalences);
4145 unmark_all (marked, marks);
4146 if (solver->inconsistent)
4147 return;
4148 else
4149 goto RESTART;
4150 }
4151 }
4152 }
4153 unmark_all (marked, marks);
4154 }
4155 KISSAT_assert (EMPTY_STACK (*marked));
4156#ifndef KISSAT_QUIET
4157 size_t found = SIZE_FIFO (closure->schedule);
4158 kissat_very_verbose (solver, "found %zu equivalences", found);
4159#endif
4160}
4161
4162static bool simplify_gates (closure *closure, unsigned lit) {
4163 kissat *const solver = closure->solver;
4164 LOG ("simplifying gates with RHS literal %s", LOGLIT (lit));
4165 KISSAT_assert (solver->values[lit]);
4166 gates *lit_occurrences = closure->occurrences + lit;
4167 for (all_pointers (gate, g, *lit_occurrences))
4168 if (!simplify_gate (closure, g))
4169 return false;
4170 RELEASE_STACK (*lit_occurrences);
4171 return true;
4172}
4173
4174static bool rewrite_gates (closure *closure, unsigned dst, unsigned src) {
4175 kissat *const solver = closure->solver;
4176 LOG ("rewriting gates with RHS literal %s", LOGLIT (src));
4177 gates *occurrences = closure->occurrences;
4178 gates *src_occurrences = occurrences + src;
4179 gates *dst_occurrences = occurrences + dst;
4180 for (all_pointers (gate, g, *src_occurrences))
4181 if (!rewrite_gate (closure, g, dst, src))
4182 return false;
4183 else if (!g->garbage && gate_contains (g, dst))
4184 PUSH_STACK (*dst_occurrences, g);
4185 RELEASE_STACK (*src_occurrences);
4186 return true;
4187}
4188
4189static bool propagate_unit (closure *closure, unsigned lit) {
4190 kissat *const solver = closure->solver;
4191 LOG ("propagation of congruence unit %s", LOGLIT (lit));
4192 (void) solver;
4193 KISSAT_assert (!solver->inconsistent);
4194 const unsigned not_lit = NOT (lit);
4195 return simplify_gates (closure, lit) && simplify_gates (closure, not_lit);
4196}
4197
4198static bool propagate_equivalence (closure *closure, unsigned lit) {
4199 kissat *const solver = closure->solver;
4200 LOG ("propagation of congruence equivalence %s", CLOGREPR (lit));
4201 KISSAT_assert (!solver->inconsistent);
4202 if (VALUE (lit))
4203 return true;
4204 const unsigned lit_repr = find_repr (closure, lit);
4205 if (solver->inconsistent)
4206 return false;
4207 const unsigned not_lit = NOT (lit);
4208 const unsigned not_lit_repr = NOT (lit_repr);
4209 return rewrite_gates (closure, lit_repr, lit) &&
4210 rewrite_gates (closure, not_lit_repr, not_lit);
4211}
4212
4213static bool propagate_units (closure *closure) {
4214 kissat *const solver = closure->solver;
4215 KISSAT_assert (!solver->inconsistent);
4216 const unsigned_array *const trail = &solver->trail;
4217 while (closure->units != trail->end)
4218 if (!propagate_unit (closure, *closure->units++))
4219 return false;
4220 return true;
4221}
4222
4223static size_t propagate_units_and_equivalences (closure *closure) {
4224 kissat *const solver = closure->solver;
4225 KISSAT_assert (!solver->inconsistent);
4226 START (merge);
4227 unsigned_fifo *schedule = &closure->schedule;
4228 size_t propagated = 0;
4230 propagate_units (closure) && !EMPTY_FIFO (*schedule)) {
4231 propagated++;
4232 unsigned lit = dequeue_next_scheduled_literal (closure);
4233 if (!propagate_equivalence (closure, lit))
4234 break;
4235 }
4236#ifndef KISSAT_QUIET
4237 const size_t units = closure->units - solver->trail.begin;
4238 kissat_very_verbose (solver, "propagated %zu congruence units", units);
4239 kissat_very_verbose (solver, "propagated %zu congruence equivalences",
4240 propagated);
4241#endif
4242 STOP (merge);
4243 return propagated;
4244}
4245
4246#ifndef KISSAT_NDEBUG
4247
4248static void dump_closure_literal (closure *closure, unsigned ilit) {
4249 kissat *const solver = closure->solver;
4250 const int elit = kissat_export_literal (solver, ilit);
4251 printf ("%u(%d)", ilit, elit);
4252 unsigned repr_ilit = find_repr (closure, ilit);
4253 if (repr_ilit != ilit) {
4254 const int repr_elit = kissat_export_literal (solver, repr_ilit);
4255 printf ("[%u(%d)]", repr_ilit, repr_elit);
4256 }
4257 const int value = VALUE (ilit);
4258 KISSAT_assert (!solver->level);
4259 if (value)
4260 printf ("@0=%d", value);
4261}
4262
4263static void dump_units (closure *closure) {
4264 unsigned_array *trail = &closure->solver->trail;
4265 size_t i = 0, propagate = closure->units - trail->begin;
4266 for (all_stack (unsigned, lit, *trail)) {
4267 printf ("trail[%zu] ", i);
4268 dump_closure_literal (closure, lit);
4269 if (i == propagate)
4270 fputs (" <-- next unit to propagate", stdout);
4271 fputc ('\n', stdout);
4272 i++;
4273 }
4274}
4275
4276static void dump_equivalences (closure *closure) {
4277 kissat *const solver = closure->solver;
4278 for (all_variables (idx)) {
4279 unsigned lit = LIT (idx);
4280 unsigned repr = closure->repr[lit];
4281 if (repr != lit)
4282 printf ("repr[%u(%d)] = %u(%d)\n", lit,
4283 kissat_export_literal (solver, lit), repr,
4284 kissat_export_literal (solver, repr));
4285 }
4286}
4287
4288static void dump_gate (closure *closure, gate *g) {
4289 const unsigned tag = g->tag;
4290 const char *str;
4291 switch (tag) {
4292 case AND_GATE:
4293 str = "AND";
4294 break;
4295 case ITE_GATE:
4296 str = "ITE";
4297 break;
4298 case XOR_GATE:
4299 str = "XOR";
4300 break;
4301 default:
4302 str = "UNKNOWN";
4303 break;
4304 }
4305 printf ("%p %s gate[%zu] ", (void *) g, str, g->id);
4306 dump_closure_literal (closure, g->lhs);
4307 fputs (" := ", stdout);
4308 if (g->tag == ITE_GATE) {
4309 dump_closure_literal (closure, g->rhs[0]);
4310 fputs (" ? ", stdout);
4311 dump_closure_literal (closure, g->rhs[1]);
4312 fputs (" : ", stdout);
4313 dump_closure_literal (closure, g->rhs[2]);
4314 } else {
4315 bool first = true;
4316 for (all_rhs_literals_in_gate (rhs, g)) {
4317 if (first)
4318 first = false;
4319 else if (g->tag == AND_GATE)
4320 fputs (" & ", stdout);
4321 else
4322 fputs (" ^ ", stdout);
4323 dump_closure_literal (closure, rhs);
4324 }
4325 }
4326 fputs (g->indexed ? " removed" : " indexed", stdout);
4327 if (g->garbage)
4328 fputs (" garbage", stdout);
4329 fputc ('\n', stdout);
4330}
4331
4332#define LESS_GATE(G, H) ((G)->id < (H)->id)
4333
4334static void dump_gates (closure *closure) {
4335 gates gates;
4336 INIT_STACK (gates);
4337 kissat *const solver = closure->solver;
4338 for (unsigned pos = 0; pos != closure->hash.size; pos++) {
4339 gate *g = closure->hash.table[pos];
4340 if (!g)
4341 continue;
4342 if (g == REMOVED)
4343 continue;
4344 PUSH_STACK (gates, g);
4345 }
4346 SORT_STACK (gate *, gates, LESS_GATE);
4347 for (all_pointers (gate, g, gates))
4348 dump_gate (closure, g);
4349 RELEASE_STACK (gates);
4350}
4351
4352void kissat_dump_closure (closure *closure) {
4353 dump_units (closure);
4354 dump_equivalences (closure);
4355 dump_gates (closure);
4356}
4357
4358#endif
4359
4360static bool find_subsuming_clause (closure *closure, clause *c) {
4361 KISSAT_assert (!c->garbage);
4362 kissat *const solver = closure->solver;
4363 const reference c_ref = kissat_reference_clause (solver, c);
4364 const value *const values = solver->values;
4365 mark *marks = solver->marks;
4366 {
4367 const unsigned *const end_lits = c->lits + c->size;
4368 for (const unsigned *p = c->lits; p != end_lits; p++) {
4369 const unsigned lit = *p;
4370 KISSAT_assert (values[lit] <= 0);
4371 const unsigned repr_lit = find_repr (closure, lit);
4372 const value value_repr_lit = values[repr_lit];
4373 KISSAT_assert (value_repr_lit <= 0);
4374 if (value_repr_lit < 0)
4375 continue;
4376 if (marks[repr_lit])
4377 continue;
4378 KISSAT_assert (!marks[NOT (repr_lit)]);
4379 marks[repr_lit] = 1;
4380 }
4381 }
4382 unsigned least_occurring_literal = INVALID_LIT;
4383 unsigned count_least_occurring = UINT_MAX;
4384 LOGREPRCLS (c, closure->repr, "trying to forward subsume");
4385 clause *subsuming = 0;
4386 for (all_literals_in_clause (lit, c)) {
4387 const unsigned repr_lit = find_repr (closure, lit);
4388 watches *const watches = &WATCHES (repr_lit);
4389 const watch *p = BEGIN_WATCHES (*watches);
4390 const watch *const end = END_WATCHES (*watches);
4391 const size_t count = end - p;
4392 KISSAT_assert (count <= UINT_MAX);
4393 if (count < count_least_occurring) {
4394 count_least_occurring = count;
4395 least_occurring_literal = repr_lit;
4396 }
4397 while (p != end) {
4398 const watch watch = *p++;
4400 const reference d_ref = watch.large.ref;
4401 clause *const d = kissat_dereference_clause (solver, d_ref);
4402 KISSAT_assert (c != d);
4403 KISSAT_assert (!d->garbage);
4404 if (!c->redundant && d->redundant)
4405 continue;
4406 for (all_literals_in_clause (other, d)) {
4407 const value value = values[other];
4408 if (value < 0)
4409 continue;
4411 const unsigned repr_other = find_repr (closure, other);
4412 if (!marks[repr_other])
4413 goto CONTINUE_WITH_NEXT_CLAUSE;
4414 }
4415 subsuming = d;
4416 goto FOUND_SUBSUMING;
4417 CONTINUE_WITH_NEXT_CLAUSE:;
4418 }
4419 }
4420FOUND_SUBSUMING:
4421 for (all_literals_in_clause (lit, c)) {
4422 const unsigned repr_lit = find_repr (closure, lit);
4423 const value value = values[repr_lit];
4424 if (!value)
4425 marks[repr_lit] = 0;
4426 }
4427 if (subsuming) {
4428 LOGREPRCLS (c, closure->repr, "subsumed");
4429 LOGREPRCLS (subsuming, closure->repr, "subsuming");
4431 INC (congruent_subsumed);
4432 return true;
4433 } else {
4434 KISSAT_assert (least_occurring_literal != INVALID_LIT);
4435 KISSAT_assert (count_least_occurring < UINT_MAX);
4436 LOGCLS (c, "forward subsumption failed of");
4437 LOG ("connecting %u occurring %s", count_least_occurring,
4438 LOGLIT (least_occurring_literal));
4439 kissat_connect_literal (solver, least_occurring_literal, c_ref);
4440 return false;
4441 }
4442}
4443
4444struct refsize {
4446 unsigned size;
4447};
4448
4449typedef struct refsize refsize;
4450typedef STACK (refsize) refsizes;
4451
4452#define RANKREFSIZE(REFSIZE) ((REFSIZE).size)
4453
4454static void sort_references_by_clause_size (kissat *solver,
4455 refsizes *candidates) {
4456 RADIX_STACK (refsize, unsigned, *candidates, RANKREFSIZE);
4457}
4458
4459static void forward_subsume_matching_clauses (closure *closure) {
4460 kissat *const solver = closure->solver;
4461 START (matching);
4462 reset_closure (closure);
4463 litpairs binaries;
4464 INIT_STACK (binaries);
4465 kissat_enter_dense_mode (solver, &binaries);
4466 bool *matchable;
4467#ifndef KISSAT_QUIET
4468 unsigned count_matchable = 0;
4469#endif
4470 CALLOC (bool, matchable, VARS);
4471 for (all_variables (idx))
4472 if (ACTIVE (idx)) {
4473 const unsigned lit = LIT (idx);
4474 const unsigned repr = find_repr (closure, lit);
4475 if (lit == repr)
4476 continue;
4477 const unsigned repr_idx = IDX (repr);
4478 if (!matchable[idx]) {
4479 LOG ("matchable %s", LOGVAR (idx));
4480 matchable[idx] = true;
4481#ifndef KISSAT_QUIET
4482 count_matchable++;
4483#endif
4484 }
4485 if (!matchable[repr_idx]) {
4486 LOG ("matchable %s", LOGVAR (repr_idx));
4487 matchable[repr_idx] = true;
4488#ifndef KISSAT_QUIET
4489 count_matchable++;
4490#endif
4491 }
4492 }
4493 kissat_phase (solver, "congruence", GET (closures),
4494 "found %u matchable variables %.0f%%", count_matchable,
4495 kissat_percent (count_matchable, solver->active));
4496 size_t potential = 0;
4497 refsizes candidates;
4498 INIT_STACK (candidates);
4499 clause *last_irredundant = kissat_last_irredundant_clause (solver);
4500 const value *const values = solver->values;
4501 mark *const marks = solver->marks;
4502 unsigneds *marked = &solver->analyzed;
4503 for (all_clauses (c)) {
4504 if (c->garbage)
4505 continue;
4506 if (last_irredundant && last_irredundant < c)
4507 break;
4508 potential++;
4509 bool contains_matchable = false;
4510 KISSAT_assert (EMPTY_STACK (*marked));
4511 LOGREPRCLS (c, closure->repr, "considering");
4512 for (all_literals_in_clause (lit, c)) {
4513 const value value = values[lit];
4514 if (value < 0)
4515 continue;
4516 if (value > 0) {
4517 LOGCLS (c, "satisfied %s in", LOGLIT (lit));
4519 break;
4520 }
4521 if (!contains_matchable) {
4522 const unsigned lit_idx = IDX (lit);
4523 if (matchable[lit_idx])
4524 contains_matchable = true;
4525 }
4526 const unsigned repr = find_repr (closure, lit);
4527 KISSAT_assert (!values[repr]);
4528 if (marks[repr])
4529 continue;
4530 const unsigned not_repr = NOT (repr);
4531 if (marks[not_repr]) {
4532 LOGCLS (c, "matches both %s and %s", CLOGREPR (lit),
4533 LOGLIT (not_repr));
4535 break;
4536 }
4537 marks[repr] = 1;
4538 PUSH_STACK (*marked, repr);
4539 }
4540 const size_t size = SIZE_STACK (*marked);
4541 for (all_stack (unsigned, repr, *marked))
4542 marks[repr] = 0;
4543 CLEAR_STACK (*marked);
4544 if (c->garbage)
4545 continue;
4546 if (!contains_matchable) {
4547 LOGREPRCLS (c, closure->repr, "no matchable variable in");
4548 continue;
4549 }
4550 const reference ref = kissat_reference_clause (solver, c);
4551 KISSAT_assert (size <= UINT_MAX);
4552 refsize refsize = {.ref = ref, .size = (unsigned)size};
4553 PUSH_STACK (candidates, refsize);
4554 }
4555 DEALLOC (matchable, VARS);
4556#ifndef KISSAT_QUIET
4557 const size_t size_candidates = SIZE_STACK (candidates);
4559 solver, "considering %zu matchable subsumption candidates %.0f%%",
4560 size_candidates, kissat_percent (size_candidates, potential));
4561#else
4562 (void) potential;
4563#endif
4564 sort_references_by_clause_size (solver, &candidates);
4565#ifndef KISSAT_QUIET
4566 size_t tried = 0, subsumed = 0;
4567#endif
4568 for (all_stack (refsize, refsize, candidates)) {
4570 break;
4571#ifndef KISSAT_QUIET
4572 tried++;
4573#endif
4574 const unsigned ref = refsize.ref;
4575 clause *c = kissat_dereference_clause (solver, ref);
4576 if (find_subsuming_clause (closure, c)) {
4577#ifndef KISSAT_QUIET
4578 subsumed++;
4579#endif
4580 }
4581 }
4582 kissat_phase (solver, "congruence", GET (closures),
4583 "subsumed %zu clauses out of %zu tried %.0f%%", subsumed,
4584 tried, kissat_percent (subsumed, tried));
4585 kissat_resume_sparse_mode (solver, false, &binaries);
4586 RELEASE_STACK (candidates);
4587 RELEASE_STACK (binaries);
4588 STOP (matching);
4589}
4590
4592 if (solver->inconsistent)
4593 return false;
4595 KISSAT_assert (!solver->level);
4596 KISSAT_assert (solver->probing);
4597 KISSAT_assert (solver->watching);
4598 if (!GET_OPTION (congruence))
4599 return false;
4600 if (!GET_OPTION (congruenceands) && !GET_OPTION (congruenceites) &&
4601 !GET_OPTION (congruencexors))
4602 return false;
4603 if (GET_OPTION (congruenceonce) && solver->statistics_.closures)
4604 return false;
4606 return false;
4607 if (DELAYING (congruence))
4608 return false;
4609 START (congruence);
4610 INC (closures);
4612 init_closure (solver, &closure);
4613 extract_gates (&closure);
4614 bool reset = false;
4615 if (!solver->inconsistent && !TERMINATED (congruence_terminated_9)) {
4616 find_units (&closure);
4617 if (!solver->inconsistent && !TERMINATED (congruence_terminated_10)) {
4618 find_equivalences (&closure);
4619 if (!solver->inconsistent && !TERMINATED (congruence_terminated_11)) {
4620 size_t propagated = propagate_units_and_equivalences (&closure);
4621 if (!solver->inconsistent && propagated &&
4623 forward_subsume_matching_clauses (&closure);
4624 reset = true;
4625 }
4626 }
4627 }
4628 }
4629 if (!reset)
4630 reset_closure (&closure);
4631 unsigned equivalent = reset_repr (&closure);
4632 kissat_phase (solver, "congruence", GET (closures),
4633 "merged %u equivalent variables %.2f%%", equivalent,
4634 kissat_percent (equivalent, solver->active));
4635 KISSAT_assert (solver->active >= equivalent);
4636#ifndef KISSAT_QUIET
4637 solver->active -= equivalent;
4638 REPORT (!equivalent, 'c');
4639 if (!solver->inconsistent)
4640 solver->active += equivalent;
4641#endif
4642 if (kissat_average (equivalent, solver->active) < 0.001)
4643 BUMP_DELAY (congruence);
4644 else
4645 REDUCE_DELAY (congruence);
4646 STOP (congruence);
4648 return equivalent;
4649}
4650
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
Definition allocate.c:49
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
#define NALLOC(T, P, N)
Definition allocate.h:24
void kissat_learned_unit(kissat *solver, unsigned lit)
Definition assign.c:18
ABC_NAMESPACE_HEADER_START typedef uint64_t generator
Definition random.h:12
#define BEGIN_STACK(S)
Definition stack.h:46
#define POP_STACK(S)
Definition stack.h:37
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define SET_END_OF_STACK(S, P)
Definition stack.h:62
#define RELEASE_STACK(S)
Definition stack.h:71
#define all_pointers(T, E, S)
Definition stack.h:99
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define ADD(NAME, DELTA)
#define INC(NAME)
#define CALLOC(T, P, N)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define DEALLOC(P, N)
#define CHECK_AND_ADD_STACK(...)
Definition check.h:152
#define CHECK_AND_ADD_EMPTY(...)
Definition check.h:146
#define REMOVE_CHECKER_STACK(...)
Definition check.h:173
void kissat_connect_referenced(kissat *solver, reference ref)
Definition clause.c:54
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
Definition clause.c:164
void kissat_new_binary_clause(kissat *solver, unsigned first, unsigned second)
Definition clause.c:122
void kissat_connect_clause(kissat *solver, clause *c)
Definition clause.c:60
void kissat_new_unwatched_binary_clause(kissat *solver, unsigned first, unsigned second)
Definition clause.c:127
void kissat_delete_binary(kissat *solver, unsigned a, unsigned b)
Definition clause.c:181
#define LOGATE(G,...)
Definition congruence.c:216
struct gate_hash_table gate_hash_table
Definition congruence.c:59
#define XOR_GATE
Definition congruence.c:29
#define add_ite_matching_proof_chain(...)
#define check_ternary
Definition congruence.c:728
#define LESS_OTHER(A, B)
#define ITE_GATE
Definition congruence.c:30
#define CLOGITEGATE(G,...)
Definition congruence.c:207
#define check_ite_lits_normalized
Definition congruence.c:339
#define SMALLER_NEGATED_BIN_COUNT(A, B)
#define check_and_gate_implied(...)
Definition congruence.c:723
#define AND_GATE
Definition congruence.c:28
bool kissat_congruence(kissat *solver)
#define add_xor_shrinking_proof_chain(...)
#define add_ite_turned_and_binary_clauses
#define SIZE_NONCES
Definition congruence.c:107
#define CLOGANDGATE(G,...)
Definition congruence.c:193
#define MAX_HASH_TABLE_SIZE
Definition congruence.c:395
#define CLOGREPR(L)
Definition congruence.c:214
void reset_gate_hash_table(closure *closure)
Definition congruence.c:236
#define check_xor_lits_normalized
Definition congruence.c:338
#define CLOGXORGATE(G,...)
Definition congruence.c:200
#define LD_MAX_ARITY
Definition congruence.c:32
#define check_and_lits_normalized
Definition congruence.c:337
#define delete_proof_chain(...)
#define check_ite_implied
Definition congruence.c:729
#define RANK_OTHER(A)
#define RANKREFSIZE(REFSIZE)
#define check_lits_sorted(...)
Definition congruence.c:333
#define all_rhs_literals_in_gate(LIT, G)
Definition congruence.c:66
#define add_xor_matching_proof_chain(...)
#define REMOVED
Definition congruence.c:61
#define check_ite_gate_implied
Definition congruence.c:730
#define check_xor_gate_implied
Definition congruence.c:727
#define LESS_LIT(A, B)
Definition congruence.c:343
#define MAX_ARITY
void kissat_enter_dense_mode(kissat *solver, litpairs *irredundant)
Definition dense.c:101
void kissat_resume_sparse_mode(kissat *solver, bool flush_eliminated, litpairs *irredundant)
Definition dense.c:201
#define ACTIVE
Definition espresso.h:129
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
#define DEQUEUE_FIFO(F, E)
Definition fifo.h:68
#define RELEASE_FIFO(F)
Definition fifo.h:78
#define INIT_FIFO(F)
Definition fifo.h:26
#define ENQUEUE_FIFO(T, F, E)
Definition fifo.h:61
#define EMPTY_FIFO(F)
Definition fifo.h:28
#define SIZE_FIFO(F)
Definition fifo.h:30
#define VARS
Definition internal.h:250
#define all_variables(IDX)
Definition internal.h:269
#define all_literals(LIT)
Definition internal.h:274
#define all_clauses(C)
Definition internal.h:279
#define LITS
Definition internal.h:251
#define BUMP_DELAY(NAME)
Definition kimits.h:183
#define REDUCE_DELAY(NAME)
Definition kimits.h:185
#define DELAYING(NAME)
Definition kimits.h:181
#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 SORT(TYPE, N, A, LESS)
Definition sort.h:135
#define SHRINK_STACK(S)
Definition stack.h:44
#define solver
Definition kitten.c:211
#define LOGCOUNTEDLITS(...)
Definition logging.h:385
#define LOGANDGATE(...)
Definition logging.h:406
#define LOGREPRCLS(...)
Definition logging.h:427
#define LOGBINARY(...)
Definition logging.h:442
#define LOGXORGATE(...)
Definition logging.h:409
#define LOGCLS(...)
Definition logging.h:415
#define LOG2(...)
Definition logging.h:352
#define LOGUNSIGNEDS2(...)
Definition logging.h:400
#define LOGITEGATE(...)
Definition logging.h:412
#define LOGLIT(...)
Definition logging.hpp:99
bool is_power_of_two(unsigned n)
Definition util.hpp:47
bool parity(unsigned a)
Definition util.hpp:71
bool sign(Lit p)
Definition SolverTypes.h:63
unsigned long long size
Definition giaNewBdd.h:39
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define kissat_verbose(...)
Definition print.h:51
#define kissat_extremely_verbose(...)
Definition print.h:53
#define kissat_very_verbose(...)
Definition print.h:52
#define kissat_phase(...)
Definition print.h:48
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
#define ADD_EMPTY_TO_PROOF(...)
Definition proof.h:135
#define ADD_STACK_TO_PROOF(...)
Definition proof.h:138
#define DELETE_STACK_FROM_PROOF(...)
Definition proof.h:161
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
Definition proprobe.c:37
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
Definition rank.h:136
#define RADIX_SORT(VTYPE, RTYPE, N, V, RANK)
Definition rank.h:25
#define INVALID_REF
Definition reference.h:16
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
#define REPORT(...)
Definition report.h:10
int lit
Definition satVec.h:130
#define LIT(IDX)
Definition literal.h:31
#define NEGATED(LIT)
Definition literal.h:35
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
#define STRIP(LIT)
Definition literal.h:37
#define IRREDUNDANT_CLAUSES
Definition statistics.h:337
#define BINARY_CLAUSES
Definition statistics.h:340
#define kissat_check_statistics(...)
Definition statistics.h:464
#define GET(NAME)
Definition statistics.h:416
unsigned lits[3]
Definition clause.h:39
bool redundant
Definition clause.h:28
unsigned size
Definition clause.h:37
bool garbage
Definition clause.h:25
uint64_t nonces[SIZE_NONCES]
Definition congruence.c:121
unsigned * negbincount
Definition congruence.c:124
unsigned_fifo schedule
Definition congruence.c:118
unsigneds unsimplified
Definition congruence.c:116
kissat * solver
Definition congruence.c:110
unsigneds lits
Definition congruence.c:114
unsigned * equivalences
Definition congruence.c:123
unsigned * largecount
Definition congruence.c:125
gate_hash_table hash
Definition congruence.c:120
bool * scheduled
Definition congruence.c:111
gates garbage
Definition congruence.c:113
gates * occurrences
Definition congruence.c:112
litpairs condbin[2]
Definition congruence.c:126
unsigned * units
Definition congruence.c:122
litpairs condeq[2]
Definition congruence.c:127
unsigned * repr
Definition congruence.c:119
litpairs binaries
Definition congruence.c:117
unsigneds rhs
Definition congruence.c:115
unsigned hash
Definition congruence.c:40
bool indexed
Definition congruence.c:43
unsigned rhs[]
Definition congruence.c:47
unsigned lhs
Definition congruence.c:39
bool marked
Definition congruence.c:44
bool garbage
Definition congruence.c:42
bool shrunken
Definition congruence.c:45
unsigned tag
Definition congruence.c:41
unsigned arity
Definition congruence.c:46
reference ref
Definition congruence.c:91
unsigned hash
Definition congruence.c:90
unsigned_array trail
Definition internal.h:140
bool inconsistent
Definition internal.h:87
unsigned lits[2]
Definition watch.h:65
unsigned offset
unsigned size
reference ref
unsigned size
#define congruence_terminated_10
Definition terminate.h:57
#define congruence_terminated_4
Definition terminate.h:51
#define TERMINATED(BIT)
Definition terminate.h:42
#define congruence_terminated_5
Definition terminate.h:52
#define congruence_terminated_2
Definition terminate.h:49
#define congruence_terminated_7
Definition terminate.h:54
#define congruence_terminated_3
Definition terminate.h:50
#define congruence_terminated_12
Definition terminate.h:59
#define congruence_terminated_8
Definition terminate.h:55
#define congruence_terminated_9
Definition terminate.h:56
#define congruence_terminated_6
Definition terminate.h:53
#define congruence_terminated_11
Definition terminate.h:58
#define congruence_terminated_1
Definition terminate.h:48
ABC_NAMESPACE_IMPL_START void kissat_flush_trail(kissat *solver)
Definition trail.c:8
#define smaller(tree, n, m, depth)
Definition trees.c:455
Definition watch.h:41
large_watch large
Definition watch.h:45
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
char * memcpy()
#define MIN(a, b)
Definition util_old.h:256
char * sprintf()
long random()
#define SWAP(TYPE, A, B)
Definition utilities.h:151
signed char mark
Definition value.h:8
#define VALUE(LIT)
Definition value.h:10
void kissat_flush_all_connected(kissat *solver)
Definition watch.c:104
#define SIZE_WATCHES(W)
Definition watch.h:104
#define BEGIN_WATCHES(WS)
Definition watch.h:115
#define END_WATCHES(WS)
Definition watch.h:118
vector watches
Definition watch.h:49
#define WATCHES(LIT)
Definition watch.h:137