30 const int lhs = g->
lhs;
31 const int cond = g->
rhs [0];
32 const int then_lit = g->
rhs[1];
33 const int else_lit = g->
rhs[2];
43 if (lhs == then_lit) {
47 if (lhs == else_lit) {
63 const int lhs = g->
lhs;
64 const int cond = g->
rhs [0];
65 const int then_lit = g->
rhs[1];
66 const int else_lit = g->
rhs[2];
84 if (lhs == then_lit) {
88 if (lhs == else_lit) {
105static size_t hash_lits (std::array<int, 16> &nonces,
108 const auto end_nonces = end (nonces);
109 const auto begin_nonces = begin (nonces);
110 auto n = begin_nonces;
111 for (
auto lit : lits) {
114 hash = (hash << 4) | (hash >> 60);
128 return find (begin (g->
rhs), end (g->
rhs),
lit) != end (g->
rhs);
134 return ((uint64_t) a.
lit1 << 32) + a.
lit2;
147 const auto offset = offsize.first;
148 const auto size = offsize.second;
149 const auto begin = std::begin (
binaries) + offset;
150 const auto end = std::begin (
binaries) + size;
155 bool found = (it != end && it->lit1 ==
lit && it->lit2 == other);
157 LOG (
"found binary [%zd] %d %d", it->id,
lit, other);
165 if (!
internal->opts.congruencebinaries)
167 START (extractbinaries);
182 const bool already_sorted =
185 already_sorted ?
lit : other,
186 already_sorted ? other :
lit));
193 const size_t size =
binaries.size ();
209 size_t extracted = 0, already_present = 0, duplicated = 0;
211 const size_t size =
internal->clauses.size ();
212 for (
size_t i = 0; i < size; ++i) {
222 const int a =
lits[0];
223 const int b =
lits[1];
224 const int c =
lits[2];
240 LOG (d,
"strengthening");
260 const size_t new_size =
binaries.size ();
263 for (
size_t j = 1; j < new_size; ++j) {
279 STOP (extractbinaries);
280 LOG (
"extracted %zu binaries (plus %zu already present and %zu "
282 extracted, already_present, duplicated);
302 LOG (c,
"mu1 %d -> %zd",
lit, c->
id);
310 LOG (c,
"mu2 %d -> %zd",
lit, c->
id);
318 LOG (c,
"mu4 %d -> %zd",
lit, c->
id);
353 if (abs (a) == abs (
except))
355 else if (abs (a) == abs (
lhs))
378 if (abs (a) == abs (
lhs) && abs (b) != abs (
lhs))
380 if (abs (a) != abs (
lhs) && abs (b) == abs (
lhs))
446 }
while (nxt != res);
452 LOG (
"finding representative of %d",
lit);
460 LOG (
"updating %d -> %d", res, nxt);
461 }
while (nxt != res);
463 if (path_length > 2) {
464 LOG (
"learning new rewriting from %d to %d (current path length: %d)",
465 lit, res, path_length);
480 }
else if (path_length == 2) {
482 LOG (
"updating information %d -> %d in eager",
lit, res);
493 LOG (
"representative of %d is %d",
lit, res);
511 }
while (nxt != res);
526 }
while (nxt != res);
530 if (path_length > 2) {
531 LOG (
"learning new rewriting from %d to %d (current path length: %d)",
532 lit, res, path_length);
533 std::vector<LRAT_ID> tmp_lrat_chain;
549 }
else if (path_length == 2) {
550 LOG (
"duplicated information %d -> %d to eager with clause %" PRIu64,
574 LOG (
"production of LRAT chain for %d with representative %" PRIu64,
lit,
588 }
while (nxt != res);
593 LOG (
"production of LRAT chain for %d with representative %" PRIu64,
lit,
607 }
while (nxt != res);
614#ifndef CADICAL_NDEBUG
618 LOG (
"checking for existing LRAT chain for %d with clause %" PRIu64,
lit,
628#ifndef CADICAL_NDEBUG
632 LOG (
"checking for existing LRAT chain for %d with clause %" PRIu64,
lit,
657 LOG (g,
"marking as garbage");
666 (*git)->indexed =
false;
667 LOG ((*git),
"removing from hash table");
679 LOG (g,
"removing from hash table");
688 LOG (g,
"adding to hash table");
694 std::vector<LitClausePair> &litIds,
int except_lhs,
bool remove_units) {
696 for (
auto &litId : litIds) {
703 std::remove_if (begin (litIds), end (litIds),
704 [] (
const LitClausePair &
p) {
return !
p.clause; }),
709 std::vector<LitClausePair> &litIds,
int except_lhs,
710 size_t &old_position1,
size_t &old_position2,
bool remove_units) {
714 for (
size_t i = 0; i < litIds.size (); ++i) {
717 litIds[i].
clause, except_lhs, remove_units);
718 litIds[j].current_lit =
720 if (i == old_position1) {
726 if (i == old_position2) {
743 bool changed =
false;
745 for (
auto lit : *c) {
746 LOG (
"checking if %d is required",
lit);
754 if (
lit == except ||
lit == -except) {
761 LOG (
"found unit %d, removing it", -
lit);
767 LOG (
"found unit %d, but ignoring it", -
lit);
771 LOG (
"found positive unit, so clause is subsumed by unit");
776 const bool neg_marked =
internal->marked2 (-other);
781 LOG (
"tautology due to %d -> %d",
lit, other);
784 LOG (
"%d -> %d already in",
lit, other);
785 }
else if (
lit != other) {
794 for (
auto lit : *c) {
804 LOG (
"generated clause is a tautology");
807 }
else if (changed &&
clause.size () == 1) {
810 LOG (c,
"oops this should not happen");
823 internal->external->check_learned_clause ();
826 const int size = (int)
clause.size ();
858 for (
int i = 0; i < size; i++)
867 LOG (c,
"new pointer %p", (
void *) c);
903 std::vector<LitClausePair> &litIds,
int except_lhs,
bool remove_units) {
905 for (
auto &litId : litIds) {
915 bool remove_units,
bool fail_on_unit) {
920 LOG (c,
"rewriting clause for LRAT proof, except for rewriting %d",
924 bool changed =
false;
926 for (
auto lit : *c) {
927 LOG (
"checking if %d is required",
lit);
935 if (
lit == except_lhs ||
lit == -except_lhs) {
942 LOG (
"found unit %d, removing it", -
lit);
948 LOG (
"found unit %d, but ignoring it", -
lit);
951 LOG (
"found positive unit %d, so clause is subsumed by unit",
lit);
957 const bool neg_marked =
internal->marked2 (-other);
962 LOG (
"tautology due to %d -> %d",
lit, other);
965 LOG (
"%d -> %d already in",
lit, other);
966 }
else if (
lit != other) {
975 for (
auto lit : *c) {
987 LOG (
"generated clause is a tautology");
990 }
else if (changed &&
clause.size () == 1) {
998 }
else if (changed) {
1001 LOG (d,
"rewritten clause to");
1003 LOG (c,
"clause is unchanged, so giving up");
1015 LOG (
"adding reason %zd for rewriting %d marked",
1021 std::vector<LRAT_ID> &
chain,
1022 bool insert_id_after,
1027 "computing normalized LRAT chain for clause to produce unit, "
1028 "rewriting except for %d (%" PRIu64
", %" PRIu64
") and %d (%" PRIu64
1029 ", %" PRIu64
") and skipping %d and %d",
1031 rewrite2.
id2, except_lhs, except_lhs2);
1033 std::vector<LRAT_ID>
units, rewriting;
1034 for (
auto other : *c) {
1038 if (other == except_lhs || other == -except_lhs) {
1040 }
else if (other == except_lhs2 || other == -except_lhs2) {
1042 }
else if (
internal->val (other) < 0) {
1043 LOG (
"found unit %d", -other);
1045 units.push_back (
id);
1046 }
else if (other == rewrite1.
src && rewrite1.
id1) {
1048 }
else if (other == -rewrite1.
src && rewrite1.
id2) {
1050 }
else if (other == rewrite2.
src && rewrite2.
id1) {
1052 }
else if (other == -rewrite2.
src && rewrite2.
id2) {
1055#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
1058 LOG (
"reason for representative of %d %d is %" PRIu64
"", other,
1063 LOG (
"no rewriting needed for %d", other);
1066 for (
auto id :
units)
1067 chain.push_back (
id);
1069 if (!insert_id_after)
1071 for (
auto id : rewriting)
1072 chain.push_back (
id);
1074 if (insert_id_after)
1082 std::vector<LRAT_ID> &
chain,
1083 bool insert_id_after,
1088 "computing normalized LRAT chain for clause, rewriting except for "
1089 "%d (%" PRIu64
", %" PRIu64
") and %d (%" PRIu64
", %" PRIu64
1090 ") and skipping %d and %d",
1092 rewrite2.
id2, except_lhs, except_lhs2);
1094 if (!insert_id_after)
1096 for (
auto other : *c) {
1100 if (other == except_lhs) {
1102 }
else if (other == except_lhs2) {
1104 }
else if (
internal->val (other) < 0) {
1105 LOG (
"found unit %d", -other);
1108 chain.push_back (
id);
1109 }
else if (other == rewrite1.
src && rewrite1.
id1) {
1111 }
else if (other == -rewrite1.
src && rewrite1.
id2) {
1113 }
else if (other == rewrite2.
src && rewrite2.
id1) {
1115 }
else if (other == -rewrite2.
src && rewrite2.
id2) {
1119 LOG (
"no rewriting needed for %d", other);
1122 if (insert_id_after)
1136 const std::vector<LitClausePair> &reasons) {
1137 for (
auto litId : reasons) {
1138 LOG (litId.clause,
"found lrat in gate %d from %zd", litId.current_lit,
1142 LOG (
lrat_chain,
"chain from %zd reasons", reasons.size ());
1150 LOG (
"calculating LRAT chain learn_congruence_unit_when_lhs_set");
1171 Gate *g,
int src,
int dst,
int clashing,
int falsified,
int unit) {
1177 std::vector<LRAT_ID> proof_chain;
1181 LOG (
"clashing %d where -lhs=%d", clashing, -g->
lhs);
1185 if (clashing == -g->
lhs) {
1188 "found lrat in gate %d from %zd (looking for %d)",
1189 litId.current_lit, litId.clause->id, falsified);
1190 if (litId.current_lit == clashing) {
1205 LOG (
"%d %d %d", src, dst, g->
lhs);
1206 if (src == g->
lhs || dst == g->
lhs) {
1207 LOG (
"degenerated AND gate with dst=lhs");
1209 LOG (litId.clause,
"definition clause %d ->",
1211 if (litId.current_lit == clashing) {
1215 LOG (proof_chain,
"produced lrat chain so far");
1220 LOG (
"degenerated AND gate with conflict without LHS");
1222 LOG (litId.clause,
"definition clause %d ->",
1227 LOG (proof_chain,
"produced lrat chain so far");
1231 LOG (
"normal AND gate");
1234 proof_chain,
false,
Rewrite (),
1236 LOG (proof_chain,
"produced lrat chain so far");
1240 LOG (proof_chain,
"produced lrat chain");
1241 }
else if (falsified) {
1242 LOG (
"falsifies %d", falsified);
1248 "found lrat in gate %d from %zd (looking for %d)",
1249 litId.current_lit, litId.clause->id, falsified);
1250 if (litId.current_lit == falsified ||
1251 (litId.current_lit == src && dst == falsified)) {
1253 proof_chain,
true,
Rewrite (),
1264 LOG (proof_chain,
"produced lrat chain");
1278 LOG (
"fully propagating");
1281 bool no_conflict =
internal->propagate ();
1296 LOG (
"already set lit %d",
lit);
1299 if (force_propagation)
1304 ++
internal->stats.congruence.units;
1310 internal->lrat_chain.push_back (
id);
1312 internal->lrat_chain.push_back (
id);
1324 if (delay_propagation)
1334 const std::vector<LRAT_ID> &extra_reasons_lit,
1335 const std::vector<LRAT_ID> &extra_reasons_ulit) {
1347 LOG (
"merging literals %d [=%d] and %d [=%d]",
lit, repr_lit, other,
1350 if (repr_lit == repr_other) {
1351 LOG (
"already merged %d and %d",
lit, other);
1358 const int val_other =
internal->val (other);
1360 if (val_lit == val_other) {
1361 LOG (
"not merging lits %d and %d assigned to same value",
lit, other);
1386 int smaller_repr = repr_lit;
1387 int larger_repr = repr_other;
1390 const std::vector<LRAT_ID> *smaller_chain = &extra_reasons_ulit;
1391 const std::vector<LRAT_ID> *larger_chain = &extra_reasons_lit;
1393 if (abs (smaller_repr) > abs (larger_repr)) {
1394 swap (smaller_repr, larger_repr);
1396 swap (smaller_chain, larger_chain);
1401 if (
lit == -other) {
1403 LOG (
"merging clashing %d and %d",
lit, other);
1406 for (
auto id : *smaller_chain)
1413 internal->lrat_chain.push_back (
id);
1414 for (
auto id : *larger_chain)
1415 internal->lrat_chain.push_back (
id);
1424 LOG (
"merging %d and %d first and then the equivalences of %d and %d "
1426 lit, other, repr_lit, repr_other);
1427 Clause *eq1_tmp =
nullptr;
1434 Clause *eq2_tmp =
nullptr;
1447 if (repr_lit == -repr_other) {
1456 rew2 =
Rewrite (other == repr_other ? 0 : other, repr_other,
1463 internal->assign_unit (-larger_repr);
1467 if (larger != larger_repr)
1471 larger != larger_repr ? larger_repr : 0);
1482 if (val_lit == val_other) {
1483 LOG (
"not merging lits %d and %d assigned to same value",
lit, other);
1488 if (val_lit == -val_other) {
1489 LOG (
"merging lits %d and %d assigned to inconsistent value",
lit,
1493 Clause *c = val_lit ? eq2_tmp : eq1_tmp;
1494 int pos = val_lit ? other :
lit;
1495 int neg = val_lit ? -
lit : -other;
1507 LOG (
"merging assigned %d and unassigned %d",
lit, other);
1509 const int unit = (val_lit < 0) ? -other : other;
1532 if (!val_lit && val_other) {
1533 LOG (
"merging assigned %d and unassigned %d",
lit, other);
1535 const int unit = (val_other < 0) ? -
lit :
lit;
1558 Clause *eq1_repr, *eq2_repr;
1559 if (smaller_repr !=
smaller || larger != larger_repr) {
1564 smaller_repr !=
smaller ? smaller_repr : 0,
1568 Rewrite (larger_repr != larger ? larger : 0,
1569 larger_repr != larger ? larger_repr : 0,
1587 if (smaller_repr !=
smaller || larger != larger_repr) {
1594 smaller_repr !=
smaller ? smaller_repr : 0,
1598 Rewrite (larger_repr != larger ? larger : 0,
1599 larger_repr != larger ? larger_repr : 0,
1618 CADICAL_assert (std::find (begin (*eq1_repr), end (*eq1_repr), -larger_repr) !=
1621 CADICAL_assert (std::find (begin (*eq2_repr), end (*eq2_repr), larger_repr) !=
1624 LOG (
"updating %d -> %d", larger_repr, smaller_repr);
1628 ++
internal->stats.congruence.congruent;
1637 int lit,
int other,
const std::vector<LRAT_ID> &extra_reasons_lit,
1638 const std::vector<LRAT_ID> &extra_reasons_ulit) {
1647 LOG (
"merging literals %s [=%d] and %s [=%d]",
LOGLIT (
lit), repr_lit,
1648 LOGLIT (other), repr_other);
1651 if (repr_lit == repr_other) {
1659 const int val_other =
internal->val (other);
1679 int smaller_repr = repr_lit;
1680 int larger_repr = repr_other;
1681 int val_smaller = val_lit;
1682 int val_larger = val_other;
1685 const std::vector<LRAT_ID> *smaller_chain = &extra_reasons_ulit;
1686 const std::vector<LRAT_ID> *larger_chain = &extra_reasons_lit;
1688 if (abs (smaller_repr) > abs (larger_repr)) {
1689 swap (smaller_repr, larger_repr);
1691 swap (smaller_chain, larger_chain);
1692 swap (val_smaller, val_larger);
1697 if (
lit == -other) {
1698 LOG (
"merging clashing %d and %d",
lit, other);
1701 internal->lrat_chain = *smaller_chain;
1710 for (
auto id : *larger_chain)
1711 internal->lrat_chain.push_back (
id);
1719 (val_smaller < 0 ? *smaller_chain : *larger_chain);
1728 if (val_lit && val_lit == val_other) {
1729 LOG (
"not merging lits %d and %d assigned to same value",
lit, other);
1733 if (val_lit && val_lit == -val_other) {
1738 internal->unit_id (val_larger < 0 ? -larger : larger));
1739 for (
auto id : (val_smaller < 0 ? *smaller_chain : *larger_chain)) {
1740 internal->lrat_chain.push_back(
id);
1747 LOG (
"merging %d and %d first and then the equivalences of %d and %d "
1749 lit, other, repr_lit, repr_other);
1750 Clause *eq1_tmp =
nullptr;
1758 Clause *eq2_tmp =
nullptr;
1772 if (repr_lit == -repr_other) {
1781 rew2 =
Rewrite (other == repr_other ? 0 : other, repr_other,
1791 internal->assign_unit (-larger_repr);
1795 if (larger != larger_repr)
1801 larger != larger_repr ? larger_repr : 0);
1817 if (val_lit == val_other) {
1818 LOG (
"not merging lits %d and %d assigned to same value",
lit, other);
1823 if (val_lit == -val_other) {
1824 LOG (
"merging lits %d and %d assigned to inconsistent value",
lit,
1828 Clause *c = val_lit ? eq2_tmp : eq1_tmp;
1829 int pos = val_lit ? other :
lit;
1830 int neg = val_lit ? -
lit : -other;
1842 LOG (
"merging assigned %d and unassigned %d",
lit, other);
1844 const int unit = (val_lit < 0) ? -other : other;
1867 if (!val_lit && val_other) {
1868 LOG (
"merging assigned %d and unassigned %d",
lit, other);
1870 const int unit = (val_other < 0) ? -
lit :
lit;
1894 Clause *eq1_repr, *eq2_repr;
1895 if (smaller_repr !=
smaller || larger != larger_repr) {
1900 smaller_repr !=
smaller ? smaller_repr : 0,
1904 Rewrite (larger_repr != larger ? larger : 0,
1905 larger_repr != larger ? larger_repr : 0,
1923 if (smaller_repr !=
smaller || larger != larger_repr) {
1930 smaller_repr !=
smaller ? smaller_repr : 0,
1934 Rewrite (larger_repr != larger ? larger : 0,
1935 larger_repr != larger ? larger_repr : 0,
1952 CADICAL_assert (std::find (begin (*eq1_repr), end (*eq1_repr), -larger_repr) !=
1957 CADICAL_assert (std::find (begin (*eq2_repr), end (*eq2_repr), larger_repr) !=
1960 LOG (
"updating %d -> %d", larger_repr, smaller_repr);
1964 ++
internal->stats.congruence.congruent;
1976 LOG (c,
"turning redundant subsuming clause into irredundant clause");
1980 internal->stats.current.irredundant++;
1981 internal->stats.added.irredundant++;
1984 internal->stats.current.redundant--;
2015 LOG (
"merging literals %d [=%d] and %d [=%d] lrat",
lit, repr_lit, other,
2018 if (repr_lit == repr_other) {
2019 LOG (
"already merged %d and %d",
lit, other);
2023 const int val_other =
internal->val (other);
2026 if (val_lit == val_other) {
2027 LOG (
"not merging lits %d and %d assigned to same value",
lit, other);
2030 if (val_lit == -val_other) {
2034 LOG (
"merging lits %d and %d assigned to inconsistent value",
lit,
2041 LOG (
"merging assigned %d and unassigned %d",
lit, other);
2042 const int unit = (val_lit < 0) ? -other : other;
2053 if (!val_lit && val_other) {
2054 LOG (
"merging assigned %d and unassigned %d", other,
lit);
2055 const int unit = (val_other < 0) ? -
lit :
lit;
2058 internal->unit_id (val_other < 0 ? -other : other));
2067 int smaller_repr = repr_lit;
2068 int larger_repr = repr_other;
2072 if (abs (smaller_repr) > abs (larger_repr)) {
2073 swap (smaller_repr, larger_repr);
2080 if (repr_lit == -repr_other) {
2081 LOG (
"merging clashing %d [=%d] and %d[=%d], smaller: %d",
lit,
2082 repr_lit, other, repr_other,
smaller);
2089 other, other == repr_other ? 0 : repr_other,
2102 if (
lit != repr_lit) {
2107 if (other != repr_other) {
2118 LOG (
"merging %d [=%d] and %d [=%d]",
lit, repr_lit, other, repr_other);
2120 bool learn_clause = (
lit != repr_lit) || (other != repr_other);
2123 if (
lit != repr_lit) {
2124 LOG (
"adding chain for lit %d -> %d",
lit, repr_lit);
2127 if (other != repr_other) {
2128 LOG (
"adding chain for lit %d -> %d", -other, -repr_other);
2137 if (
lit != repr_lit)
2139 if (other != repr_other)
2146 if (smaller_repr == repr_lit) {
2166 LOG (
"not learning new clause, using already existing one");
2167 if (smaller_repr == repr_lit) {
2168 LOG (
"setting ids of %d: %" PRIu64
"; %d: %" PRIu64
" (case 1)",
2169 larger, id1, -larger, id2);
2173 LOG (
"setting ids of %d: %" PRIu64
"; %d: %" PRIu64
" (case 2)",
2174 larger, id2, -larger, id1);
2180 LOG (
"updating %d -> %d", larger_repr, smaller_repr);
2184 ++
internal->stats.congruence.congruent;
2192 LOG (g,
"connect %d to",
lit);
2223#ifndef CADICAL_NDEBUG
2225 it.current_lit = 0, it.clause =
nullptr;
2227 it.current_lit = 0, it.clause =
nullptr;
2229 it.current_lit = 0, it.clause =
nullptr;
2242 n = 1 | rand.
next ();
2252 LOG (
"[gate-extraction]");
2275 LOG (g,
"checking implied");
2276 const int lhs = g->
lhs;
2277 const int not_lhs = -lhs;
2278 for (
auto other : g->
rhs)
2292 LOG (
"starting deletion of proof chain");
2300 LOG (
"reading %d from chain",
lit);
2308 id = ((
LRAT_ID) id1 << 32) + id2;
2312 LOG (
"found %d as literal in chain",
lit);
2323 LOG (
"finished deletion of proof chain");
2332 const int lhs = g->
lhs;
2353 g->
rhs[0] = falsifies;
2355 }
else if (clashing) {
2356 LOG (g,
"gate before clashing on %d", clashing);
2358 g->
rhs[0] = clashing;
2359 g->
rhs[1] = -clashing;
2361 LOG (g,
"gate after clashing on %d", clashing);
2368 std::vector<LRAT_ID> &extra_reasons_lit,
2369 std::vector<LRAT_ID> &extra_reasons_ulit) {
2370 LOG (
"generate chain for gate boiling down to unit");
2380 extra_reasons_ulit,
true,
Rewrite ());
2392 if (repr_lit == repr_other) {
2393 LOG (
"skipping already merged");
2398 extra_reasons_ulit,
true,
Rewrite (),
2400 LOG (extra_reasons_ulit,
"lrat chain for negative side");
2407 litId.clause,
Rewrite (src, dst, id1, id2), extra_reasons_lit,
true,
2409 LOG (extra_reasons_lit,
"lrat chain for positive side");
2413 Gate *g,
Gate *h, std::vector<LRAT_ID> &extra_reasons_lit,
2414 std::vector<LRAT_ID> &extra_reasons_ulit,
bool remove_units) {
2426 if (g_tautology && h_tautology) {
2427 LOG (
"both gates are a tautology");
2431 if (litId.current_lit == h->
lhs) {
2433 LOG (litId.clause,
"binary clause to push into the reason");
2437 extra_reasons_lit.push_back (litId.clause->id);
2444 if (litId.current_lit == g->
lhs) {
2447 LOG (litId.clause,
"binary clause to push into the reason");
2451 extra_reasons_ulit.push_back (litId.clause->id);
2458 if (g_tautology || h_tautology) {
2462 Gate *tauto = (g_tautology ? g : h);
2463 Gate *other = (g_tautology ? h : g);
2464 LOG (tauto,
"one gate is a tautology");
2468 auto &extra_reasons_tauto =
2469 (!g_tautology ? extra_reasons_lit : extra_reasons_ulit);
2470 auto &extra_reasons_other =
2471 (!g_tautology ? extra_reasons_ulit : extra_reasons_lit);
2475 if (litId.current_lit == tauto->
lhs) {
2478 LOG (litId.clause,
"binary clause to push into the reason");
2480 litId.clause, other->
lhs, remove_units);
2482 extra_reasons_tauto.push_back (litId.clause->id);
2488 LOG (tauto,
"now the other direction");
2492 "binary clause from %d to push into the reason [avoiding %d]",
2493 litId.current_lit, tauto->
lhs);
2494 if (litId.current_lit != tauto->
lhs) {
2495 LOG (litId.clause,
"binary clause to push into the reason");
2498 litId.clause, tauto->
lhs, remove_units);
2502 extra_reasons_other.push_back (litId.clause->id);
2538 LOG (extra_reasons_ulit,
"lrat chain for negative side");
2544 LOG (extra_reasons_lit,
"lrat chain for positive side");
2551 int falsifies,
int clashing) {
2552 LOG (g,
"update and gate of arity %ld", g->
arity ());
2555 if (falsifies || clashing) {
2562 else if (unit == -src)
2567 }
else if (g->
arity () == 1) {
2583 std::vector<LRAT_ID> extra_reasons_lit;
2584 std::vector<LRAT_ID> extra_reasons_ulit;
2588 extra_reasons_ulit);
2590 extra_reasons_ulit)) {
2591 ++
internal->stats.congruence.unaries;
2592 ++
internal->stats.congruence.unary_and;
2602 std::vector<LRAT_ID> extra_reasons_lit2;
2603 std::vector<LRAT_ID> extra_reasons_ulit2;
2606 extra_reasons_ulit2);
2608 extra_reasons_ulit2))
2612 LOG (g,
"removing from table");
2613 (void)
table.erase (it);
2616 LOG (g,
"inserting gate into table");
2633 LOG (g,
"updating");
2638 if (g->
arity () == 0) {
2654 internal->lrat_chain.push_back (
id);
2661 }
else if (g->
arity () == 1) {
2662 std::vector<LRAT_ID> reasons_implication, reasons_back;
2668 reasons_implication.push_back (g->
pos_lhs_ids[0].clause->id);
2669 reasons_back.push_back (g->
pos_lhs_ids[1].clause->id);
2685 g->
lhs, g->
rhs[0], reasons_implication,
2687 ++
internal->stats.congruence.unaries;
2688 ++
internal->stats.congruence.unary_and;
2695 std::vector<LRAT_ID> reasons_implication, reasons_back;
2697 reasons_implication, reasons_back);
2707 LOG (g,
"reinserting in table");
2725 LOG (g,
"simplifying");
2727 std::vector<int>::iterator it = begin (g->
rhs);
2728 bool ulhs_in_rhs =
false;
2729 for (
auto lit : g->
rhs) {
2749 for (
size_t j = 0; j < size; ++j) {
2750 LOG (
"looking at %d [%ld %ld]", g->
pos_lhs_ids[j].current_lit, i, j);
2756 LOG (
"keeping %d [%ld %ld]", g->
pos_lhs_ids[i].current_lit, i, j);
2759 LOG (
"resizing to %ld", i);
2766 LOG (g,
"shrunken");
2769 g->
rhs.resize (it - std::begin (g->
rhs));
2772 LOG (g,
"shrunken");
2774 std::vector<LRAT_ID> reasons_lrat_src, reasons_lrat_usrc;
2777 ++
internal->stats.congruence.simplified_ands;
2778 ++
internal->stats.congruence.simplified;
2784 if (litId.current_lit == g->
lhs) {
2815 for (
Gate *g : occs) {
2846 const auto &its =
table.equal_range (g);
2848 for (
auto it = its.first; it != its.second; ++it) {
2849 LOG ((*it),
"checking gate in the table");
2853 if ((*it)->tag != g->
tag)
2855 if ((*it)->rhs != g->
rhs)
2862 LOG (g,
"searching");
2863 LOG (h,
"already existing");
2869 LOG (g->
rhs,
"gate not found in table");
2877 auto &
lits = this->lits;
2898 std::vector<LRAT_ID> result;
2900 back_inserter (result),
2902 LOG (result,
"lrat chain positive (%d):", lhs);
2905 back_inserter (result),
2907 LOG (result,
"lrat chain negative (%d):", lhs);
2915 std::vector<LRAT_ID> reasons_lrat_src, reasons_lrat_usrc;
2920 reasons_lrat_usrc)) {
2921 LOG (
"found merged literals");
2936 ++
internal->stats.congruence.gates;
2940 LOG (g,
"creating new");
2941 for (
auto lit : g->
rhs) {
2950 const int not_lhs = -lhs;
2951 LOG (
"trying to find AND gate with first LHS %d", (lhs));
2952 LOG (
"negated LHS %d occurs in %zd binary clauses", (not_lhs),
2954 unsigned matched = 0;
2956 const size_t arity =
lits.size () - 1;
2958 for (
auto w :
internal->watches (not_lhs)) {
2959 LOG (w.clause,
"checking clause for candidates");
2962 CADICAL_assert (w.clause->literals[0] == -lhs || w.clause->literals[1] == -lhs);
2963 const int other = w.blit;
2966 LOG (
"marking %d mu2", other);
2970 internal->analyzed.push_back (other);
2977 LOG (
"found %zd initial LHS candidates",
internal->analyzed.size ());
2978 if (matched < arity) {
3007 LOG (
"learning binary clause %d %d", a, b);
3013 const signed char a_value =
internal->val (a);
3016 const signed char b_value =
internal->val (b);
3022 else if (a_value < 0 && !b_value) {
3024 }
else if (!a_value && b_value < 0)
3027 LOG (
"clause reduced to unit %d", unit);
3046 Clause *res =
internal->new_hyper_ternary_resolved_clause_and_watch (
3050 already_sorted ? b : a));
3053 LOG (res,
"learning clause");
3064#ifndef CADICAL_NDEBUG
3081 LOG (c,
"promoting tmp");
3082#ifndef CADICAL_NDEBUG
3090 LOG (res,
"promoted to");
3098 LOG (
"learning tmp binary clause %d %d", a, b);
3118 LOG (res,
"promoted to");
3123 const int not_lhs = -lhs;
3125 if (
marked (not_lhs) < 2) {
3126 LOG (
"skipping no-candidate LHS %d (%d)", lhs,
marked (not_lhs));
3130 LOG (
"trying to find AND gate with remaining LHS %d", (lhs));
3131 LOG (
"negated LHS %d occurs times in %zd binary clauses", (not_lhs),
3134 const size_t arity =
lits.size () - 1;
3138 for (
auto w :
internal->watches (not_lhs)) {
3142 LOG (c,
"checking");
3146 const int other = w.blit;
3153 LOG (
"pushing %d -> %zd", other, w.clause->id);
3156 LOG (
"marking %d mu4", other);
3165 auto q = begin (
internal->analyzed);
3170 if (
lit == not_lhs) {
3180 LOG (
"keeping LHS candidate %d", -
lit);
3182 LOG (
"dropping LHS candidate %d", -
lit);
3189 LOG (
"after filtering %zu LHS candidate remain",
3193 if (matched < arity) {
3209 uint64_t res =
internal->noccs (-a);
3228 LOG (c,
"extracting and gates with clause");
3230 const unsigned arity_limit =
3232 const unsigned size_limit = arity_limit + 1;
3233 size_t max_negbincount = 0;
3236 for (
int lit : *c) {
3244 LOG (c,
"found satisfied clause");
3250 if (++size > size_limit) {
3251 LOG (c,
"clause is actually too large, thus skipping");
3259 "%d negated does not occur in any binary clause, thus skipping",
3266 if (count > max_negbincount)
3267 max_negbincount = count;
3272 LOG (c,
"is actually too small, thus skipping");
3279 const size_t arity = size - 1;
3280 if (max_negbincount < arity) {
3282 "all literals have less than %lu negated occurrences"
3292 const size_t clause_size =
lits.size ();
3293 for (
size_t i = 0; i < clause_size; ++i) {
3298 if (count < arity) {
3302 }
else if (reduced == i)
3306 const size_t reduced_size = clause_size - reduced;
3308 LOG (c,
"trying as base arity %lu AND gate", arity);
3311 begin (
lits) + reduced_size,
3315 unsigned extracted = 0;
3317 for (
size_t i = 0; i < clause_size; ++i) {
3323 const int lhs =
lits[i];
3324 LOG (
"trying LHS candidate literal %d with %ld negated occurrences",
3334 }
else if (
internal->analyzed.empty ()) {
3335 LOG (
"early abort AND gate search");
3344 LOG (
lits,
"finish unmarking");
3350 LOG (c,
"extracted %u with arity %lu AND base", extracted, arity);
3362 START (extractands);
3366 const size_t size =
internal->clauses.size ();
3367 for (
size_t i = 0; i < size && !
internal->terminated_asynchronously ();
3402 for (
auto lit : lits)
3409 for (
size_t i = 0; i < lits.
size () && carry; ++i) {
3425 internal->external->check_learned_clause ();
3450 internal->external->check_learned_clause ();
3458 LOG (g,
"starting XOR shrinking proof chain");
3469 const int lhs = g->
lhs;
3474 const bool parity = (lhs > 0);
3476 const size_t size =
clause.size ();
3477 const unsigned end = 1u << (size - 1);
3480 for (
auto pair : first) {
3481 LOG (pair.clause,
"key %d", pair.current_lit);
3486 for (
unsigned i = 0; i != end; ++i) {
3491 clause.push_back (pivot);
3494 clause.push_back (-pivot);
3503 if (
clause.size () > 1) {
3527 const int lhs = g->
lhs;
3528 LOG (g,
"checking implied");
3531 for (
auto other : g->
rhs) {
3533 clause.push_back (other);
3536 const unsigned arity = g->
arity ();
3537 const unsigned end = 1u << arity;
3538 const bool parity = (lhs > 0);
3540 for (
unsigned i = 0; i != end; ++i) {
3543 internal->external->check_learned_clause ();
3577 std::swap (
rhs[1],
rhs[2]);
3631 LOG (g->
rhs,
"g/RHS = ");
3635#ifndef CADICAL_NDEBUG
3636bool is_tautological_ite_gate (
Gate *g) {
3639 const int cond_lit = g->
rhs[0];
3640 const int then_lit = g->
rhs[1];
3641 const int else_lit = g->
rhs[2];
3642 return cond_lit == then_lit || cond_lit == else_lit;
3648 LOG (g,
"post normalize");
3653 internal->external->check_learned_clause ();
3668 const uint32_t id2_higher = (
id >> 32);
3671 chain.push_back (id2_higher);
3672 chain.push_back (id2_lower);
3675 chain.push_back (0);
3682#ifndef CADICAL_NDEBUG
3688 bool trivial =
false;
3693 signed char ¬_lit_mark =
marked (-
lit);
3694 if (not_lit_mark & 4) {
3719 LOG (
"skipping trivial proof");
3731 LOG (
"starting ITE turned AND supporting binary clauses");
3734 int not_lhs = -g->
lhs;
3746 for (
auto pair : source) {
3755 int lhs,
int except2,
bool flip) {
3757 for (
auto pair : source) {
3781 LOG (
"starting XOR matching proof");
3785 for (
auto pair : first) {
3786 bool first = pair.current_lit & 1;
3787 int rest = pair.current_lit >> 1;
3788 rest &= ~(1 << (g->
rhs.
size () - 1));
3789 if (first == (lhs1 > 0)) {
3790 first_ids.push_back (
LitIdPair (rest, pair.clause->id));
3792 second_ids.push_back (
LitIdPair (rest, pair.clause->id));
3794 LOG (pair.clause,
"key %d", pair.current_lit);
3796 for (
auto pair : second) {
3797 bool first = pair.current_lit & 1;
3798 int rest = pair.current_lit >> 1;
3799 rest &= ~(1 << (g->
rhs.
size () - 1));
3800 if (first == (lhs2 < 0)) {
3801 first_ids.push_back (
LitIdPair (rest, pair.clause->id));
3803 second_ids.push_back (
LitIdPair (rest, pair.clause->id));
3805 LOG (pair.clause,
"key %d", pair.current_lit);
3815 const size_t off = 1u << size;
3816 for (
size_t i = 0; i != off; ++i) {
3821 for (
auto pair : first_ids) {
3832 int32_t rest = n &= ~(1 << (
unsimplified.size () - 1));
3833 first_tmp.push_back (
LitIdPair (rest, id1));
3836 for (
auto pair : second_ids) {
3848 int32_t rest = n &= ~(1 << (
unsimplified.size () - 1));
3849 second_tmp.push_back (
LitIdPair (rest, id2));
3854 first_ids.swap (first_tmp);
3855 second_ids.swap (second_tmp);
3861 to_lrat.push_back (first_ids.back ().id);
3862 back_lrat.push_back (second_ids.back ().id);
3866 LOG (
"finished XOR matching proof");
3878 if (lhs !=
lit && -lhs !=
lit) {
3888 std::vector<LRAT_ID> reasons_implication, reasons_back;
3890 reasons_implication, reasons_back);
3906 for (
auto pair : glauses)
3909 ++
internal->stats.congruence.gates;
3913 LOG (g,
"creating new");
3915 for (
auto lit : g->
rhs) {
3927 for (
auto r =
rhs.rbegin (); r !=
rhs.rend (); r++) {
3936 int lhs,
int except,
bool flip) {
3941 (void) lhs, (
void) except;
3945 n += !(
lit > 0) ^ flip;
3954 int except2,
bool flip) {
3971 int lhs,
int except2,
bool flip) {
3974 for (
auto &litId : xs) {
3980#ifndef CADICAL_NDEBUG
3981 std::for_each (begin (xs), end (xs), [&xs] (
const LitClausePair &x) {
3988 const unsigned arity_limit =
internal->opts.congruencexorarity;
3990 const unsigned size_limit = arity_limit + 1;
3994 LOG (c,
"considering clause for XOR");
4002 for (
auto lit : *c) {
4007 LOG (c,
"satisfied by %d",
lit);
4009 goto CONTINUE_COUNTING_NEXT_CLAUSE;
4011 if (size == size_limit)
4012 goto CONTINUE_COUNTING_NEXT_CLAUSE;
4018 for (
auto lit : *c) {
4024 LOG (c,
"considering clause for XOR as candidate");
4025 candidates.push_back (c);
4026 CONTINUE_COUNTING_NEXT_CLAUSE:;
4029 LOG (
"considering %zd out of %zd", candidates.size (),
4031 const unsigned rounds =
internal->opts.congruencexorcounts;
4033 const size_t original_size = candidates.size ();
4036 for (
unsigned round = 0; round < rounds; ++round) {
4037 LOG (
"round %d of XOR extraction", round);
4040 unsigned cand_size = candidates.size ();
4042 for (
size_t i = 0; i < cand_size; ++i) {
4043 Clause *c = candidates[i];
4044 LOG (c,
"considering");
4046 for (
auto lit : *c) {
4052 const unsigned arity = size - 1;
4053 const unsigned needed_clauses = 1u << (arity - 1);
4054 for (
auto lit : *c) {
4056 LOG (c,
"not enough occurrences, so ignoring");
4058 goto CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE;
4064 candidates[j++] = candidates[i];
4066 CONTINUE_WITH_NEXT_CANDIDATE_CLAUSE:;
4068 candidates.resize (j);
4075 LOG (
"after round %d, %zd (%ld %%) remain", round, candidates.size (),
4076 candidates.size () / (1 + original_size) * 100);
4079 for (
auto c : candidates) {
4086 unsigned least_occurring_literal = 0;
4087 unsigned count_least_occurring = UINT_MAX;
4088 const size_t size_lits =
lits.size ();
4089#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
4090 const unsigned arity = size_lits - 1;
4092#ifndef CADICAL_NDEBUG
4093 const unsigned count_limit = 1u << (arity - 1);
4095 LOG (
lits,
"trying to find arity %u XOR side clause", arity);
4101 if (count >= count_least_occurring)
4103 count_least_occurring = count;
4104 least_occurring_literal =
lit;
4108 LOG (
"searching XOR side clause watched by %d#%u",
4109 least_occurring_literal, count_least_occurring);
4110 LOG (
"searching for size %ld", size_lits);
4111 for (
auto c :
internal->occs (least_occurring_literal)) {
4112 LOG (c,
"checking");
4116 if ((
size_t) c->size < size_lits)
4119 for (
auto other : *c) {
4124 LOG (c,
"found satisfied %d in", other);
4132 LOG (
"not marked %d", other);
4137 if (found == size_lits && !c->garbage) {
4141 LOG (
"too few literals");
4147 LOG (res,
"found matching XOR side");
4149 LOG (
"no matching XOR side clause found");
4154 LOG (c,
"checking clause");
4158 const unsigned arity_limit =
internal->opts.congruencexorarity;
4159 const unsigned size_limit = arity_limit + 1;
4160 unsigned negated = 0, size = 0;
4162 for (
auto lit : *c) {
4170 if (size == size_limit) {
4171 LOG (c,
"size limit reached");
4176 largest = smallest =
lit;
4182 LOG (
"new smallest %d",
lit);
4187 LOG (c,
"not largest %d (largest: %d) occurs negated in XOR base",
4195 LOG (c,
"negated literal %d not largest in XOR base",
lit);
4198 if (
lit < 0 && negated++) {
4199 LOG (c,
"more than one negated literal in XOR base");
4207 LOG (c,
"short XOR base clause");
4211 LOG (
"double checking if possible");
4212 const unsigned arity = size - 1;
4213 const unsigned needed_clauses = 1u << (arity - 1);
4217 if (count >= needed_clauses)
4220 "literal %d in XOR base clause only occurs %u times in large "
4221 "clause thus skipping",
4227 LOG (
"checking for XOR side clauses");
4229 const unsigned end = 1u << arity;
4234 for (
unsigned i = 0; i != end; ++i) {
4253 LOG (
lits,
"found all needed %u matching clauses:", found);
4256 auto p = begin (
lits);
4258 while ((
lit = *
p) > 0)
4260 LOG (
"flipping RHS literal %d", (
lit));
4263 LOG (
lits,
"normalized negations");
4264 unsigned extracted = 0;
4265 for (
auto lhs :
lits) {
4275 LOG (
"no arity %u XOR gate extracted", arity);
4281 START (extractxors);
4282 LOG (
"starting extracting XOR");
4283 std::vector<Clause *> candidates = {};
4285 for (
auto c : candidates) {
4301 if (!
internal->flags (v).active ())
4303 for (
int sgn = -1; sgn < 1; sgn += 2) {
4308 const int other = w.blit;
4310 LOG (w.clause,
"binary clause %d %d and %d %d give unit %d",
lit,
4311 other,
lit, -other,
lit);
4328 internal->analyzed.push_back (other);
4342 if (!
internal->flags (v).active ())
4349 const int other = w.blit;
4354 internal->analyzed.push_back (other);
4365 const int other = w.blit;
4369 LOG (
"binary clause %d %d", -
lit, other);
4373 LOG (
"found equivalence %d %d with %d and %d as the representative",
4374 lit, other, lit_repr, other_repr);
4375 if (lit_repr != other_repr) {
4391 LOG (w.clause,
"merging");
4397 ++
internal->stats.congruence.congruent;
4432 LOG (g,
"rewriting %d into %d in", src, dst);
4433 int clashing = 0, falsifies = 0;
4434 unsigned dst_count = 0, not_dst_count = 0;
4435 auto q = begin (g->
rhs);
4436 for (
int &
lit : g->
rhs) {
4440 LOG (
"found negated LHS literal %d",
lit);
4452 LOG (
"found falsifying literal %d", (
lit));
4457 if (not_dst_count) {
4458 LOG (
"clashing literals %d and %d", (-dst), (dst));
4468 LOG (
"clashing literals %d and %d", (dst), (-dst));
4482 LOG (litId.clause,
"%d ->", litId.current_lit);
4490 const int orig_falsifies = falsifies == dst ? src : falsifies;
4491 const int orig_clashing =
4492 clashing == -dst ? -src : (clashing == dst ? src : clashing);
4493 int keep_clashing = clashing;
4494 LOG (
"keeping chain for falsifies: %d aka %d and clashing: %d aka %d",
4495 falsifies, orig_falsifies, clashing, orig_clashing);
4496 for (
size_t j = 0; j < size; ++j) {
4497 LOG (g->
pos_lhs_ids[j].clause,
"looking at %d [%zd %zd] with val %d",
4501 if (keep_clashing && g->
pos_lhs_ids[i].current_lit != orig_clashing &&
4502 g->
pos_lhs_ids[i].current_lit != -orig_clashing &&
4517 LOG (
"maybe keeping %d [%zd %zd], src: %d, found: %d",
4521 g->
pos_lhs_ids[i].current_lit = dst, found =
true;
4525 LOG (
"keeping %d [%zd %zd]", g->
pos_lhs_ids[i].current_lit, i, j);
4528 LOG (
"resizing to %zd", i);
4533 if (q != end (g->
rhs)) {
4534 g->
rhs.resize (q - begin (g->
rhs));
4540 std::vector<LRAT_ID> reasons_lrat_src, reasons_lrat_usrc;
4542 LOG (g,
"rewritten as");
4546 ++
internal->stats.congruence.rewritten_ands;
4570 const auto &occs =
goccs (src);
4571 for (
auto g : occs) {
4576 goccs (dst).push_back (g);
4578 goccs (src).clear ();
4580#ifndef CADICAL_NDEBUG
4581 for (
const auto &occs :
gtab) {
4582 for (
auto g : occs) {
4593 if (dst != g->
lhs && dst != -g->
lhs)
4607 LOG (g,
"rewriting (%d -> %d)", src, dst);
4610 size_t j = 0, dst_count = 0;
4611 bool original_dst_negated = (dst < 0);
4613 unsigned negate = original_dst_negated;
4614 const size_t size = g->
rhs.
size ();
4615 for (
size_t i = 0; i < size; ++i) {
4628 LOG (
"keeping value %d",
lit);
4632 LOG (
"flipping LHS %d", g->
lhs);
4636 if (dst_count == 2) {
4637 LOG (
"destination found twice, removing");
4639 for (
size_t i = 0; i < j; ++i) {
4640 const int lit = g->
rhs[i];
4650 }
else if (j != size) {
4654 g->
hash = hash_lits (
4682 LOG (g,
"simplifying");
4686 unsigned negate = 0;
4688 const size_t size = g->
rhs.
size ();
4690 for (
size_t i = 0; i < size; ++i) {
4701 LOG (
"flipping LHS literal %d", (g->
lhs));
4705 LOG (
"shrunken gate");
4718 LOG (g,
"simplified");
4720 internal->stats.congruence.simplified++;
4721 internal->stats.congruence.simplified_xors++;
4727 const int idx = abs (
lit);
4733 LOG (
"scheduled literal %d",
lit);
4737 LOG (
"propagation of congruence unit %d",
lit);
4759 LOG (
"propagating literal %d",
lit);
4770 START (congruencemerge);
4771 size_t propagated = 0;
4772 LOG (
"propagating at least %zd units",
schedule.size ());
4788 LOG (
"propagated %zu congruence units",
units);
4789 LOG (
"propagated %zu congruence equivalences", propagated);
4791#ifndef CADICAL_NDEBUG
4793 for (
const auto &occs :
gtab) {
4794 for (
auto g : occs) {
4804 for (
auto lit : g->rhs) {
4819 STOP (congruencemerge);
4840 LOG (g,
"deleting");
4846 for (
auto &occ :
gtab) {
4859 internal->proof->delete_clause (c);
4877 for (
auto sgn = -1; sgn <= 1; sgn += 2) {
4878 const int lit = v * sgn;
4880 const size_t size = watchers.size ();
4882 for (
size_t i = 0; i != size; ++i) {
4883 const auto w = watchers[i];
4884 watchers[j] = watchers[i];
4885 if (!w.clause->garbage)
4909 START (congruencematching);
4911 std::vector<signed char> matchable;
4912 matchable.resize (
internal->max_var + 1);
4913 size_t count_matchable = 0;
4916 if (!
internal->flags (idx).active ())
4918 const int lit = idx;
4922 const int repr_idx = abs (repr);
4923 if (!matchable[idx]) {
4924 LOG (
"matchable %d", idx);
4925 matchable[idx] =
true;
4929 if (!matchable[repr_idx]) {
4930 LOG (
"matchable %d", repr_idx);
4931 matchable[repr_idx] =
true;
4936 LOG (
"found %.0f%%",
4937 (
double) count_matchable /
4939 std::vector<Clause *> candidates;
4940 auto &analyzed =
internal->analyzed;
4942 for (
auto *c :
internal->clauses) {
4950 bool contains_matchable =
false;
4951 for (
auto lit : *c) {
4956 LOG (c,
"mark satisfied");
4960 if (!contains_matchable) {
4961 const int idx = abs (
lit);
4963 contains_matchable =
true;
4970 const int not_repr = -repr;
4972 LOG (c,
"matches both %d and %d", (
lit), (not_repr));
4977 analyzed.push_back (repr);
4980 for (
auto lit : analyzed)
4985 if (!contains_matchable) {
4986 LOG (
"no matching variable");
4989 LOG (c,
"candidate");
4990 candidates.push_back (c);
4994 size_t tried = 0, subsumed = 0;
4996 for (
auto c : candidates) {
5004 LOG (
"[congruence] subsumed %.0f%%",
5005 (
double) subsumed / (
double) (tried ? tried : 1));
5006 STOP (congruencematching);
5020 LOG (subsumed,
"subsumed");
5029 LOG (
"turning redundant subsuming clause into irredundant clause");
5034 stats.current.irredundant++;
5035 stats.added.irredundant++;
5036 stats.irrlits += subsuming->
size;
5038 stats.current.redundant--;
5040 stats.added.redundant--;
5046 Clause *subsuming =
nullptr;
5047 for (
auto lit : *subsumed) {
5050 const signed char repr_val =
internal->val (repr_lit);
5059 int least_occuring_lit = 0;
5060 size_t count_least_occurring = INT_MAX;
5061 LOG (subsumed,
"trying to forward subsume");
5063 for (
auto lit : *subsumed) {
5065 const size_t count =
internal->occs (
lit).size ();
5067 if (count < count_least_occurring) {
5068 count_least_occurring = count;
5069 least_occuring_lit = repr_lit;
5074 if (!subsumed->
redundant && d->redundant)
5076 for (
auto other : *d) {
5077 const signed char v =
internal->val (other);
5082 if (!
marked (repr_other))
5083 goto CONTINUE_WITH_NEXT_CLAUSE;
5084 LOG (
"subsuming due to %d -> %d", other, repr_other);
5087 goto FOUND_SUBSUMING;
5089 CONTINUE_WITH_NEXT_CLAUSE:;
5095 for (
auto lit : *subsumed) {
5102 LOG (subsumed,
"subsumed");
5103 LOG (subsuming,
"subsuming");
5105 ++
internal->stats.congruence.subsumed;
5108 internal->occs (least_occuring_lit).push_back (subsumed);
5114static bool skip_ite_gate (
Gate *g) {
5122 Gate *g,
int src,
int dst, std::vector<LRAT_ID> &reasons_implication,
5123 std::vector<LRAT_ID> &reasons_back) {
5132 if ((g->
rhs[1] == src && g->
lhs == dst && g->
rhs[2] == g->
lhs) ||
5133 (g->
rhs[2] == src && g->
lhs == dst && g->
rhs[1] == g->
lhs) ||
5134 (g->
rhs[1] == -src && g->
lhs == -dst && g->
rhs[2] == g->
lhs) ||
5135 (g->
rhs[2] == -src && g->
lhs == -dst && g->
rhs[1] == g->
lhs))
5146 LOG (
"degenerated case with lhs = -cond");
5149 reasons_back.push_back (g->
pos_lhs_ids[0].clause->id);
5150 reasons_implication.push_back (g->
pos_lhs_ids[1].clause->id);
5154 LOG (
"degenerated case with lhs = cond");
5157 reasons_back.push_back (g->
pos_lhs_ids[3].clause->id);
5158 reasons_implication.push_back (g->
pos_lhs_ids[0].clause->id);
5161 reasons_implication.push_back (g->
pos_lhs_ids[0].clause->id);
5162 reasons_implication.push_back (g->
pos_lhs_ids[2].clause->id);
5163 reasons_back.push_back (g->
pos_lhs_ids[1].clause->id);
5164 reasons_back.push_back (g->
pos_lhs_ids[3].clause->id);
5171 LOG (g,
"updating lrat from");
5174 if (litId.current_lit == src)
5175 litId.current_lit = dst;
5176 if (litId.current_lit == -src)
5177 litId.current_lit = -dst;
5183 Gate *g,
int src,
int dst,
size_t idx1,
size_t idx2,
5184 int cond_lit_to_learn_if_degenerated) {
5187 LOG (g,
"rewriting to proper AND");
5190 const int lit = g->
rhs[0];
5209 const int lit = g->
rhs[1];
5213 const int other = (dst == g->
rhs[0] || dst == g->
rhs[1])
5214 ? dst ^ g->
rhs[0] ^ g->
rhs[1]
5215 : (-dst) ^ g->
rhs[0] ^ g->
rhs[1];
5239 LOG (
"updating flags");
5252 if ((idx1 == (
size_t) -1 || idx2 == (
size_t) -1)) {
5270 return p.clause == d || !p.clause;
5288 LOG (long_clause->clause,
"new long clause");
5296#ifndef CADICAL_NDEBUG
5300 for (
auto other : *litId.clause) {
5308 LOG (
id.
clause,
"clause after rewriting:");
5317 Gate *g, std::vector<LRAT_ID> &reasons_implication,
5318 std::vector<LRAT_ID> &reasons_back, std::vector<LRAT_ID> &reasons_unit,
5319 bool rewritting_then,
bool &learn_units) {
5321 const size_t idx1 = rewritting_then ? 0 : 2;
5322 const size_t idx2 = idx1 + 1;
5323 const size_t other_idx1 = rewritting_then ? 2 : 0;
5324 const size_t other_idx2 = other_idx1 + 1;
5325 const int cond_lit = g->
rhs[0];
5326 const int lit_to_merge = g->
rhs[rewritting_then ? 2 : 1];
5327 const int other_lit = g->
rhs[rewritting_then ? 1 : 2];
5336 LOG (
"cond: %d, merging %d and rewriting to %d", cond_lit, lit_to_merge,
5342 if (repr_lhs == -repr_other_lit) {
5343 LOG (
"special case: %s=%s, checking if other: %s %s",
LOGLIT (g->
lhs),
5347 if (rewritting_then && repr_cond_lit == repr_lhs) {
5348 LOG (
"t=-lhs/c=lhs");
5355 reasons_unit = {id_unit};
5357 reasons_implication.push_back (id_unit);
5361 reasons_implication.push_back (g->
pos_lhs_ids[3].clause->id);
5365 if (!rewritting_then && repr_cond_lit == repr_lhs) {
5366 LOG (
"e=-lhs/c=lhs");
5373 reasons_unit = {id_unit};
5375 reasons_implication.push_back (id_unit);
5379 reasons_implication.push_back (g->
pos_lhs_ids[0].clause->id);
5383 if (!rewritting_then && repr_cond_lit == -repr_lhs) {
5384 LOG (
"e=-lhs/c=-lhs");
5398 reasons_unit = {id_unit};
5404 reasons_implication.push_back (id_unit);
5405 reasons_implication.push_back (g->
pos_lhs_ids[1].clause->id);
5409 if (rewritting_then && repr_cond_lit == -repr_lhs) {
5410 LOG (
"t=-lhs/c=-lhs");
5416 reasons_unit = {id_unit};
5421 reasons_implication.push_back (id_unit);
5422 reasons_implication.push_back (g->
pos_lhs_ids[2].clause->id);
5426 if (rewritting_then && repr_lit_to_merge == repr_lhs) {
5427 LOG (
"t=-lhs/e=lhs from rewriting then");
5439 reasons_unit = {id_unit};
5444 if (!rewritting_then && repr_lit_to_merge == repr_lhs) {
5445 LOG (
"t=-lhs/e=lhs from rewriting else");
5457 reasons_unit = {id_unit};
5462 if (other_lit == repr_lhs) {
5463 LOG (
"TODO FIX ME t=-lhs/e=lhs");
5472 reasons_unit.push_back (g->
pos_lhs_ids[idx1].clause->id);
5473 reasons_unit.push_back (g->
pos_lhs_ids[idx2].clause->id);
5484 LOG (
"normal path");
5488 reasons_unit.push_back (g->
pos_lhs_ids[idx1].clause->id);
5489 reasons_unit.push_back (g->
pos_lhs_ids[idx2].clause->id);
5492 if (!rewritting_then && repr_lhs == repr_lit_to_merge) {
5496 reasons_implication.push_back (g->
pos_lhs_ids[other_idx1].clause->id);
5497 reasons_implication.push_back (g->
pos_lhs_ids[idx1].clause->id);
5498 reasons_implication.push_back (g->
pos_lhs_ids[idx2].clause->id);
5500 reasons_back.push_back (g->
pos_lhs_ids[other_idx2].clause->id);
5501 reasons_back.push_back (g->
pos_lhs_ids[idx1].clause->id);
5502 reasons_back.push_back (g->
pos_lhs_ids[idx2].clause->id);
5504 LOG (
"learn extra clauses XXXXXXXXXXXXXXXXXXXXXXXXX");
5505 const int lhs = g->
lhs;
5506 const int cond = g->
rhs[0];
5507 if (rewritting_then) {
5528 if (skip_ite_gate (g))
5532 LOG (g,
"rewriting %d by %d in", src, dst);
5537 const int lhs = g->
lhs;
5538 const int cond = g->
rhs[0];
5539 const int then_lit = g->
rhs[1];
5540 const int else_lit = g->
rhs[2];
5541 const int not_lhs = -(lhs);
5542 const int not_dst = -(dst);
5543 const int not_cond = -(cond);
5544 const int not_then_lit = -(then_lit);
5545 const int not_else_lit = -(else_lit);
5555 LOG (g,
"all values are set");
5559 LOG (g,
"all values are set 2");
5564 else if (src == cond) {
5565 if (dst == then_lit) {
5572 rhs[0] = not_then_lit;
5573 rhs[1] = not_else_lit;
5574 if (then_lit == lhs || else_lit == lhs)
5578 }
else if (not_dst == then_lit) {
5585 }
else if (dst == else_lit) {
5592 }
else if (not_dst == else_lit) {
5599 rhs[0] = not_then_lit;
5600 rhs[1] = not_else_lit;
5601 if (then_lit == lhs || else_lit == lhs)
5610 }
else if (src == then_lit) {
5611 if (not_dst == g->
lhs) {
5614 std::vector<LRAT_ID> reasons_implication, reasons_back, reasons_unit;
5616 bool learn_units_instead_of_equivalence =
false;
5618 g, reasons_implication, reasons_back, reasons_unit,
true,
5619 learn_units_instead_of_equivalence);
5620 if (learn_units_instead_of_equivalence) {
5627 if (-else_lit == lhs) {
5635 ++
internal->stats.congruence.unaries;
5636 ++
internal->stats.congruence.unary_ites;
5646 }
else if (dst == cond) {
5654 rhs[1] = not_else_lit;
5655 if (else_lit == lhs || cond == lhs)
5659 }
else if (not_dst == cond) {
5666 }
else if (dst == else_lit) {
5669 std::vector<LRAT_ID> reasons_implication, reasons_back;
5674 ++
internal->stats.congruence.unaries;
5675 ++
internal->stats.congruence.unary_ites;
5679 }
else if (not_dst == else_lit) {
5683 if (g->
lhs == cond) {
5694 LOG (
"changing to xor");
5702 LOG (litId.clause,
"%d ->", litId.current_lit);
5709 LOG (litId.clause,
"%d ->", litId.current_lit);
5721 if (not_dst == g->
lhs) {
5723 std::vector<LRAT_ID> reasons_implication, reasons_back, reasons_unit;
5724 bool learn_units_instead_of_equivalence =
false;
5726 g, reasons_implication, reasons_back, reasons_unit,
false,
5727 learn_units_instead_of_equivalence);
5728 if (learn_units_instead_of_equivalence) {
5732 if (then_lit != lhs) {
5733 LOG (
"special case, learning %d",cond == -lhs ? -then_lit : then_lit);
5741 ++
internal->stats.congruence.unaries;
5742 ++
internal->stats.congruence.unary_ites;
5752 }
else if (dst == cond) {
5759 }
else if (not_dst == cond) {
5767 rhs[1] = not_then_lit;
5768 if (then_lit == lhs || cond == lhs)
5772 }
else if (dst == then_lit) {
5775 std::vector<LRAT_ID> reasons_implication, reasons_back;
5780 ++
internal->stats.congruence.unaries;
5781 ++
internal->stats.congruence.unary_ites;
5784 }
else if (not_dst == then_lit) {
5798 }
else if (not_lhs == cond) {
5808 }
else if (not_lhs == then_lit) {
5839 bool negate_lhs =
false;
5842 negate_lhs = !negate_lhs;
5846 negate_lhs = !negate_lhs;
5854 std::swap (
rhs[0],
rhs[1]);
5866 LOG (g,
"special XOR:");
5867 const int unit =
rhs[0] ^ -g->
lhs ^
rhs[1];
5878 LOG (g,
"special XOR:");
5879 const int unit =
rhs[0] ^ g->
lhs ^
rhs[1];
5891 bool negated =
false;
5892 for (
int j = 0; j < 2; ++i, ++j) {
5909 LOG (g,
"removed units");
5916 LOG (litId.clause,
"%d ->", litId.current_lit);
5921 Clause *c1 =
nullptr, *c2 =
nullptr;
5924 bool rhs_as_src_first =
5951 LOG (g,
"rewritten");
5955#ifndef CADICAL_NDEBUG
5958 CADICAL_assert ((size_t) l.clause->size ==
5966#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
5968 LOG (
id.
clause,
"clause after rewriting:");
5977#ifndef CADICAL_NDEBUG
5980 [] (
LitClausePair l) { CADICAL_assert (l.clause->size == 2); });
5987 __builtin_unreachable ();
6003 std::vector<LRAT_ID> reasons_implication, reasons_back;
6005 reasons_implication,
6012 std::vector<LRAT_ID> reasons_implication, reasons_back;
6015 reasons_back,
false);
6029 if (
lit != cond &&
lit != then_lit &&
lit != else_lit)
6037 LOG (g,
"rewritten");
6063 int normalized_lhs = negate_lhs ? not_lhs : lhs;
6064 std::vector<LRAT_ID> extra_reasons_lit, extra_reasons_ulit;
6067 extra_reasons_ulit);
6069 extra_reasons_ulit))
6077 LOG (g,
"normalized");
6083 if (
lit != cond &&
lit != then_lit &&
lit != else_lit)
6112 if (g->
lhs == -g->
rhs[0]) {
6113 LOG (
"special case of LHS=-cond where only one clause in LRAT is needed is needed");
6114 size_t idx = (
internal->val (g->
rhs[1]) < 0 ? idx2 : idx1);
6123 if (g->
lhs == g->
rhs[0]) {
6124 LOG (
"special case of LHS=cond where only one clause in LRAT is needed is needed");
6125 size_t idx = (
internal->val (g->
rhs[1]) > 0 ? idx2 : idx1);
6151 Gate *g,
Gate *h, std::vector<LRAT_ID> &reasons_lrat_src,
6152 std::vector<LRAT_ID> &reasons_lrat_usrc,
bool remove_units) {
6158 reasons_lrat_usrc, remove_units);
6168 LOG (litId.clause,
"%d ->", litId.current_lit);
6189 size_t new_idx1 = idx1;
6190 size_t new_idx2 = idx2;
6195 LOG (g,
"degenerated AND gate");
6196 const int replacement_lit = (g->
rhs[1] == g->
lhs ? g->
rhs[0] : g->
rhs[1]);
6199 LOG (litId.clause,
"%d ->", litId.current_lit);
6200 if (litId.current_lit == removed_lit)
6201 litId.current_lit = -replacement_lit;
6202 if (litId.current_lit == -removed_lit)
6203 litId.current_lit = replacement_lit;
6204 LOG (litId.clause,
"%d ->", litId.current_lit);
6206 CADICAL_assert (std::find (begin (*litId.clause), end (*litId.clause), litId.current_lit) !=
6207 end (*litId.clause));
6225 return p.clause == d;
6240 LOG (long_clause->clause,
"new long clause");
6246 const int first_lit = g->
rhs[0];
6247 const int second_lit = g->
rhs[1];
6250 LOG (litId.clause,
"%s ->",
LOGLIT (litId.current_lit));
6251 if (
internal->val (litId.current_lit)) {
6253 int replacement_lit = 0;
6254 for (
int i = 0; i < 2; ++i) {
6255 if (litId.clause->literals[i] == first_lit) {
6256 replacement_lit = first_lit;
6258 }
else if (litId.clause->literals[i] == second_lit) {
6259 replacement_lit = second_lit;
6265 litId.current_lit = replacement_lit;
6266 }
else if (litId.current_lit == removed_lit)
6267 litId.current_lit = -g->
rhs[0];
6268 else if (litId.current_lit == -removed_lit)
6269 litId.current_lit = g->
rhs[0];
6270 LOG (litId.clause,
"%d ->", litId.current_lit);
6274 CADICAL_assert (std::find (begin (*litId.clause), end (*litId.clause),
6275 litId.current_lit) != end (*litId.clause));
6281 std::vector<LitClausePair> &clauses,
6282 std::vector<LRAT_ID> &reasons_implication,
6283 std::vector<LRAT_ID> &reasons_back) {
6287 auto then_imp = clauses[0];
6288 auto neg_then_imp = clauses[1];
6289 auto else_imp = clauses[2];
6290 auto neg_else_imp = clauses[3];
6291 reasons_implication.push_back (then_imp.clause->id);
6292 reasons_implication.push_back (else_imp.clause->id);
6293 reasons_back.push_back (neg_then_imp.clause->id);
6294 reasons_back.push_back (neg_else_imp.clause->id);
6298 Gate *g, std::vector<LRAT_ID> &reasons_implication,
6299 std::vector<LRAT_ID> &reasons_back,
size_t idx1,
size_t idx2) {
6308 LOG (reasons_back,
"LRAT");
6309 LOG (reasons_implication,
"LRAT");
6323 Gate *g, std::vector<LRAT_ID> &reasons_lrat,
6324 std::vector<LRAT_ID> &reasons_back_lrat,
size_t idx1,
size_t idx2) {
6328#if defined(LOGGING) || !defined(CADICAL_NDEBUG)
6329 const int cond = g->
rhs[0];
6331 LOG (
"cond = %d", cond);
6335 LOG (litid.clause,
"clause in gate:");
6344 if (skip_ite_gate (g))
6346 LOG (g,
"simplifying");
6351 const int cond =
rhs[0];
6352 const int then_lit =
rhs[1];
6353 const int else_lit =
rhs[2];
6354 const signed char v_cond =
internal->val (cond);
6355 const signed char v_else =
internal->val (else_lit);
6356 const signed char v_then =
internal->val (then_lit);
6357 std::vector<LRAT_ID> reasons_lrat, reasons_back_lrat;
6358 if (v_cond && v_else && v_then) {
6359 LOG (g,
"all values are set");
6362 }
else if (v_cond > 0) {
6367 reasons_back_lrat)) {
6368 ++
internal->stats.congruence.unary_ites;
6369 ++
internal->stats.congruence.unaries;
6371 }
else if (v_cond < 0) {
6376 reasons_back_lrat)) {
6377 ++
internal->stats.congruence.unary_ites;
6378 ++
internal->stats.congruence.unaries;
6381 LOG (
"then %d: %d; else %d: %d", then_lit, v_then, else_lit, v_else);
6382 std::vector<LRAT_ID> extra_reasons, extra_reasons_back;
6384 if (v_then > 0 && v_else > 0) {
6387 }
else if (v_then < 0 && v_else < 0) {
6390 }
else if (v_then > 0 && v_else < 0) {
6393 extra_reasons_back, 1, 2);
6395 extra_reasons_back)) {
6396 ++
internal->stats.congruence.unary_ites;
6397 ++
internal->stats.congruence.unaries;
6399 }
else if (v_then < 0 && v_else > 0) {
6402 extra_reasons_back, 0, 3);
6405 ++
internal->stats.congruence.unary_ites;
6406 ++
internal->stats.congruence.unaries;
6417 }
else if (v_then < 0) {
6421 }
else if (v_else > 0) {
6435 std::swap (
rhs[0],
rhs[1]);
6446 std::vector<LRAT_ID> reasons_lrat, reasons_lrat_back;
6449 reasons_lrat_back,
false);
6451 reasons_lrat_back)) {
6460 if (
lit != cond &&
lit != then_lit &&
lit != else_lit) {
6473 ++
internal->stats.congruence.simplified;
6474 ++
internal->stats.congruence.simplified_ites;
6478 Gate *g,
Gate *h,
int lhs1,
int lhs2, std::vector<LRAT_ID> &reasons1,
6479 std::vector<LRAT_ID> &reasons2) {
6488 LOG (g,
"starting ITE matching proof chain");
6489 LOG (h,
"starting ITE matching proof chain with");
6494 const auto &
rhs = g->
rhs;
6497 const int cond =
rhs[0];
6498 LRAT_ID g_then_id = 0, g_neg_then_id = 0, g_neg_else_id = 0;
6499 LRAT_ID h_then_id = 0, h_neg_then_id = 0, h_else_id = 0;
6500 LRAT_ID g_else_id = 0, h_neg_else_id = 0;
6512 CADICAL_assert (!(degenerated_g_not_cond && degenerated_h_not_cond));
6527 LOG (g,
"get ids from");
6533 g_then_id = g_then_clause->id;
6535 auto &g_neg_then_clause = g->
pos_lhs_ids[1].clause;
6538 if (g_neg_then_clause)
6539 g_neg_then_id = g_neg_then_clause->id;
6545 g_else_id = g_else_clause->id;
6547 auto &g_neg_else_clause = g->
pos_lhs_ids[3].clause;
6550 if (g_neg_else_clause)
6551 g_neg_else_id = g_neg_else_clause->id;
6553 LOG (h,
"now clauses from");
6559 h_then_id = h_then_clause->id;
6561 auto &h_neg_then_clause = h->
pos_lhs_ids[1].clause;
6564 if (h_neg_then_clause)
6565 h_neg_then_id = h_neg_then_clause->id;
6571 h_else_id = h_else_clause->id;
6573 auto &h_neg_else_clause = h->
pos_lhs_ids[3].clause;
6576 if (h_neg_else_clause)
6577 h_neg_else_id = h_neg_else_clause->id;
6581 if (degenerated_g_cond) {
6582 LOG (
"special case: cond = lhs, g degenerated");
6604 reasons1.push_back (id1);
6605 reasons2.push_back (id2);
6610 if (degenerated_h_cond) {
6611 LOG (
"special case: cond = lhs, h degenerated");
6633 reasons2.push_back (id1);
6634 reasons1.push_back (id2);
6639 if (degenerated_g_not_cond) {
6640 LOG (
"special case: cond = -lhs, g degenerated");
6645 CADICAL_assert (g_neg_then_id && h_then_id && g_else_id && h_neg_else_id);
6663 reasons2.push_back (id1);
6664 reasons1.push_back (id2);
6669 if (degenerated_h_not_cond) {
6670 LOG (
"special case: cond = -lhs, h degenerated");
6675 CADICAL_assert (g_neg_then_id && h_then_id && g_else_id && h_neg_else_id);
6693 reasons2.push_back (id1);
6694 reasons1.push_back (id2);
6699 LOG (
"normal path");
6701 (g_then_id && g_neg_then_id));
6703 (g_else_id && g_neg_else_id));
6705 (h_then_id && h_neg_then_id));
6707 (h_else_id && h_neg_else_id));
6714 if (degenerated_g_then || degenerated_h_then) {
6715 id1 = degenerated_g_then ? h_neg_then_id : g_then_id;
6727 if (degenerated_g_else || degenerated_h_else) {
6728 id2 = degenerated_g_else ? h_neg_else_id : g_else_id;
6745 if (degenerated_g_then || degenerated_h_then) {
6746 id3 = degenerated_g_then ? h_then_id : g_neg_then_id;
6761 if (degenerated_g_else || degenerated_h_else) {
6762 id4 = degenerated_g_else ? h_else_id : g_neg_else_id;
6774 reasons1.push_back (id1), reasons1.push_back (id2);
6775 reasons2.push_back (id3), reasons2.push_back (id4);
6780 LOG (
"finished ITE matching proof chain");
6784 std::vector<LitClausePair> &&clauses) {
6786 if (else_lit == -then_lit) {
6788 LOG (
"skipping ternary XOR %d := %d ^ %d", lhs, cond, -then_lit);
6790 LOG (
"skipping ternary XOR %d := %d ^ %d", -lhs, cond, then_lit);
6793 if (else_lit == then_lit) {
6794 LOG (
"found trivial ITE gate %d := %d ? %d : %d", (lhs), (cond),
6795 (then_lit), (else_lit));
6796 std::vector<LRAT_ID> reasons_implication, reasons_back;
6803 ++
internal->stats.congruence.trivial_ite;
6808 rhs.push_back (cond);
6809 rhs.push_back (then_lit);
6810 rhs.push_back (else_lit);
6811 LOG (
"ITE gate %d = %d ? %d : %d", lhs, cond, then_lit, else_lit);
6813 bool negate_lhs =
false;
6832 std::vector<LRAT_ID> extra_reasons_lit, extra_reasons_ulit;
6834 extra_reasons_ulit);
6836 extra_reasons_ulit)) {
6838 LOG (
"found merged literals");
6851 ++
internal->stats.congruence.gates;
6855 LOG (g,
"creating new");
6859 for (
auto lit : g->
rhs) {
6876#ifdef CADICAL_NDEBUG
6894#ifndef CADICAL_NDEBUG
6897 const int normalize_lit =
6901 LOG (c,
"looking for (normalized) %d in ",
lit);
6902 for (
auto other : *c) {
6903 const int normalize_other =
6905 LOG (
"%d -> %d ", other, normalize_other);
6906 CADICAL_assert (!normalized || other == -except || normalize_other == other);
6907 if (normalize_other == normalize_lit) {
6914 (void) c, (
void)
lit, (void) normalized, (
void) except;
6919#ifndef CADICAL_NDEBUG
6928 (void) g, (
void) normalized;
6940 std::vector<ClauseSize> &candidates) {
6941 std::vector<Clause *> ternary;
6953 for (
auto lit : *c) {
6958 LOG (c,
"deleting as satisfied due to %d",
lit);
6960 goto CONTINUE_COUNTING_NEXT_CLAUSE;
6963 goto CONTINUE_COUNTING_NEXT_CLAUSE;
6969 ternary.push_back (c);
6970 LOG (c,
"counting original ITE gate base");
6971 for (
auto lit : *c) {
6975 CONTINUE_COUNTING_NEXT_CLAUSE:;
6978 for (
auto c : ternary) {
6981 unsigned positive = 0, negative = 0, twice = 0;
6982 for (
auto lit : *c) {
6987 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
6990 if (count_lit > 1 && count_not_lit > 1)
6998 goto CONTINUE_WITH_NEXT_TERNARY_CLAUSE;
7002 if (positive && negative)
7003 candidates.push_back (c);
7004 CONTINUE_WITH_NEXT_TERNARY_CLAUSE:;
7024 int first = 0, second = 0;
7025 for (
auto other : *c) {
7049 LOG (c,
"literal %d condition binary clause %d %d",
lit, first, second);
7055 const int a =
p.first;
7056 const int b = q.
first;
7061 const int c =
p.second;
7072 return (lita << 32) + litb;
7087lit_implications::const_iterator
7089 int lit, lit_implications::const_iterator begin,
7090 lit_implications::const_iterator end) {
7091 LOG (
"searching for %d in",
lit);
7092 for (
auto it = begin; it != end; ++it)
7093 LOG (
"%d [%d]", it->first, it->second);
7094 lit_implications::const_iterator found = std::lower_bound (
7097 return a.
second < b.second;
7099#ifndef CADICAL_NDEBUG
7100 auto found2 = std::binary_search (
7103 return a.
second < b.second;
7107 if (found < end && found->second ==
lit) {
7115 lit_implications::const_iterator pos_begin,
7116 lit_implications::const_iterator pos_end,
7118 lit_implications::const_iterator neg_begin,
7119 lit_implications::const_iterator neg_end,
7127 for (lit_implications::const_iterator
p = pos_begin;
p != pos_end;
p++) {
7128 const int other =
p->second;
7129 const int not_other = -other;
7130 const lit_implications::const_iterator other_clause =
7134 if (other_clause != neg_end) {
7136 end (*other_clause->clause),
7137 neg_lit) != end (*other_clause->clause));
7147 LOG (
"found conditional %d equivalence %d = %d",
lit,
7154 condeq.push_back (equivalence);
7155 if (equivalence.
second < 0) {
7158 condeq.push_back (inverse_equivalence);
7163 condeq.push_back (inverse_equivalence);
7176 const lit_implications::const_iterator begin =
condbin.cbegin ();
7177 const lit_implications::const_iterator end =
condbin.cend ();
7178 lit_implications::const_iterator pos_begin = begin;
7182 for (
const auto &pair :
condbin)
7183 LOG (
"unsorted conditional %d equivalence %d = %d",
lit, pair.first,
7186 LOG (
"searching for first positive literal for lit %d",
lit);
7188 if (pos_begin == end)
7190 next_lit = pos_begin->first;
7191 LOG (
"checking %d", next_lit);
7201 const int pos_lit = next_lit;
7202 lit_implications::const_iterator pos_end = pos_begin + 1;
7203 LOG (
"searching for first other literal after finding lit %d",
7208 next_lit = pos_end->first;
7209 if (next_lit != pos_lit)
7215 const int neg_lit = -pos_lit;
7216 if (next_lit != neg_lit) {
7218 pos_begin = pos_end + 1;
7219 LOG (
"next_lit %d < 0", next_lit);
7221 if (pos_begin == end)
7223 next_lit = pos_begin->first;
7229 pos_begin = pos_end;
7232 const lit_implications::const_iterator neg_begin = pos_end;
7233 lit_implications::const_iterator neg_end = neg_begin + 1;
7234 while (neg_end != end) {
7235 next_lit = neg_end->first;
7236 if (next_lit != neg_lit)
7241 for (lit_implications::const_iterator
p = pos_begin;
p != pos_end;
p++)
7242 LOG (
"conditional %d binary clause %d %d with positive %d", (
lit),
7243 (
p->first), (
p->second), (pos_lit));
7244 for (lit_implications::const_iterator
p = neg_begin;
p != neg_end;
p++)
7245 LOG (
"conditional %d binary clause %d %d with negative %d", (
lit),
7246 (
p->first), (
p->second), (neg_lit));
7248 const size_t pos_size = pos_end - pos_begin;
7249 const size_t neg_size = neg_end - neg_begin;
7250 if (pos_size <= neg_size) {
7251 LOG (
"searching negation of %zu conditional binary clauses "
7252 "with positive %d in %zu conditional binary clauses with %d",
7253 pos_size, (pos_lit), neg_size, (neg_lit));
7257 LOG (
"searching negation of %zu conditional binary clauses "
7258 "with negative %d in %zu conditional binary clauses with %d",
7259 neg_size, (neg_lit), pos_size, (pos_lit));
7267 pos_begin = neg_end + 1;
7269 if (pos_begin == end)
7271 next_lit = pos_begin->first;
7277 pos_begin = neg_end;
7297 LOG (
"sorted conditional %d equivalence %d = %d",
lit, pair.first,
7299 LOG (
"found %zu conditional %d equivalences",
condeq.size (),
lit);
7306 LOG (
"merging cond for literal %d", cond);
7307 auto q = begin (not_condeq);
7308 const auto end_not_condeq = end (not_condeq);
7310 const int lhs =
p.first;
7311 const int then_lit =
p.second;
7313 p.check_invariant ();
7315 while (q != end_not_condeq && q->first < lhs)
7317 while (q != end_not_condeq && q->first == lhs) {
7318 LOG (
"looking when %d at p= %d %d", cond,
p.first,
p.second);
7319 LOG (
"looking when %d at %d %d", -cond, q->first, q->second);
7321 const int else_lit = not_cond_pair.
second;
7322 std::vector<LitClausePair> clauses;
7328 LOG (
p.second_clause,
"pairing %d", then_lit);
7329 LOG (
p.first_clause,
"pairing %d", -then_lit);
7341 new_ite_gate (lhs, cond, then_lit, else_lit, std::move (clauses));
7349 LOG (
"search for ITE for literal %d ",
lit);
7351 if (!
condeq[0].empty ()) {
7353 if (!
condeq[1].empty ()) {
7368 const int lit = idx;
7369 const int not_lit = -idx;
7372 auto not_lit_watches =
internal->occs (not_lit);
7373 const size_t size_lit_watches = lit_watches.size ();
7374 const size_t size_not_lit_watches = not_lit_watches.size ();
7375 if (size_lit_watches <= size_not_lit_watches) {
7376 if (size_lit_watches > 1)
7379 if (size_not_lit_watches > 1)
7388 START (extractites);
7389 std::vector<ClauseSize> candidates;
7394 if (
internal->flags (idx).active ()) {
7432 if (!
opts.congruence)
7441 LOG (
"delaying congruence %" PRId64
" more times",
7452 const int64_t old =
stats.congruence.congruent;
7453 const int old_merged =
stats.congruence.congruent;
7456 if (!
internal->opts.congruencebinaries) {
7457 const bool dedup =
opts.deduplicate;
7458 opts.deduplicate =
true;
7460 opts.deduplicate = dedup;
7462 ++
stats.congruence.rounds;
7495 closure.forward_subsume_matching_clauses ();
7513 const int64_t new_merged =
stats.congruence.congruent;
7515#ifndef CADICAL_QUIET
7516 phase (
"congruence-phase",
stats.congruence.rounds,
"merged %ld literals",
7517 new_merged - old_merged);
7524#ifndef CADICAL_NDEBUG
7526 for (
auto v :
vars) {
7527 for (
auto sgn = -1; sgn <= 1; sgn += 2) {
7528 const int lit = v * sgn;
7532 if (w.clause->garbage)
7535 LOG (w.clause,
"watched");
7539 LOG (
"and now the clauses:");
7540 size_t nb_clauses = 0;
7551 if (new_merged == old_merged) {
7557 LOG (
"delay congruence internal %" PRId64,
7562 return new_merged != old_merged;
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define add_ite_matching_proof_chain(...)
#define check_ite_lits_normalized
#define check_and_gate_implied(...)
#define add_xor_shrinking_proof_chain(...)
#define add_ite_turned_and_binary_clauses
#define check_ite_implied
#define add_xor_matching_proof_chain(...)
#define check_ite_gate_implied
#define check_xor_gate_implied
bool ite_flags_neg_cond_lhs(int8_t flag)
bool ite_flags_cond_lhs(int8_t flag)
void inc_lits(vector< int > &lits)
std::vector< lit_equivalence > lit_equivalences
bool less_litpair(lit_equivalence p, lit_equivalence q)
void update_ite_flags(Gate *g)
bool gate_contains(Gate *g, int lit)
std::vector< lit_implication > lit_implications
bool ite_flags_no_then_clauses(int8_t flag)
void check_correct_ite_flags(const Gate *const g)
bool ite_flags_no_else_clauses(int8_t flag)
std::string string_of_gate(Gate_Type t)
bool parity_lits(const vector< int > &lits)
void rsort(I first, I last, Rank rank)
#define START_SIMPLIFIER(S, M)
#define STOP_SIMPLIFIER(S, M)
#define MSORT(LIMIT, FIRST, LAST, RANK, LESS)
static size_t bytes(int size)
vector< LRAT_ID > eager_representant_id
LRAT_ID & representative_id(int lit)
void simplify_ite_gate_condition_set(Gate *g, std::vector< LRAT_ID > &reasons_lrat, std::vector< LRAT_ID > &reasons_back_lrat, size_t idx1, size_t idx2)
void reset_ite_gate_extraction()
Gate * find_xor_gate(Gate *)
void produce_representative_lrat(int lit)
int find_eager_representative(int)
vector< LRAT_ID > lrat_chain
void simplify_xor_gate(Gate *g)
void search_condeq(int lit, int pos_lit, lit_implications::const_iterator pos_begin, lit_implications::const_iterator pos_end, int neg_lit, lit_implications::const_iterator neg_begin, lit_implications::const_iterator neg_end, lit_equivalences &condeq)
Gate * find_ite_gate(Gate *, bool &)
void merge_condeq(int cond, lit_equivalences &condeq, lit_equivalences ¬_condeq)
bool simplify_ite_gate_to_and(Gate *g, size_t idx1, size_t idx2, int removed)
vector< int > unsimplified
bool propagate_unit(int lit)
Gate * new_xor_gate(const vector< LitClausePair > &, int)
vector< LitClausePair > lrat_chain_and_gate
void check_and_gate_implied(Gate *g)
bool rewriting_lhs(Gate *g, int dst)
Gate * find_and_lits(const vector< int > &rhs, Gate *except=nullptr)
void simplify_and_gate(Gate *g)
void simplify_unit_xor_lrat_clauses(const vector< LitClausePair > &, int)
Clause * learn_binary_tmp_or_full_clause(int a, int b)
Clause * add_tmp_binary_clause(int a, int b)
LRAT_ID find_eager_representative_lrat(int lit)
int & representative(int lit)
void extract_ite_gates_of_variable(int idx)
void set_mu4_reason(int lit, Clause *c)
void set_mu2_reason(int lit, Clause *c)
LRAT_ID simplify_and_add_to_proof_chain(vector< int > &unsimplified, LRAT_ID delete_id=0)
void produce_eager_representative_lrat(int lit)
void merge_ite_gate_same_then_else_lrat(std::vector< LitClausePair > &clauses, std::vector< LRAT_ID > &reasons_implication, std::vector< LRAT_ID > &reasons_back)
Clause * find_large_xor_side_clause(std::vector< int > &lits)
void push_id_and_rewriting_lrat_unit(Clause *c, Rewrite rewrite1, std::vector< LRAT_ID > &chain, bool=true, Rewrite rewrite2=Rewrite(), int execept_lhs=0, int except_lhs2=0)
void check_ite_implied(int lhs, int cond, int then_lit, int else_lit)
void compute_rewritten_clause_lrat_simple(Clause *c, int except)
void init_xor_gate_extraction(std::vector< Clause * > &candidates)
vector< int > representant
void check_binary_implied(int a, int b)
bool skip_and_gate(Gate *g)
char & lazy_propagated(int lit)
void push_id_on_chain(std::vector< LRAT_ID > &chain, Clause *c)
void push_lrat_unit(int lit)
void push_id_and_rewriting_lrat_full(Clause *c, Rewrite rewrite1, std::vector< LRAT_ID > &chain, bool=true, Rewrite rewrite2=Rewrite(), int execept_lhs=0, int except_lhs2=0)
void merge_and_gate_lrat_produce_lrat(Gate *g, Gate *h, std::vector< LRAT_ID > &reasons_lrat, std::vector< LRAT_ID > &reasons_lrat_back, bool remove_units=true)
uint64_t & new_largecounts(int lit)
std::array< lit_equivalences, 2 > condeq
void rewrite_xor_gate(Gate *g, int dst, int src)
void update_and_gate_unit_build_lrat_chain(Gate *g, int src, LRAT_ID id1, LRAT_ID id2, int dst, std::vector< LRAT_ID > &extra_reasons_lit, std::vector< LRAT_ID > &extra_reasons_ulit)
void shrink_and_gate(Gate *g, int falsified=0, int clashing=0)
bool rewrite_gates(int dst, int src, LRAT_ID id1, LRAT_ID id2)
std::array< int, 16 > nonces
vector< uint64_t > glargecounts
int find_representative_and_compress(int, bool update_eager=true)
bool normalize_ite_lits_gate(Gate *rhs)
void produce_ite_merge_lhs_then_else_reasons(Gate *g, std::vector< LRAT_ID > &reasons_implication, std::vector< LRAT_ID > &reasons_back, std::vector< LRAT_ID > &reasons_unit, bool, bool &)
void extract_xor_gates_with_base_clause(Clause *c)
void import_lazy_and_find_eager_representative_and_compress_both(int)
Gate * find_first_and_gate(Clause *base_clause, int lhs)
void add_ite_matching_proof_chain(Gate *g, Gate *h, int lhs1, int lhs2, std::vector< LRAT_ID > &reasons1, std::vector< LRAT_ID > &reasons2)
void learn_congruence_unit_when_lhs_set(Gate *g, int src, LRAT_ID id1, LRAT_ID id2, int dst)
uint32_t number_from_xor_reason(const std::vector< int > &rhs, int, int except2=0, bool flip=0)
std::array< lit_implications, 2 > condbin
void check_contained_module_rewriting(Clause *c, int lit, bool, int except)
LRAT_ID & eager_representative_id(int lit)
vector< signed char > marks
vector< int > eager_representant
void update_and_gate(Gate *g, GatesTable::iterator, int src, int dst, LRAT_ID id1, LRAT_ID id2, int falsified=0, int clashing=0)
int find_lrat_representative_with_marks(int lit)
LitClausePair marked_mu1(int lit)
Clause * maybe_add_binary_clause(int a, int b)
void init_and_gate_extraction()
vector< CompactBinary > binaries
bool learn_congruence_unit(int unit, bool=false, bool=false)
void learn_congruence_unit_falsifies_lrat_chain(Gate *g, int src, int dst, int clashing, int falsified, int unit)
bool rewrite_gate(Gate *g, int dst, int src, LRAT_ID id1, LRAT_ID id2)
void init_ite_gate_extraction(std::vector< ClauseSize > &candidates)
vector< Clause * > extra_clauses
vector< LRAT_ID > representant_id
void sort_literals_by_var(vector< int > &rhs)
void reset_xor_gate_extraction()
bool merge_literals_lrat(Gate *g, Gate *h, int lit, int other, const std::vector< LRAT_ID > &={}, const std::vector< LRAT_ID > &={})
bool find_binary(int, int) const
void check_not_tmp_binary_clause(Clause *c)
void simplify_ite_gate_produce_unit_lrat(Gate *g, int lit, size_t idx1, size_t idx2)
int find_eager_representative_and_compress(int)
void check_ternary(int a, int b, int c)
void produce_rewritten_clause_lrat_and_clean(vector< LitClausePair > &, int execept_lhs=0, bool=true)
uint64_t & largecount(int lit)
void forward_subsume_matching_clauses()
bool merge_literals_equivalence(int lit, int other, Clause *c1, Clause *c2)
void rewrite_ite_gate_update_lrat_reasons(Gate *g, int src, int dst)
Gate * new_ite_gate(int lhs, int cond, int then_lit, int else_lit, std::vector< LitClausePair > &&clauses)
void add_xor_matching_proof_chain(Gate *g, int lhs1, const vector< LitClausePair > &, int lhs2, vector< LRAT_ID > &, vector< LRAT_ID > &)
void rewrite_ite_gate(Gate *g, int dst, int src)
void update_and_gate_build_lrat_chain(Gate *g, Gate *h, std::vector< LRAT_ID > &extra_reasons_lit, std::vector< LRAT_ID > &extra_reasons_ulit, bool remove_units=true)
int & eager_representative(int lit)
lit_implications::const_iterator find_lit_implication_second_literal(int lit, lit_implications::const_iterator begin, lit_implications::const_iterator end)
void check_ite_lrat_reasons(Gate *g, bool=false)
void simplify_ite_gate(Gate *g)
bool rewrite_ite_gate_to_and(Gate *g, int dst, int src, size_t c, size_t d, int cond_lit_to_learn_if_degenerated)
void reset_and_gate_extraction()
uint64_t & largecounts(int lit)
void rewrite_and_gate(Gate *g, int dst, int src, LRAT_ID id1, LRAT_ID id2)
void promote_clause(Clause *)
LitClausePair marked_mu2(int lit)
LRAT_ID check_and_add_to_proof_chain(vector< int > &clause)
uint32_t number_from_xor_reason_reversed(const std::vector< int > &rhs)
bool skip_xor_gate(Gate *g)
void add_clause_to_chain(std::vector< int >, LRAT_ID)
Clause * maybe_promote_tmp_binary_clause(Clause *)
void simplify_and_sort_xor_lrat_clauses(const vector< LitClausePair > &, vector< LitClausePair > &, int, int except2=0, bool flip=0)
vector< uint64_t > gnew_largecounts
void schedule_literal(int lit)
int find_representative(int lit)
void extract_ite_gates_of_literal(int)
bool simplify_gates(int lit)
void produce_ite_merge_then_else_reasons(Gate *g, int dst, int src, std::vector< LRAT_ID > &reasons_implication, std::vector< LRAT_ID > &reasons_back)
LitClausePair marked_mu4(int lit)
bool find_subsuming_clause(Clause *c)
void find_conditional_equivalences(int lit, lit_implications &condbin, lit_equivalences &condeq)
std::vector< std::pair< size_t, size_t > > offsetsize
std::vector< char > lazy_propagated_idx
void mark_garbage(Gate *)
size_t propagate_units_and_equivalences()
void gate_sort_lrat_reasons(std::vector< LitClausePair > &, int, int except2=0, bool flip=0)
void update_xor_gate(Gate *g, GatesTable::iterator)
void check_ite_gate_implied(Gate *g)
void connect_goccs(Gate *g, int lit)
Clause * add_binary_clause(int a, int b)
void subsume_clause(Clause *subsuming, Clause *subsumed)
void sort_literals_by_var_except(vector< int > &rhs, int, int except2=0)
LRAT_ID find_representative_lrat(int lit)
Gate * find_gate_lits(const vector< int > &rhs, Gate_Type typ, Gate *except=nullptr)
Gate * new_and_gate(Clause *, int)
void find_representative_and_compress_both(int)
vector< LitClausePair > mu2_ids
void add_xor_shrinking_proof_chain(Gate *g, int src)
void delete_proof_chain()
Clause * new_tmp_clause(std::vector< int > &clause)
void simplify_ite_gate_then_else_set(Gate *g, std::vector< LRAT_ID > &reasons_implication, std::vector< LRAT_ID > &reasons_back, size_t idx1, size_t idx2)
bool simplify_gate(Gate *g)
bool propagate_equivalence(int lit)
void check_xor_gate_implied(Gate const *const)
std::vector< Clause * > new_unwatched_binary_clauses
void set_mu1_reason(int lit, Clause *c)
Clause * produce_rewritten_clause_lrat(Clause *c, int execept_lhs=0, bool remove_units=true, bool=true)
signed char & marked(int lit)
void add_ite_turned_and_binary_clauses(Gate *g)
void copy_conditional_equivalences(int lit, lit_implications &condbin)
vector< LitClausePair > mu1_ids
void extract_and_gates_with_base_clause(Clause *c)
vector< LitClausePair > mu4_ids
Gate * find_remaining_and_gate(Clause *base_clause, int lhs)
void extract_condeq_pairs(int lit, lit_implications &condbin, lit_equivalences &condeq)
Gate * find_xor_lits(const vector< int > &rhs)
vector< LitClausePair > pos_lhs_ids
vector< LitClausePair > neg_lhs_ids
size_t operator()(const Gate *const g) const
std::array< int, 16 > & nonces
void mark_duplicated_binary_clauses_as_garbage()
vector< int64_t > lrat_chain
void report(char type, int verbose_level=0)
void learn_empty_clause()
void backtrack(int target_level=0)
vector< Clause * > clauses
Watches & watches(int lit)
bool operator()(const CompactBinary &a, const CompactBinary &b)
uint64_t operator()(const CompactBinary &a)
bool operator()(const int &a, const int &b) const
congruence_occurrences_larger(Internal *s)
congruence_occurrences_rank(Internal *s)
lit_equivalence negate_both()
Type operator()(const lit_implication &a) const
CaDiCaL::Internal * internal
litpair_rank(Internal *i)
bool operator()(const lit_implication &a, const lit_implication &b) const
litpair_smaller(Internal *i)
CaDiCaL::Internal * internal
Type operator()(const LitClausePair &a)
sort_literals_by_var_rank_except(Internal *i, int my_lhs, int except2)
sort_literals_by_var_rank_except(Internal *i, int my_lhs)
CaDiCaL::Internal * internal
Type operator()(const int &a) const
sort_literals_by_var_rank(Internal *i)
Type operator()(const int &a) const
CaDiCaL::Internal * internal
sort_literals_by_var_smaller_except(Internal *i, int my_lhs, int except2)
sort_literals_by_var_smaller_except(Internal *i, int my_lhs)
bool operator()(const int &a, const int &b) const
CaDiCaL::Internal * internal
CaDiCaL::Internal * internal
bool operator()(const int &a, const int &b) const
sort_literals_by_var_smaller(Internal *i)
#define smaller(tree, n, m, depth)