16static void assign_and_propagate_units (
kissat *
solver, unsigneds *units) {
19 LOG (
"assigning and propagating %zu units",
SIZE_STACK (*units));
22 LOG (
"trying to assign and propagate unit %s now",
LOGLIT (unit));
25 LOG (
"skipping satisfied unit %s",
LOGLIT (unit));
26 }
else if (
value < 0) {
27 LOG (
"inconsistent unit %s",
LOGLIT (unit));
30 solver->inconsistent =
true;
33 INC (substitute_units);
40static void determine_representatives (
kissat *
solver,
unsigned *repr) {
41 size_t bytes =
LITS *
sizeof (unsigned);
54 unsigned trivial_sccs = 0;
55 unsigned non_trivial_sccs = 0;
57 bool inconsistent =
false;
68 LOG (
"substitute root %s",
LOGLIT (root));
71 const unsigned mark_root = reached + 1;
77 const unsigned not_lit =
NOT (
lit);
78 unsigned reach_lit = reach[
lit];
84 ticks += 1 + kissat_cache_lines (size_watches,
sizeof (
watch));
89 const unsigned idx_other =
IDX (other);
90 if (!
flags[idx_other].active)
93 unsigned reach_other = reach[other];
94 if (reach_other < reach_lit)
95 reach_lit = reach_other;
97 if (reach_lit != mark_lit) {
99 reach[
lit] = reach_lit;
103 unsigned *begin_scc = end_scc;
106 while (*--begin_scc !=
lit);
108 const size_t size_scc = end_scc - begin_scc;
109 unsigned min_lit =
lit;
111 for (
const unsigned *
p = begin_scc;
p != end_scc;
p++) {
112 const unsigned other = *
p;
119 LOG (
"size %zu SCC entered trough %s representative %s", size_scc,
128 for (
const unsigned *
p = begin_scc;
p != end_scc;
p++) {
129 const unsigned other = *
p;
130 LOG (
"substitute repr[%s] = %s",
LOGLIT (other),
132 repr[other] = min_lit;
133 reach[other] = UINT_MAX;
135 const unsigned not_other =
NOT (other);
136 const unsigned repr_not_other = repr[not_other];
139 if (min_lit == repr_not_other) {
140 LOG (
"clashing literals %s and %s in same SCC",
LOGLIT (other),
149 const unsigned mark_not_other =
mark[not_other];
152 if (mark_root > mark_not_other)
154 LOG (
"root %s implies both %s and %s",
LOGLIT (root),
156 const unsigned unit =
NOT (root);
166 LOG (
"substitute mark[%s] = %u",
LOGLIT (
lit), reached);
167 const unsigned not_lit =
NOT (
lit);
170 ticks += 1 + kissat_cache_lines (size_watches,
sizeof (
watch));
175 const unsigned idx_other =
IDX (other);
176 if (!
flags[idx_other].active)
188 "determining substitution "
189 "representatives took %" PRIu64
190 " 'substitute_ticks'",
192 ADD (substitute_ticks, ticks);
193 LOG (
"reached %u literals", reached);
194 LOG (
"found %u non-trivial SCCs", non_trivial_sccs);
195 LOG (
"found %u trivial SCCs", trivial_sccs);
197 assign_and_propagate_units (
solver, &units);
207static bool *add_representative_equivalences (
kissat *
solver,
215 const unsigned lit =
LIT (idx);
216 const unsigned other = repr[
lit];
220#ifdef CHECKING_OR_PROVING
221 const unsigned not_lit =
NOT (
lit);
222 const unsigned not_other =
NOT (other);
230 eliminate[idx] =
true;
235static void remove_representative_equivalences (
kissat *
solver,
238 if (!
solver->inconsistent) {
240 const bool incremental =
GET_OPTION (incremental);
247 const unsigned lit =
LIT (idx);
248 const unsigned other = repr[
lit];
249 const unsigned not_lit =
NOT (
lit);
250 const unsigned not_other =
NOT (other);
262 const value other_value = values[other];
263 if (incremental || other_value) {
264 if (other_value <= 0)
266 if (other_value >= 0)
278static void substitute_binaries (
kissat *
solver,
unsigned *repr) {
282 statches *delayed_watched = (statches *) &
solver->delayed;
286 size_t substituted = 0;
290 litwatches delayed_deleted;
292#ifdef CHECKING_OR_PROVING
293 litpairs delayed_removed;
297 const unsigned repr_lit = repr[
lit];
298 const unsigned not_repr_lit =
NOT (repr_lit);
308 const unsigned repr_other = repr[other];
311 if (repr_other == not_repr_lit) {
312 LOGBINARY (repr_other, repr_lit,
"becomes tautological");
319 }
else if (repr_other == repr_lit) {
320 const unsigned unit = repr_lit;
321 LOG (
"simplifies to unit %s",
LOGLIT (unit));
332 if (
lit == repr_lit && other == repr_other) {
336 if (
lit == repr_lit) {
337 LOGBINARY (repr_lit, repr_other,
"substituted in place");
340 LOGBINARY (repr_lit, repr_other,
"delayed substituted");
348#ifdef CHECKING_OR_PROVING
361 watches = all_watches + repr_lit;
366 assign_and_propagate_units (
solver, &units);
376#ifdef CHECKING_OR_PROVING
385 LOG (
"substituted %zu binary clauses", substituted);
386 LOG (
"removed %zu binary clauses", removed);
389static void substitute_clauses (
kissat *
solver,
unsigned *repr) {
395 size_t substituted = 0;
400 references delayed_garbage;
405 LOGCLS (c,
"substituting");
408 bool satisfied =
false;
409 bool substitute =
false;
410 bool tautological =
false;
412 const value lit_value = values[
lit];
423 const unsigned repr_lit = repr[
lit];
424 const value repr_value = values[repr_lit];
425 if (repr_value < 0) {
426 LOG (
"dropping falsified substituted %s (was %s)",
431 if (repr_value > 0) {
432 LOGCLS (c,
"satisfied by substituted %s (was %s)",
437 if (
lit != repr_lit) {
439 LOG (
"substituted literal %s (was %s)",
LOGLIT (repr_lit),
444 if (marks[repr_lit]) {
446 LOG (
"skipping duplicated %s",
LOGLIT (repr_lit));
449 const unsigned not_repr_lit =
NOT (repr_lit);
450 if (marks[not_repr_lit]) {
451 LOG (
"substituted clause tautological "
452 "containing both %s and %s",
457 marks[repr_lit] =
true;
460 if (satisfied || tautological) {
465 }
else if (substitute || shrink) {
468 LOG (
"simplifies to empty clause");
473 solver->inconsistent =
true;
475 }
else if (size == 1) {
485 }
else if (size == 2) {
492 LOGCLS (c,
"unsubstituted");
493 LOGBINARY (first, second,
"substituted");
500 LOGCLS (c,
"unsubstituted");
511 const unsigned old_size = c->size;
512 unsigned *old_lits = c->lits;
515 memcpy (old_lits, new_lits, new_size *
sizeof *old_lits);
518 if (new_size < old_size) {
527 LOGCLS (c,
"unsorted substituted");
535 assign_and_propagate_units (
solver, &units);
542 LOG (
"substituted %zu large clauses", substituted);
543 LOG (
"removed %zu substituted large clauses", removed);
546static bool substitute_round (
kissat *
solver,
unsigned round) {
548 const unsigned active =
solver->active;
549 size_t bytes =
LITS *
sizeof (unsigned);
551 memset (repr, 0xff, bytes);
552 determine_representatives (
solver, repr);
553 bool *eliminate = add_representative_equivalences (
solver, repr);
554 substitute_binaries (
solver, repr);
555 substitute_clauses (
solver, repr);
556 remove_representative_equivalences (
solver, repr, eliminate);
558 unsigned removed = active -
solver->active;
560 "round %u removed %u variables %.0f%%", round, removed,
561 kissat_percent (removed, active));
567 return !
solver->inconsistent && removed;
570static void substitute_rounds (
kissat *
solver,
bool complete) {
573 const unsigned maxrounds =
GET_OPTION (substituterounds);
574 for (
unsigned round = 1; round <= maxrounds; round++) {
575 const uint64_t before =
solver->statistics_.substitute_ticks;
576 if (!substitute_round (
solver, round))
578 const uint64_t after =
solver->statistics_.substitute_ticks;
579 const uint64_t ticks = after - before;
582 solver->statistics_.search_ticks -
solver->last.ticks.probe;
583 const double fraction =
GET_OPTION (substituteeffort) * 1e-3;
584 const uint64_t limit = fraction *
reference;
588 "last substitute round took %" PRIu64
" 'substitute_ticks' "
589 "> limit %" PRIu64
" = %g * %" PRIu64
" 'search_ticks'",
595 if (!
solver->inconsistent) {
597 LOG (
"now all large clauses are watched after binary clauses");
598 solver->large_clauses_watched_after_binary_clauses =
true;
599 kissat_reset_propagate (
solver);
612 LOG (
"assuming not all large clauses watched after binary clauses");
613 solver->large_clauses_watched_after_binary_clauses =
false;
618 substitute_rounds (
solver, complete);
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_malloc(kissat *solver, size_t bytes)
void * kissat_calloc(kissat *solver, size_t n, size_t size)
void kissat_free(kissat *solver, void *ptr, size_t bytes)
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
void kissat_learned_unit(kissat *solver, unsigned lit)
#define all_stack(T, E, S)
#define SET_END_OF_STACK(S, P)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define REMOVE_CHECKER_CLAUSE(...)
#define CHECK_AND_ADD_LITS(...)
#define CHECK_AND_ADD_EMPTY(...)
#define CHECK_AND_ADD_BINARY(...)
#define REMOVE_CHECKER_BINARY(...)
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
void kissat_new_binary_clause(kissat *solver, unsigned first, unsigned second)
void kissat_delete_binary(kissat *solver, unsigned a, unsigned b)
void kissat_mark_eliminated_variable(kissat *solver, unsigned idx)
#define all_variables(IDX)
#define all_literals(LIT)
#define all_literals_in_clause(LIT, C)
#define KISSAT_assert(ignore)
#define kissat_extremely_verbose(...)
#define kissat_phase(...)
#define ADD_EMPTY_TO_PROOF(...)
#define ADD_BINARY_TO_PROOF(...)
#define DELETE_CLAUSE_FROM_PROOF(...)
#define ADD_LITS_TO_PROOF(...)
#define DELETE_BINARY_FROM_PROOF(...)
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
ABC_NAMESPACE_HEADER_START typedef unsigned reference
#define kissat_check_statistics(...)
void kissat_substitute(kissat *solver, bool complete)
#define substitute_terminated_1
void kissat_watch_large_clauses(kissat *solver)
#define BEGIN_WATCHES(WS)
#define PUSH_WATCHES(W, E)
#define all_binary_blocking_watches(WATCH, WATCHES)
#define SET_END_OF_WATCHES(WS, P)
void kissat_weaken_binary(kissat *solver, unsigned lit, unsigned other)
void kissat_weaken_unit(kissat *solver, unsigned lit)