26#define MERGE_CONDITIONAL_EQUIVALENCES
32#define LD_MAX_ARITY 26
33#define MAX_ARITY ((1 << LD_MAX_ARITY) - 1)
36#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
61#define REMOVED ((gate *) (~(uintptr_t) 0))
63#define BEGIN_RHS(G) ((G)->rhs)
64#define END_RHS(G) (BEGIN_RHS (G) + (G)->arity)
66#define all_rhs_literals_in_gate(LIT, G) \
68 *LIT##_PTR = BEGIN_RHS (G), *const LIT##_END = END_RHS (G); \
69 LIT##_PTR != LIT##_END && ((LIT = *LIT##_PTR), true); \
72#ifdef INDEX_BINARY_CLAUSES
78typedef struct binary_clause binary_clause;
80struct binary_hash_table {
82 size_t size, size2, count;
85typedef struct binary_hash_table binary_hash_table;
94#ifdef INDEX_LARGE_CLAUSES
98struct large_clause_hash_table {
100 size_t size, size2, count;
103typedef struct large_clause_hash_table large_clause_hash_table;
107#define SIZE_NONCES 16
128#ifdef INDEX_BINARY_CLAUSES
129 binary_hash_table bintab;
131#ifdef INDEX_LARGE_CLAUSES
132 large_clause_hash_table clauses;
134#ifdef CHECKING_OR_PROVING
137#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
169#ifdef CHECKING_OR_PROVING
172#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
180static size_t bytes_gate (
size_t arity) {
181 return sizeof (
gate) + arity *
sizeof (
unsigned);
184static unsigned actual_gate_arity (
gate *g) {
185 unsigned res = g->
arity;
193#define CLOGANDGATE(G, ...) \
195 KISSAT_assert ((G)->tag == AND_GATE); \
196 LOGANDGATE ((G)->id, closure->repr, (G)->lhs, (G)->arity, (G)->rhs, \
200#define CLOGXORGATE(G, ...) \
202 KISSAT_assert ((G)->tag == XOR_GATE); \
203 LOGXORGATE ((G)->id, closure->repr, (G)->lhs, (G)->arity, (G)->rhs, \
207#define CLOGITEGATE(G, ...) \
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__); \
214#define CLOGREPR(L) LOGREPR ((L), closure->repr)
216#define LOGATE(G, ...) \
218 if ((G)->tag == AND_GATE) \
219 CLOGANDGATE (G, __VA_ARGS__); \
220 else if ((G)->tag == XOR_GATE) \
221 CLOGXORGATE (G, __VA_ARGS__); \
223 KISSAT_assert ((G)->tag == ITE_GATE); \
224 CLOGITEGATE (G, __VA_ARGS__); \
231 unsigned actual_arity = actual_gate_arity (g);
232 size_t actual_bytes = bytes_gate (actual_arity);
266#ifdef CHECKING_OR_PROVING
293 const unsigned *
const end_lits =
lits +
size;
294 for (
const unsigned *
p =
lits;
p != end_lits;
p++) {
295 const unsigned lit = *
p;
298 const unsigned not_lit =
lit ^ 1;
312 const unsigned *
lits) {
315 for (
size_t i = 1; i != arity; i++)
320 const unsigned *
lits) {
333#define check_lits_sorted(...) \
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
343#define LESS_LIT(A, B) ((A) < (B))
350static unsigned hash_lits (
closure *
closure,
unsigned tag,
size_t arity,
351 const unsigned *
lits) {
362 const unsigned *end_lits =
lits + arity;
365 const uint64_t *n =
nonces + tag;
368 for (
const unsigned *l =
lits; l != end_lits; l++) {
383static size_t reduce_hash (
unsigned hash,
size_t size,
size_t size2) {
395#define MAX_HASH_TABLE_SIZE ((size_t) 1 << 32)
405static bool match_lits (
gate *g,
unsigned tag,
unsigned hash,
size_t size,
406 const unsigned *
lits) {
412 if (g->
arity != size)
414 const unsigned *
p =
lits;
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;
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;
434 for (
size_t old_pos = 0; old_pos != old_size; old_pos++) {
435 gate *g = old_table[old_pos];
442 size_t new_pos = reduce_hash (g->
hash, new_size, new_size);
443 while (new_table[new_pos]) {
445 if (++new_pos == new_size)
448 new_table[new_pos] = g;
451 solver,
"flushed %zu entries %.0f%% resizing table of size %zu",
452 flushed, kissat_percent (flushed, old_size), old_size);
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));
470 size_t pos = reduce_hash (g->
hash, hash_size, hash_size);
472 INC (congruent_lookups);
473 INC (congruent_lookups_removed);
474 unsigned collisions = 0;
475 while (table[
pos] != g) {
477 if (++
pos == hash_size)
480 ADD (congruent_collisions_removed, collisions);
481 ADD (congruent_collisions, collisions);
483 LOGATE (g,
"removing from hash table");
489 size_t size,
const unsigned *
lits,
gate *except) {
497 size_t start_pos = reduce_hash (
hash, hash_size, hash_size);
499 INC (congruent_lookups);
500 INC (congruent_lookups_find);
501 size_t pos = start_pos;
502 unsigned collisions = 0;
504 while ((g = table[
pos])) {
511 }
else if (g != except && match_lits (g, tag,
hash, size,
lits)) {
512 INC (congruent_matched);
517 if (++
pos == hash_size)
519 if (
pos == start_pos)
522 ADD (congruent_collisions_find, collisions);
523 ADD (congruent_collisions, collisions);
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);
538 size_t pos = reduce_hash (g->
hash, hash_size, hash_size);
540 unsigned collisions = 0;
543 if (++
pos == hash_size)
546 ADD (congruent_collisions_index, collisions);
547 ADD (congruent_collisions, collisions);
567 while (carry &&
p != end) {
569 unsigned not_lit =
NOT (
lit);
580#define LESS_LITERAL(A, B) ((A) < (B))
584 unsigneds *implied = &
closure->implied;
585 SORT_STACK (
unsigned, *implied, LESS_LITERAL);
587 const unsigned *
const end =
END_STACK (*implied);
589 bool tautological =
false;
590 for (
const unsigned *
p = q;
p != end;
p++) {
591 const unsigned lit = *
p;
594 const unsigned not_lit =
NOT (
lit);
595 if (prev == not_lit) {
611 unsigneds *implied = &
closure->implied;
621 unsigneds *implied = &
closure->implied;
634 const unsigned lhs = g->
lhs;
635 const unsigned not_lhs =
NOT (lhs);
637 check_binary_implied (
closure, not_lhs, other);
638 unsigneds *implied = &
closure->implied;
642 const unsigned not_other =
NOT (other);
654 const unsigned lhs = g->
lhs;
655 const unsigned not_lhs =
NOT (lhs);
663 unsigned arity = g->
arity;
664 unsigned end = 1u << arity;
667 for (
unsigned i = 0; i != end; i++) {
681 unsigneds *implied = &
closure->implied;
689 unsigned cond,
unsigned then_lit,
694 LOG (
"checking implied ITE gate %s := %s ? %s : %s",
LOGLIT (lhs),
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);
709#ifndef KISSAT_NOPTIONS
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];
723#define check_and_gate_implied(...) \
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
736 unsigned res =
lit, next =
repr[res];
738 res = next, next =
repr[res];
742#ifndef MERGE_CONDITIONAL_EQUIVALENCES
745 unsigned b,
unsigned ignore) {
750 const watch *
p = begin_watches;
751 while (
p != end_watches) {
763 if (
lit == a ||
lit == b) {
767 goto CONTINUE_WITH_NEXT_WATCH;
772 CONTINUE_WITH_NEXT_WATCH:;
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);
791 return find_other_two (
solver, c_watches, a, b, c);
796static bool learn_congruence_unit (
closure *
closure,
unsigned unit) {
802 INC (congruent_units);
805 LOG (
"inconsistent congruence unit %s",
LOGLIT (unit));
810 LOG (
"learning congruence unit %s",
LOGLIT (unit));
816 LOG (
"propagating congruence unit %s yields conflict",
LOGLIT (unit));
820static void add_binary_clause (
closure *
closure,
unsigned a,
unsigned b) {
835 else if (a_value < 0 && !b_value)
837 else if (!a_value && b_value < 0)
840 (void) !learn_congruence_unit (
closure, unit);
844 LOGBINARY (a, b,
"adding representative");
865static unsigned dequeue_next_scheduled_literal (
closure *
closure) {
868#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
871 unsigned idx =
IDX (res);
884 unsigned repr_other = find_repr (
closure, other);
886 if (repr_lit == repr_other) {
887 LOG (
"already merged %s and %s", LOGREPR (
lit,
repr),
888 LOGREPR (other,
repr));
892 const value lit_value = values[
lit];
893 const value other_value = values[other];
897 if (lit_value == other_value) {
898 LOG (
"not merging %s and %s assigned to the same value",
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;
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);
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);
925 unsigned larger = repr_other;
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;
939 LOG (
"merging %s and %s", LOGREPR (
lit,
repr), LOGREPR (other,
repr));
941 const unsigned not_larger =
NOT (larger);
943 repr[not_larger] = not_smaller;
945 LOG (
"congruence repr[%s] = %s",
LOGLIT (not_larger),
948 add_binary_clause (
closure, larger, not_smaller);
949 schedule_literal (
closure, larger);
962 unsigned lhs,
unsigned arity,
const unsigned *
lits) {
964 const size_t bytes = bytes_gate (arity);
966#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
967 g->id =
closure->gates_added++;
982 ADD (congruent_arity, arity);
983 INC (congruent_gates);
988 unsigned arity,
unsigned *
lits,
gate *except) {
996 INC (congruent_matched_ands);
999 "could not find matching");
1014 unsigned not_lit =
NOT (
lit);
1018 const unsigned arity =
SIZE_STACK (*rhs_stack);
1025 INC (congruent_ands);
1030 ADD (congruent_arity_ands, arity);
1031 INC (congruent_gates_ands);
1035#ifdef CHECKING_OR_PROVING
1037static void copy_literals (
kissat *
solver, unsigneds *dst,
1038 const unsigneds *src) {
1049#ifndef KISSAT_NDEBUG
1053 bool trivial =
false;
1058 const unsigned not_lit =
NOT (
lit);
1059 const mark not_lit_mark = marks[not_lit];
1060 if (not_lit_mark & 4) {
1065 marks[
lit] = lit_mark;
1082#define SIMPLIFY_AND_ADD_TO_PROOF_CHAIN() \
1083 simplify_and_add_to_proof_chain (solver, marks, unsimplified, clause, \
1087 unsigned lhs1,
unsigned lhs2) {
1091 if (!kissat_checking_or_proving (
solver))
1093 LOG (
"starting XOR matching proof chain");
1096 unsigneds *
const chain = &
closure->chain;
1101 const unsigned reduced_arity = g->
arity - 1;
1102 for (
unsigned i = 0; i != reduced_arity; i++)
1104 const unsigned not_lhs1 =
NOT (lhs1);
1105 const unsigned not_lhs2 =
NOT (lhs2);
1109 for (
unsigned i = 0; i != 1u <<
size; i++) {
1112 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1116 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1123 LOG (
"finished XOR matching proof chain");
1128 unsigneds *chain = &
closure->chain;
1129 if (!kissat_checking_or_proving (
solver)) {
1135 LOG (
"starting deletion of proof chain");
1139 const unsigned *end =
END_STACK (*chain);
1140 const unsigned *
p = start;
1142 const unsigned lit = *
p;
1144 while (start !=
p) {
1145 const unsigned other = *start++;
1158 LOG (
"finished deletion of proof chain");
1163#define add_xor_matching_proof_chain(...) \
1167#define delete_proof_chain(...) \
1174 unsigned arity,
unsigned *
lits,
gate *except) {
1182 INC (congruent_matched_xors);
1185 "tried but did not find matching");
1198 const unsigned not_lhs =
NOT (lhs);
1200 if (
lit != lhs &&
lit != not_lhs) {
1204 const unsigned arity =
SIZE_STACK (*rhs_stack);
1212 INC (congruent_xors);
1213 if (!
solver->inconsistent)
1219 ADD (congruent_arity_xors, arity);
1220 INC (congruent_gates_xors);
1224#ifdef CHECKING_OR_PROVING
1227 unsigned lhs1,
unsigned lhs2) {
1231 if (!kissat_checking_or_proving (
solver))
1233 LOG (
"starting ITE matching proof chain");
1237 unsigneds *chain = &
closure->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);
1248 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1251 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1260 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1263 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1265 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1267 LOG (
"finished ITE matching proof chain");
1272 if (!kissat_checking_or_proving (
solver))
1274 LOG (
"starting ITE turned AND supporting binary clauses");
1277 unsigneds *chain = &
closure->chain;
1281 const unsigned not_lhs =
NOT (g->
lhs);
1282 const unsigned *
rhs = g->
rhs;
1285 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1288 SIMPLIFY_AND_ADD_TO_PROOF_CHAIN ();
1294#define add_ite_matching_proof_chain(...) \
1298#define add_ite_turned_and_binary_clauses add_ite_matching_proof_chain
1318 bool *negate_lhs_ptr,
unsigned arity,
1323 lits[2],
"finding not yet normalized");
1324 bool negate_lhs = normalize_ite_lits (
solver,
lits);
1327 LOG (
"normalization forces negation of LHS");
1329 lits[2],
"normalized");
1331 *negate_lhs_ptr = negate_lhs;
1337 INC (congruent_matched_ites);
1340 lits[1],
lits[2],
"tried but did not find matching");
1345 bool *negate_lhs_ptr,
gate *g) {
1346 return find_ite_lits (
closure, h, negate_lhs_ptr, g->
arity, g->
rhs, g);
1350 unsigned then_lit,
unsigned else_lit) {
1352 const unsigned not_then_lit =
NOT (then_lit);
1353 if (else_lit == not_then_lit) {
1356 LOG (
"skipping ternary XOR gate %s := %s ^ %s",
LOGLIT (lhs),
1359 LOG (
"skipping ternary XOR gate %s := %s ^ %s",
LOGLIT (
NOT (lhs)),
1364 if (else_lit == then_lit) {
1365 LOG (
"found trivial ITE gate %s := %s ? %s : %s",
LOGLIT (lhs),
1367 if (merge_literals (
closure, lhs, then_lit))
1368 INC (congruent_trivial_ite);
1377 const unsigned arity = 3;
1381 gate *g = find_ite_lits (
closure, &
hash, &negate_lhs, arity, rhs_lits, 0);
1387 INC (congruent_ites);
1388 if (!
solver->inconsistent)
1396 INC (congruent_gates_ites);
1404 LOGATE (g,
"marked as garbage");
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;
1415 if (new_end_rhs == old_end_rhs)
1417 const unsigned new_arity = new_end_rhs -
rhs;
1423 g->
arity = new_arity;
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);
1448static bool gate_contains (
gate *g,
unsigned lit) {
1456#ifndef KISSAT_NDEBUG
1459 if (dst != g->
lhs && dst !=
NOT (g->
lhs))
1461 mark_gate_as_garbage (
closure, g);
1466 unsigned *new_end_rhs,
unsigned falsifies,
1467 unsigned clashing) {
1469#ifndef KISSAT_NDEBUG
1474 g->
rhs[0] = falsifies;
1475 new_end_rhs = g->
rhs + 1;
1478 g->
rhs[0] = clashing;
1479 g->
rhs[1] =
NOT (clashing);
1480 new_end_rhs = g->
rhs + 2;
1482 shrink_gate (
closure, g, new_end_rhs);
1486 unsigned clashing) {
1492 else if (g->
arity == 1) {
1495 (void) learn_congruence_unit (
closure, g->
rhs[0]);
1496 else if (value_lhs < 0)
1499 INC (congruent_unary_ands);
1500 INC (congruent_unary);
1508 INC (congruent_ands);
1517 mark_gate_as_garbage (
closure, g);
1521 if (skip_and_gate (
closure, g))
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;
1532 while (
p != end_of_rhs) {
1533 const unsigned lit = *
p++;
1548 INC (congruent_simplified);
1549 INC (congruent_simplified_ands);
1554 if (skip_and_gate (
closure, g))
1556 if (!gate_contains (g, src))
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;
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++;
1578 if (
lit == not_lhs) {
1592 if (not_dst_count) {
1600 if (
lit == not_dst) {
1614 shrink_and_gate (
closure, g, q, falsifies, clashing);
1617 update_and_gate (
closure, g, falsifies, clashing);
1618 INC (congruent_rewritten);
1619 INC (congruent_rewritten_ands);
1622static bool skip_xor_gate (
gate *g) {
1630#ifdef CHECKING_OR_PROVING
1635 if (!kissat_checking_or_proving (
solver))
1637 LOG (
"starting XOR shrinking proof chain");
1640 for (
unsigned i = 0; i != g->
arity; i++) {
1641 unsigned lit = g->
rhs[i];
1644 const unsigned lhs = g->
lhs;
1645 const unsigned not_lhs =
NOT (lhs);
1649 const unsigned not_pivot =
NOT (pivot);
1652 const unsigned end = 1u <<
size;
1653 for (
unsigned i = 0; i != end; i++) {
1677 LOG (
"finished XOR shrinking proof chain");
1682#define add_xor_shrinking_proof_chain(...) \
1688 unsigned *new_end_rhs) {
1690 shrink_gate (
closure, g, new_end_rhs);
1699 else if (g->
arity == 1) {
1702 (void) learn_congruence_unit (
closure, g->
rhs[0]);
1703 else if (value_lhs < 0)
1706 INC (congruent_unary_xors);
1707 INC (congruent_unary);
1717 INC (congruent_xors);
1718 if (!
solver->inconsistent)
1728 mark_gate_as_garbage (
closure, g);
1732 if (skip_xor_gate (g))
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;
1752 shrink_xor_gate (
closure, g, q);
1756 INC (congruent_simplified);
1757 INC (congruent_simplified_xors);
1762 if (skip_xor_gate (g))
1764 if (rewriting_lhs (
closure, g, dst))
1766 if (!gate_contains (g, src))
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;
1776 for (
const unsigned *
p = q;
p != end_of_rhs;
p++) {
1795 if (dst_count == 2) {
1800 for (
const unsigned *
p = q;
p != end_of_rhs;
p++) {
1801 const unsigned lit = *
p;
1807 shrink_xor_gate (
closure, g, q);
1812 if (!g->
garbage && !
solver->inconsistent && original_dst_negated &&
1815 connect_occurrence (
closure, dst, g);
1818 INC (congruent_rewritten);
1819 INC (congruent_rewritten_xors);
1822static bool skip_ite_gate (
gate *g) {
1830 if (skip_ite_gate (g))
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);
1848 }
else if (cond_value < 0) {
1849 if (merge_literals (
closure, lhs, else_lit)) {
1850 INC (congruent_unary_ites);
1851 INC (congruent_unary);
1854 const value then_value = values[then_lit];
1855 const value else_value = values[else_lit];
1856 const unsigned not_lhs =
NOT (lhs);
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);
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);
1875 if (then_value > 0) {
1880 }
else if (then_value < 0) {
1884 }
else if (else_value > 0) {
1911 INC (congruent_ands);
1918 if (
lit != cond &&
lit != then_lit &&
lit != else_lit)
1924 mark_gate_as_garbage (
closure, g);
1925 INC (congruent_simplified);
1926 INC (congruent_simplified_ites);
1931 if (skip_ite_gate (g))
1933 if (!gate_contains (g, src))
1937 unsigned *
const rhs = g->
rhs;
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);
1952 if (dst == then_lit) {
1959 rhs[0] = not_then_lit;
1960 rhs[1] = not_else_lit;
1961 }
else if (not_dst == then_lit) {
1967 }
else if (dst == else_lit) {
1973 }
else if (not_dst == else_lit) {
1980 rhs[0] = not_then_lit;
1981 rhs[1] = not_else_lit;
1986 }
else if (src == then_lit) {
1995 rhs[1] = not_else_lit;
1996 }
else if (not_dst == cond) {
2002 }
else if (dst == else_lit) {
2005 if (merge_literals (
closure, lhs, else_lit)) {
2006 INC (congruent_unary_ites);
2007 INC (congruent_unary);
2010 }
else if (not_dst == else_lit) {
2029 }
else if (not_dst == cond) {
2037 rhs[1] = not_then_lit;
2038 }
else if (dst == then_lit) {
2041 if (merge_literals (
closure, lhs, then_lit)) {
2042 INC (congruent_unary_ites);
2043 INC (congruent_unary);
2046 }
else if (not_dst == then_lit) {
2064 bool negate_lhs =
false;
2067 negate_lhs = !negate_lhs;
2071 negate_lhs = !negate_lhs;
2101 INC (congruent_ands);
2102 if (!
solver->inconsistent)
2112 if (
lit != cond &&
lit != then_lit &&
lit != else_lit)
2134 unsigned normalized_lhs = negate_lhs ? not_lhs : lhs;
2136 if (merge_literals (
closure, h->
lhs, normalized_lhs))
2137 INC (congruent_ites);
2138 if (!
solver->inconsistent)
2151 if (
lit != cond &&
lit != then_lit &&
lit != else_lit)
2157 mark_gate_as_garbage (
closure, g);
2158 INC (congruent_rewritten);
2159 INC (congruent_rewritten_ites);
2164 simplify_and_gate (
closure, g);
2166 simplify_xor_gate (
closure, g);
2168 simplify_ite_gate (
closure, g);
2175 rewrite_and_gate (
closure, g, dst, src);
2177 rewrite_xor_gate (
closure, g, dst, src);
2179 rewrite_ite_gate (
closure, g, dst, src);
2189#define RANK_OTHER(A) ((A).lits[1])
2190#define LESS_OTHER(A, B) (RANK_OTHER (A) < RANK_OTHER (B))
2201 const size_t m = (l + r) / 2;
2202 const unsigned tmp = binaries[m].
lits[1];
2205 else if (tmp > other)
2221static uint64_t rank_litpair (
litpair p) {
2222 uint64_t res =
p.lits[0];
2232 START (extractbinaries);
2241 const unsigned lit =
p->lits[0];
2242 while (q != end && q->
lits[0] ==
lit)
2244 const size_t size = q -
p;
2246 const size_t offset =
p - binaries;
2256 clause *last_irredundant = kissat_last_irredundant_clause (
solver);
2258 size_t extracted = 0, duplicated = 0;
2263 if (last_irredundant && last_irredundant < d)
2269 const unsigned *lits = d->lits;
2270 const unsigned a = lits[0];
2273 const unsigned b = lits[1];
2276 const unsigned c = lits[2];
2279 const unsigned not_a =
NOT (a);
2280 const unsigned not_b =
NOT (b);
2281 const unsigned not_c =
NOT (c);
2294 LOGCLS (d,
"strengthening");
2297 add_binary_clause (
closure, l, k);
2305 litpair *added = binaries + before;
2306#ifndef KISSAT_NDEBUG
2307 const size_t after = end - binaries;
2316 const unsigned lit = pair.
lits[0];
2317 const unsigned other = pair.
lits[1];
2318 if (
p == added ||
lit != prev_lit || other != prev_other) {
2332 ADD (congruent_binaries, extracted - duplicated);
2334 extracted, duplicated);
2335 STOP (extractbinaries);
2338#ifndef INDEX_BINARY_CLAUSES
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),
2351 unsigneds *
const marked = &
solver->analyzed;
2354 const unsigned arity =
SIZE_STACK (*lits) - 1;
2355 unsigned matched = 0;
2366 const mark tmp = marks[other];
2375 LOG (
"found %zu initial LHS candidates",
SIZE_STACK (*marked));
2376 if (matched < arity)
2379 return new_and_gate (
closure, lhs);
2387 const unsigned not_lhs =
NOT (lhs);
2389 if (marks[not_lhs] < 2) {
2390 LOG (
"skipping no-candidate LHS %s",
LOGLIT (lhs));
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),
2398 const unsigned arity =
SIZE_STACK (*lits) - 1;
2399 unsigned matched = 0;
2406 while (
p != end_watches) {
2417 marks[other] =
mark | 4;
2422 unsigneds *
const marked = &
solver->analyzed;
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;
2429 while (
p != end_marked) {
2430 const unsigned lit = *
p++;
2431 if (
lit == not_lhs) {
2450 LOG (
"after filtering %zu LHS candidates remain",
SIZE_STACK (*marked));
2453 if (matched < arity)
2456 return new_and_gate (
closure, lhs);
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];
2472#define SMALLER_NEGATED_BIN_COUNT(A, B) \
2473 smaller_negated_bin_count (negbincount, A, B)
2482#ifdef INDEX_BINARY_CLAUSES
2484static unsigned hash_binary (
closure *
closure, binary_clause *binary) {
2485 return hash_lits (
closure, 0, 2, binary->lits);
2494 binary_hash_table *bintab = &
closure->bintab;
2495 if (!bintab->count) {
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];
2535 const unsigned size_limit = arity_limit + 1;
2538 unsigned size = 0, max_negbincount = 0;
2550 if (++
size > size_limit) {
2551 LOGCLS (c,
"too large actual size %u thus skipping",
size);
2554 const unsigned count = negbincount[
lit];
2557 "%s negated does not occur in any binary clause "
2562 if (count > max_negbincount)
2563 max_negbincount = count;
2567 LOGCLS (c,
"actual size %u too small thus skipping",
size);
2570 const unsigned arity =
size - 1;
2571 if (max_negbincount < arity) {
2573 "all literals have less than %u negated occurrences "
2578 unsigned *begin_lits =
BEGIN_STACK (*lits), *reduced_lits = begin_lits;
2580 "counted candidate arity %u AND gate base clause", arity);
2581 const unsigned *
const end_lits =
END_STACK (*lits);
2582#ifndef INDEX_BINARY_CLAUSES
2584 unsigneds *marked = &
solver->analyzed;
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);
2593 if (count < arity) {
2594 if (reduced_lits <
p)
2595 *
p = *reduced_lits, *reduced_lits++ =
lit;
2596 else if (reduced_lits ==
p)
2601 const size_t reduced_size = end_lits - reduced_lits;
2603 LOGCLS (c,
"trying as base arity %u AND gate", arity);
2604 sort_lits_by_negbincount (
closure, reduced_size, reduced_lits);
2606 if (begin_lits < reduced_lits) {
2607 LOGCOUNTEDLITS (reduced_lits - begin_lits, begin_lits, negbincount,
2608 "skipping low occurrence");
2610 "remaining LHS candidate");
2613 "all remain LHS candidate");
2616 unsigned extracted = 0;
2618#ifndef INDEX_BINARY_CLAUSES
2621 for (
unsigned *
p = reduced_lits;
p != end_lits;
p++) {
2622 if (
solver->inconsistent)
2626 const unsigned lhs = *
p;
2627 LOG (
"trying LHS candidate literal %s with %u negated occurrences",
2628 LOGLIT (lhs), 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++)
2634 const unsigned rhs = *q, not_rhs =
NOT (rhs);
2635 if (!indexed_binary (
closure, not_lhs, not_rhs))
2636 goto CONTINUE_WITH_NEXT_LHS;
2638 (void) new_and_gate (
closure, lhs);
2642 CONTINUE_WITH_NEXT_LHS:;
2647 if (find_first_and_gate (
closure, lhs, lits)) {
2653 LOG (
"early abort AND gate search");
2655 }
else if (find_remaining_and_gate (
closure, lhs, lits)) {
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);
2671 LOGCLS (c,
"extracted %u with arity %u AND base", extracted, arity);
2675#ifdef INDEX_LARGE_CLAUSES
2689 unsigned arity = size_lits - 1;
2691 "trying to find arity %u XOR side clause", arity);
2694 large_clause_hash_table *clauses = &
closure->clauses;
2695 if (!clauses->count)
2699 unsigneds *sorted = &
solver->clause;
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);
2715 while (valid_large_clause (
hash_ref = table +
pos)) {
2724 if (!values[other] && !marks[other])
2725 goto CONTINUE_WITH_NEXT_HASH_BUCKET;
2729 CONTINUE_WITH_NEXT_HASH_BUCKET:
2730 if (++
pos == hash_size)
2738 LOGCLS (res,
"found indexed matching XOR side clause");
2740 LOG (
"no matching XOR side clause found");
2752 unsigned count_least_occurring = UINT_MAX;
2755#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
2756 const unsigned arity = size_lits - 1;
2758#ifndef KISSAT_NDEBUG
2759 const unsigned count_limit = 1u << (arity - 1);
2763 "trying to find arity %u XOR side clause", arity);
2767 unsigned count = largecount[
lit];
2769 if (count >= count_least_occurring)
2771 count_least_occurring = count;
2772 least_occurring_literal =
lit;
2776 LOG (
"searching XOR side clause watched by %s#%u",
2777 LOGLIT (least_occurring_literal), count_least_occurring);
2786 clause *
const c = kissat_dereference_clause (
solver, ref);
2789 if (c->
size < size_lits)
2809 if (found < UINT_MAX && !c->garbage) {
2817 LOGCLS (res,
"found matching XOR side");
2819 LOG (
"no matching XOR side clause found");
2832 const unsigned arity_limit =
2834 const unsigned size_limit = arity_limit + 1;
2835 unsigned negated = 0,
size = 0;
2848 if (
size == size_limit) {
2849 LOGCLS (c,
"size limit %u for XOR base clause exceeded in",
2854 largest = smallest =
lit;
2861 if (
lit > largest) {
2863 LOGCLS (c,
"not largest literal %s occurs negated in XOR base",
2871 LOGCLS (c,
"negated literal %s not largest in XOR base",
2876 LOGCLS (c,
"more than one negated literal in XOR base");
2884 LOGCLS (c,
"short XOR base clause");
2887 const unsigned arity =
size - 1;
2888 const unsigned needed_clauses = 1u << (arity - 1);
2892 unsigned count = largecount[
lit];
2893 if (count >= needed_clauses)
2896 "literal %s in XOR base clause only occurs "
2897 "%u times in large clauses thus skipping",
2901 LOGCLS (c,
"trying arity %u XOR base", arity);
2904 const unsigned end = 1u << arity;
2906#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
2909 for (
unsigned i = 0; i != end; i++) {
2910 while (i && parity_lits (
solver, lits) != negated)
2913#ifdef INDEX_LARGE_CLAUSES
2924#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
2928 while (parity_lits (
solver, lits) != negated)
2931 LOG (
"found all needed %u matching clauses:", found);
2940 unsigned extracted = 0;
2941 for (
all_stack (
unsigned, lhs, *lits)) {
2947 if (
solver->inconsistent)
2951 LOG (
"no arity %u XOR gate extracted", arity);
2954#ifdef INDEX_BINARY_CLAUSES
2959 size_t size = 2 * limit;
2961 while (
size > size2)
2964 binary_hash_table *bintab = &
closure->bintab;
2965 CALLOC (binary_hash_table, bintab->table,
size);
2967 bintab->size =
size;
2968 bintab->size2 = size2;
2970 solver,
"allocated binary clause hash table of size %zu",
size);
2973#ifndef KISSAT_NDEBUG
2975static bool binaries_hash_table_is_full (binary_hash_table *bintab) {
2978 if (2 * bintab->count < bintab->size)
2987 binary_hash_table *bintab = &
closure->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])
2998 table[
pos] = binary;
3008 binary_hash_table *bintab = &
closure->bintab;
3009 DEALLOC (bintab->table, bintab->size);
3017 unsigned *negbincount;
3020#ifdef INDEX_BINARY_CLAUSES
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
3043#ifdef INDEX_BINARY_CLAUSES
3048#ifdef INDEX_LARGE_CLAUSES
3050static void init_large_clauses (
closure *
closure,
size_t expected) {
3052 size_t size = 2 * expected;
3054 while (
size > size2)
3057 large_clause_hash_table *clauses = &
closure->clauses;
3058 CALLOC (large_clause_hash_table, clauses->table,
size);
3060 clauses->size =
size;
3061 clauses->size2 = size2;
3063 solver,
"allocated large clause hash table of size %zu",
size);
3066#ifndef KISSAT_NDEBUG
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) {
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);
3102 while (valid_large_clause (
clause = table +
pos))
3103 if (++
pos == hash_size)
3113 large_clause_hash_table *clauses = &
closure->clauses;
3115 DEALLOC (clauses->table, clauses->size);
3121 references *candidates) {
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);
3129 unsigned *largecount;
3134 if (last_irredundant && last_irredundant < c)
3139 int continue_counting_next_clause = 0;
3147 continue_counting_next_clause = 1;
3150 if (
size == size_limit) {
3151 continue_counting_next_clause = 1;
3156 if(continue_counting_next_clause) {
3169 size_t original_candidates =
SIZE_STACK (*candidates);
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);
3178 const unsigned counting_rounds =
GET_OPTION (congruencexorcounts);
3179 for (
unsigned round = 1; round <= counting_rounds; round++) {
3181 unsigned *new_largecount;
3185 while (
p != end_candidates) {
3194 const unsigned arity =
size - 1;
3195 const unsigned needed_clauses = 1u << (arity - 1);
3197 if (largecount[
lit] < needed_clauses) {
3199 goto CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE;
3203 new_largecount[
lit]++;
3205 CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE:;
3208 largecount = new_largecount;
3213 size_t remaining_candidates =
SIZE_STACK (*candidates);
3214 const char *how_often;
3218 else if (round == 2)
3219 how_often =
"twice";
3221 sprintf (buffer,
"%u times", round);
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),
3235#ifdef INDEX_LARGE_CLAUSES
3240#ifdef INDEX_LARGE_CLAUSES
3241 index_large_clause (
closure, ref);
3256#ifdef INDEX_LARGE_CLAUSES
3257 reset_large_clauses (
closure);
3262 references *candidates) {
3265 clause *last_irredundant = kissat_last_irredundant_clause (
solver);
3267 unsigned *largecount;
3274 if (last_irredundant && last_irredundant < c)
3279 int continue_counting_next_clause = 0;
3287 continue_counting_next_clause = 1;
3291 continue_counting_next_clause = 1;
3296 if(continue_counting_next_clause) {
3304 LOGCLS (c,
"counting original ITE gate base");
3312 "counted %zu ternary ITE clauses "
3313 "(%.0f%% of %" PRIu64
" irredundant clauses)",
3317 size_t connected = 0;
3322 unsigned positive = 0, negative = 0, twice = 0;
3326 const unsigned not_lit =
NOT (
lit);
3327 const unsigned count_not_lit = largecount[not_lit];
3329 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
3330 const unsigned count_lit = largecount[
lit];
3332 if (count_lit > 1 && count_not_lit > 1)
3340 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
3345 if (positive && negative)
3347 CONTINUE_WITH_NEXT_TERNARY_CLAUSE:;
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)",
3361 kissat_percent (size_candidates, connected),
3381static void unmark_all (unsigneds *marked,
signed char *marks) {
3387#ifdef MERGE_CONDITIONAL_EQUIVALENCES
3389static void copy_conditional_equivalences (
kissat *
solver,
unsigned lit,
3391 litpairs *condbin) {
3396 for (
const watch *
p = begin_watches;
p != end_watches;
p++) {
3419 pair = (
litpair){.lits = {first, second}};
3422 pair = (
litpair){.lits = {second, first}};
3424 LOG (
"literal %s conditional binary clause %s %s",
LOGLIT (
lit),
3431 const unsigned a =
p.lits[0], b = q.
lits[0];
3436 const unsigned c =
p.lits[1], d = q.
lits[1];
3440#define RADIDX_SORT_PAIR_LIMIT 32
3442static void sort_pairs (
kissat *
solver, litpairs *pairs) {
3447 for (
int i = 1; i >= 0; i--)
3451static bool find_litpair_second_literal (
unsigned lit,
const litpair *begin,
3453 const litpair *l = begin, *r = end;
3455 const litpair *m = l + (r - l) / 2;
3457 unsigned other = m->
lits[1];
3460 else if (other >
lit)
3470 unsigned neg_lit,
const litpair *neg_begin,
3471 const litpair *neg_end, litpairs *condeq) {
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;
3485 first = neg_lit, second = other;
3487 first = pos_lit, second = not_other;
3488 LOG (
"found conditional %s equivalence %s = %s",
LOGLIT (
lit),
3494 litpair equivalence = {.lits = {first, second}};
3497 litpair inverse_equivalence = {.lits = {
NOT (second),
NOT (first)}};
3500 litpair inverse_equivalence = {.lits = {second, first}};
3511 litpairs *condbin, litpairs *condeq) {
3512#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
3517 const litpair *pos_begin = begin;
3520 if (pos_begin == end)
3522 next_lit = pos_begin->
lits[0];
3531 const unsigned pos_lit = next_lit;
3532 const litpair *pos_end = pos_begin + 1;
3536 next_lit = pos_end->
lits[0];
3537 if (next_lit != pos_lit)
3543 const unsigned neg_lit =
NOT (pos_lit);
3544 if (next_lit != neg_lit) {
3546 pos_begin = pos_end + 1;
3548 if (pos_begin == end)
3550 next_lit = pos_begin->
lits[0];
3556 pos_begin = pos_end;
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)
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",
3573 for (
const litpair *
p = neg_begin;
p != neg_end;
p++)
3574 LOG (
"conditional %s binary clause %s %s with negative %s",
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);
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);
3598 pos_begin = neg_end + 1;
3600 if (pos_begin == end)
3602 next_lit = pos_begin->lits[0];
3608 pos_begin = neg_end;
3621 sort_pairs (
solver, condbin);
3623 if (kissat_logging (
solver)) {
3625 LOG (
"sorted conditional %s binary clause %s %s",
LOGLIT (
lit),
3627 LOG (
"found %zu conditional %s binary clauses",
SIZE_STACK (*condbin),
3631 extract_condeq_pairs (
closure,
lit, condbin, condeq);
3632 sort_pairs (
solver, condeq);
3634 if (kissat_logging (
solver)) {
3636 LOG (
"sorted conditional %s equivalence %s = %s",
LOGLIT (
lit),
3638 LOG (
"found %zu conditional %s equivalences",
SIZE_STACK (*condeq),
3644static void merge_condeq (
closure *
closure,
unsigned cond, litpairs *condeq,
3645 litpairs *not_condeq) {
3653 const litpair *q = begin_not_condeq;
3654 while (
p != end_condeq) {
3656 const unsigned lhs = cond_pair.
lits[0];
3657 const unsigned then_lit = cond_pair.
lits[1];
3659 while (q != end_not_condeq && q->
lits[0] < lhs)
3661 while (q != end_not_condeq && q->
lits[0] == lhs) {
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)
3675#ifndef KISSAT_NDEBUG
3680 find_conditional_equivalences (
closure,
lit, lit_watches, condbin + 0,
3684 find_conditional_equivalences (
closure, not_lit, not_lit_watches,
3685 condbin + 1, condeq + 1);
3689 merge_condeq (
closure, not_lit, condeq + 0, condeq + 1);
3691 merge_condeq (
closure,
lit, condeq + 1, condeq + 0);
3699static void extract_ite_gates_of_variable (
closure *
closure,
unsigned idx) {
3701 const unsigned lit =
LIT (idx);
3702 const unsigned not_lit =
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,
3712 if (size_not_lit_watches > 1)
3713 extract_ite_gates_of_literal (
closure, not_lit,
lit, not_lit_watches,
3720static void mark_third_literal_in_ternary_clauses (
3722 mark *marks,
unsigned a,
unsigned b) {
3732 for (
const watch *
p = begin;
p != end;
p++) {
3742 if (
lit == a ||
lit == b) {
3758 LOGCLS (c,
"marking %s as third literal in",
LOGLIT (third));
3766 mark *
const marks,
unsigned lhs,
3767 unsigned cond,
unsigned then_lit) {
3770 unsigned a =
NOT (lhs), b = cond;
3778 for (
const watch *
p = begin;
p != end;
p++) {
3788 if (
lit == a ||
lit == b) {
3800 unsigned not_else_lit =
NOT (else_lit);
3801 if (!marks[not_else_lit])
3803 LOGCLS (c,
"found fourth matching");
3805 marks[not_else_lit] = 0;
3806 new_ite_gate (
closure, lhs, cond, then_lit, else_lit);
3809 SWAP (
unsigned, a, b);
3839 unsigneds *marked = &
solver->analyzed;
3840 for (
all_stack (
unsigned, lhs, *lits)) {
3843 if (largecount[lhs] < 2)
3845 const unsigned not_lhs =
NOT (lhs);
3846 if (largecount[not_lhs] < 2)
3848 for (
all_stack (
unsigned, not_cond, *lits)) {
3849 if (not_cond == lhs)
3853 if (largecount[not_cond] < 2)
3855 const unsigned cond =
NOT (not_cond);
3856 if (largecount[cond] < 2)
3858 const unsigned not_then_lit = sum ^ lhs ^ not_cond;
3859 const unsigned then_lit =
NOT (not_then_lit);
3860 if (!largecount[then_lit])
3862 LOGCLS (c,
"found first ITE gate '%s := %s ? %s : ...' gate base",
3864 clause *d = find_ternary_clause (
solver, not_lhs, not_cond, then_lit);
3867 LOGCLS (d,
"found matching second ITE gate");
3868 mark_third_literal_in_ternary_clauses (
solver, values, marked, marks,
3870 extract_ite_gate (
closure, values, marks, lhs, cond, then_lit);
3871 unmark_all (marked, marks);
3882 START (extractands);
3885 const uint64_t matched_before = s->congruent_matched_ands;
3886 const uint64_t gates_before = s->congruent_gates_ands;
3888 init_and_gate_extraction (
closure);
3889 clause *last_irredundant = kissat_last_irredundant_clause (
solver);
3893 if (
solver->inconsistent)
3895 if (last_irredundant && last_irredundant < c)
3901 extract_and_gates_with_base_clause (
closure, c);
3903 reset_and_gate_extraction (
closure);
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;
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));
3921 START (extractxors);
3922 references candidates;
3924 init_xor_gate_extraction (
closure, &candidates);
3928 const uint64_t matched_before = s->congruent_matched_xors;
3929 const uint64_t gates_before = s->congruent_gates_xors;
3934 if (
solver->inconsistent)
3939 extract_xor_gates_with_base_clause (
closure, c);
3941 reset_xor_gate_extraction (
closure);
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;
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));
3960 START (extractites);
3961 references candidates;
3963 init_ite_gate_extraction (
closure, &candidates);
3966 const uint64_t matched_before = s->congruent_matched_ites;
3967 const uint64_t gates_before = s->congruent_gates_ites;
3969#ifdef MERGE_CONDITIONAL_EQUIVALENCES
3972 extract_ite_gates_of_variable (
closure, idx);
3973 if (
solver->inconsistent)
3980 if (
solver->inconsistent)
3985 extract_ite_gates_with_base_clause (
closure, c);
3988 reset_ite_gate_extraction (
closure);
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;
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));
4020 const uint64_t before = s->congruent_gates + s->congruent_matched;
4033 const uint64_t after = s->congruent_gates + s->congruent_matched;
4034 const uint64_t found = after - before;
4036 "found %" PRIu64
" gates (%.2f%% variables)", found,
4037 kissat_percent (found,
solver->active));
4048 unsigneds *marked = &
solver->analyzed;
4055 unsigned lit =
LIT (idx);
4056 for (
unsigned sign = 0;
sign != 2;
sign++,
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),
4072 bool failed = !learn_congruence_unit (
closure,
lit);
4073 unmark_all (marked, marks);
4084 unmark_all (marked, marks);
4099 unsigneds *
const marked = &
solver->analyzed;
4106 const unsigned lit =
LIT (idx);
4111 while (
p != end_lit_watches) {
4125 const unsigned not_lit =
NOT (
lit);
4129 while (
p != end_not_lit_watches) {
4134 if (not_lit > other)
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) {
4144 INC (congruent_equivalences);
4145 unmark_all (marked, marks);
4146 if (
solver->inconsistent)
4153 unmark_all (marked, marks);
4164 LOG (
"simplifying gates with RHS literal %s",
LOGLIT (
lit));
4168 if (!simplify_gate (
closure, g))
4174static bool rewrite_gates (
closure *
closure,
unsigned dst,
unsigned src) {
4176 LOG (
"rewriting gates with RHS literal %s",
LOGLIT (src));
4178 gates *src_occurrences = occurrences + src;
4179 gates *dst_occurrences = occurrences + dst;
4181 if (!rewrite_gate (
closure, g, dst, src))
4183 else if (!g->
garbage && gate_contains (g, dst))
4191 LOG (
"propagation of congruence unit %s",
LOGLIT (
lit));
4194 const unsigned not_lit =
NOT (
lit);
4200 LOG (
"propagation of congruence equivalence %s",
CLOGREPR (
lit));
4204 const unsigned lit_repr = find_repr (
closure,
lit);
4205 if (
solver->inconsistent)
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);
4216 const unsigned_array *
const trail = &
solver->trail;
4223static size_t propagate_units_and_equivalences (
closure *
closure) {
4228 size_t propagated = 0;
4232 unsigned lit = dequeue_next_scheduled_literal (
closure);
4246#ifndef KISSAT_NDEBUG
4248static void dump_closure_literal (
closure *
closure,
unsigned ilit) {
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);
4260 printf (
"@0=%d",
value);
4265 size_t i = 0, propagate =
closure->
units - trail->begin;
4267 printf (
"trail[%zu] ", i);
4270 fputs (
" <-- next unit to propagate", stdout);
4271 fputc (
'\n', stdout);
4279 unsigned lit =
LIT (idx);
4282 printf (
"repr[%u(%d)] = %u(%d)\n",
lit,
4283 kissat_export_literal (
solver,
lit), repr,
4284 kissat_export_literal (
solver, repr));
4289 const unsigned tag = g->
tag;
4305 printf (
"%p %s gate[%zu] ", (
void *) g, str, g->id);
4307 fputs (
" := ", stdout);
4310 fputs (
" ? ", stdout);
4312 fputs (
" : ", stdout);
4320 fputs (
" & ", stdout);
4322 fputs (
" ^ ", stdout);
4323 dump_closure_literal (
closure, rhs);
4326 fputs (g->
indexed ?
" removed" :
" indexed", stdout);
4328 fputs (
" garbage", stdout);
4329 fputc (
'\n', stdout);
4332#define LESS_GATE(G, H) ((G)->id < (H)->id)
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;
4371 const unsigned repr_lit = find_repr (
closure,
lit);
4372 const value value_repr_lit = values[repr_lit];
4374 if (value_repr_lit < 0)
4376 if (marks[repr_lit])
4379 marks[repr_lit] = 1;
4383 unsigned count_least_occurring = UINT_MAX;
4387 const unsigned repr_lit = find_repr (
closure,
lit);
4391 const size_t count = end -
p;
4393 if (count < count_least_occurring) {
4394 count_least_occurring = count;
4395 least_occurring_literal = repr_lit;
4401 clause *
const d = kissat_dereference_clause (
solver, d_ref);
4411 const unsigned repr_other = find_repr (
closure, other);
4412 if (!marks[repr_other])
4413 goto CONTINUE_WITH_NEXT_CLAUSE;
4416 goto FOUND_SUBSUMING;
4417 CONTINUE_WITH_NEXT_CLAUSE:;
4422 const unsigned repr_lit = find_repr (
closure,
lit);
4425 marks[repr_lit] = 0;
4431 INC (congruent_subsumed);
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);
4452#define RANKREFSIZE(REFSIZE) ((REFSIZE).size)
4454static void sort_references_by_clause_size (
kissat *
solver,
4455 refsizes *candidates) {
4468 unsigned count_matchable = 0;
4473 const unsigned lit =
LIT (idx);
4474 const unsigned repr = find_repr (
closure,
lit);
4477 const unsigned repr_idx =
IDX (repr);
4478 if (!matchable[idx]) {
4479 LOG (
"matchable %s", LOGVAR (idx));
4480 matchable[idx] =
true;
4485 if (!matchable[repr_idx]) {
4486 LOG (
"matchable %s", LOGVAR (repr_idx));
4487 matchable[repr_idx] =
true;
4494 "found %u matchable variables %.0f%%", count_matchable,
4495 kissat_percent (count_matchable,
solver->active));
4496 size_t potential = 0;
4497 refsizes candidates;
4499 clause *last_irredundant = kissat_last_irredundant_clause (
solver);
4502 unsigneds *marked = &
solver->analyzed;
4506 if (last_irredundant && last_irredundant < c)
4509 bool contains_matchable =
false;
4521 if (!contains_matchable) {
4522 const unsigned lit_idx =
IDX (
lit);
4523 if (matchable[lit_idx])
4524 contains_matchable =
true;
4526 const unsigned repr = find_repr (
closure,
lit);
4530 const unsigned not_repr =
NOT (repr);
4531 if (marks[not_repr]) {
4541 for (
all_stack (
unsigned, repr, *marked))
4546 if (!contains_matchable) {
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));
4564 sort_references_by_clause_size (
solver, &candidates);
4566 size_t tried = 0, subsumed = 0;
4576 if (find_subsuming_clause (
closure, c)) {
4583 "subsumed %zu clauses out of %zu tried %.0f%%", subsumed,
4584 tried, kissat_percent (subsumed, tried));
4592 if (
solver->inconsistent)
4620 size_t propagated = propagate_units_and_equivalences (&
closure);
4621 if (!
solver->inconsistent && propagated &&
4623 forward_subsume_matching_clauses (&
closure);
4631 unsigned equivalent = reset_repr (&
closure);
4633 "merged %u equivalent variables %.2f%%", equivalent,
4634 kissat_percent (equivalent,
solver->active));
4637 solver->active -= equivalent;
4638 REPORT (!equivalent,
'c');
4639 if (!
solver->inconsistent)
4640 solver->active += equivalent;
4642 if (kissat_average (equivalent,
solver->active) < 0.001)
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
void kissat_free(kissat *solver, void *ptr, size_t bytes)
void kissat_learned_unit(kissat *solver, unsigned lit)
ABC_NAMESPACE_HEADER_START typedef uint64_t generator
#define all_stack(T, E, S)
#define SET_END_OF_STACK(S, P)
#define all_pointers(T, E, S)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define CHECK_AND_ADD_STACK(...)
#define CHECK_AND_ADD_EMPTY(...)
#define REMOVE_CHECKER_STACK(...)
void kissat_connect_referenced(kissat *solver, reference ref)
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
void kissat_new_binary_clause(kissat *solver, unsigned first, unsigned second)
void kissat_connect_clause(kissat *solver, clause *c)
void kissat_new_unwatched_binary_clause(kissat *solver, unsigned first, unsigned second)
void kissat_delete_binary(kissat *solver, unsigned a, unsigned b)
struct gate_hash_table gate_hash_table
#define add_ite_matching_proof_chain(...)
#define CLOGITEGATE(G,...)
#define check_ite_lits_normalized
#define SMALLER_NEGATED_BIN_COUNT(A, B)
#define check_and_gate_implied(...)
bool kissat_congruence(kissat *solver)
#define add_xor_shrinking_proof_chain(...)
#define add_ite_turned_and_binary_clauses
#define CLOGANDGATE(G,...)
#define MAX_HASH_TABLE_SIZE
void reset_gate_hash_table(closure *closure)
#define check_xor_lits_normalized
#define CLOGXORGATE(G,...)
#define check_and_lits_normalized
#define delete_proof_chain(...)
#define check_ite_implied
#define RANKREFSIZE(REFSIZE)
#define check_lits_sorted(...)
#define all_rhs_literals_in_gate(LIT, G)
#define add_xor_matching_proof_chain(...)
#define check_ite_gate_implied
#define check_xor_gate_implied
void kissat_enter_dense_mode(kissat *solver, litpairs *irredundant)
void kissat_resume_sparse_mode(kissat *solver, bool flush_eliminated, litpairs *irredundant)
#define DEQUEUE_FIFO(F, E)
#define ENQUEUE_FIFO(T, F, E)
#define all_variables(IDX)
#define all_literals(LIT)
#define REDUCE_DELAY(NAME)
#define all_literals_in_clause(LIT, C)
#define KISSAT_assert(ignore)
#define SORT_STACK(TYPE, S, LESS)
#define SORT(TYPE, N, A, LESS)
#define LOGCOUNTEDLITS(...)
#define LOGUNSIGNEDS2(...)
bool is_power_of_two(unsigned n)
#define kissat_verbose(...)
#define kissat_extremely_verbose(...)
#define kissat_very_verbose(...)
#define kissat_phase(...)
#define ADD_EMPTY_TO_PROOF(...)
#define ADD_STACK_TO_PROOF(...)
#define DELETE_STACK_FROM_PROOF(...)
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
#define RADIX_SORT(VTYPE, RTYPE, N, V, RANK)
ABC_NAMESPACE_HEADER_START typedef unsigned reference
#define IRREDUNDANT_CLAUSES
#define kissat_check_statistics(...)
uint64_t nonces[SIZE_NONCES]
#define congruence_terminated_10
#define congruence_terminated_4
#define congruence_terminated_5
#define congruence_terminated_2
#define congruence_terminated_7
#define congruence_terminated_3
#define congruence_terminated_12
#define congruence_terminated_8
#define congruence_terminated_9
#define congruence_terminated_6
#define congruence_terminated_11
#define congruence_terminated_1
ABC_NAMESPACE_IMPL_START void kissat_flush_trail(kissat *solver)
#define smaller(tree, n, m, depth)
void kissat_flush_all_connected(kissat *solver)
#define BEGIN_WATCHES(WS)