26static inline bool more_occurrences (
unsigned *counts,
unsigned a,
28 const unsigned s = counts[a], t = counts[b];
29 return ((t - s) | ((b - a) & ~(s - t))) >> 31;
32#define MORE_OCCURRENCES(A, B) more_occurrences (counts, (A), (B))
34static void vivify_sort_lits_by_counts (
kissat *
solver,
size_t size,
35 unsigned *lits,
unsigned *counts) {
39static void vivify_sort_stack_by_counts (
kissat *
solver, unsigneds *stack,
43 vivify_sort_lits_by_counts (
solver, size, lits, counts);
51static inline void count_literal (
unsigned lit,
unsigned *counts) {
52 counts[
lit] += counts[
lit] < (unsigned) INT_MAX;
55static void count_clause (
clause *c,
unsigned *counts) {
57 count_literal (
lit, counts);
60static bool simplify_vivification_candidate (
kissat *
solver,
80 if (non_false == c->
size)
86 LOGBINARY (first, second,
"vivification shrunken candidate");
100 const unsigned old_size = c->
size;
101 unsigned new_size = 0, *lits = c->
lits;
102 for (
unsigned i = 0; i < old_size; i++) {
103 const unsigned lit = lits[i];
107 lits[new_size++] =
lit;
124 LOGCLS (c,
"vivification shrunken candidate");
125 LOG (
"vivification candidate does not need to be simplified");
138#define COUNTREF_COUNTS 1
139#define LD_MAX_COUNTREF_SIZE 31
140#define MAX_COUNTREF_SIZE ((1u << LD_MAX_COUNTREF_SIZE) - 1)
156 size_t scheduled, tried, vivified;
175 LOG (
"initialized vivifier");
200 vivifier->mode =
"vivify-irredundant";
207 LOG (
"set vivifier tier %d mode '%s' with tag '%c'", tier,
vivifier->mode,
215 LOG (
"clearing vivifier");
216 unsigned *counts =
vivifier->counts;
225 LOG (
"releasing vivifier");
226 unsigned *counts =
vivifier->counts;
235 LOG (
"scheduling vivification candidates");
237 unsigned lower_glue_limit, upper_glue_limit;
238 unsigned tier1 = vivify_tier1_limit (
solver);
239 unsigned tier2 =
MAX (tier1, vivify_tier2_limit (
solver));
243 lower_glue_limit = 0;
244 upper_glue_limit = tier1;
247 lower_glue_limit = tier1 < tier2 ? tier1 + 1 : 0;
248 upper_glue_limit = tier2;
251 lower_glue_limit = tier2 + 1;
252 upper_glue_limit = UINT_MAX;
256 lower_glue_limit = 0;
257 upper_glue_limit = UINT_MAX;
262 size_t prioritized = 0;
263 unsigned *counts =
vivifier->counts;
264 references *schedule = &
vivifier->schedule;
265 for (
unsigned prioritize = 0; prioritize < 2; prioritize++) {
270 count_clause (c, counts);
274 if (c->
glue < lower_glue_limit)
276 if (c->
glue > upper_glue_limit)
280 if (c->
vivify != prioritize)
282 if (simplify_vivification_candidate (
solver, c))
294 "prioritized %zu clauses %.0f%%", prioritized,
295 kissat_percent (prioritized, scheduled));
298 "prioritizing all %zu scheduled clauses", scheduled);
309static inline bool worse_candidate (
kissat *
solver,
unsigned *counts,
311 const clause *
const c = kissat_dereference_clause (
solver, r);
312 const clause *
const d = kissat_dereference_clause (
solver, s);
322 const unsigned *
const e =
END_LITS (c);
323 const unsigned *
const f =
END_LITS (d);
327 while (
p != e && q != f) {
330 const unsigned u = counts[a];
331 const unsigned v = counts[b];
338 if (
p != e && q == f)
341 if (
p == e && q != f)
354#define WORSE_CANDIDATE(A, B) worse_candidate (solver, counts, (A), (B))
359 unsigned *counts =
vivifier->counts;
360 references *schedule = &
vivifier->schedule;
366 unsigned *counts =
vivifier->counts;
367 references *schedule = &
vivifier->schedule;
370 vivify_sort_clause_by_counts (
solver, c, counts);
384 unsigned best_count = 0;
386 int continue_with_next_literal = 0;
387 for (
unsigned j = 0; j != i; j++)
388 if (lits[j] ==
lit) {
389 continue_with_next_literal = 1;
392 if(continue_with_next_literal) {
395 const unsigned lit_count = counts[
lit];
397 if (lit_count <= best_count)
399 best_count = lit_count;
404 cr->
count[i] = best_count;
411 references *schedule = &
vivifier->schedule;
412 countrefs *countrefs = &
vivifier->countrefs;
413 unsigned *counts =
vivifier->counts;
418 init_countref (&
countref, c, ref, counts);
424#define RANK_COUNTREF_BY_INVERSE_SIZE(CR) ((unsigned) (~(CR).size))
425#define RANK_COUNTREF_BY_VIVIFY(CR) ((unsigned) ((CR).vivify))
426#define RANK_COUNTREF_BY_COUNT(CR) \
427 ((unsigned) ((CR).count[COUNTREF_COUNTS - 1 - i]))
431 countrefs *countrefs = &
vivifier->countrefs;
441 references *schedule = &
vivifier->schedule;
442 countrefs *countrefs = &
vivifier->countrefs;
456 solver,
"sorting %s vivification candidates precisely",
458 sort_scheduled_candidate_literals (
vivifier);
459 sort_vivification_candidates_after_sorting_literals (
vivifier);
463 "sorting %s vivification candidates imprecisely "
464 "by first %u literals",
467 rank_vivification_candidates (
vivifier);
474 clause *conflict,
unsigned implied,
475 clause **subsuming_ptr,
bool *redundant_ptr) {
477 LOG (
"starting vivification conflict analysis");
478 bool redundant =
false;
479 bool subsumes =
false;
486 unsigned not_implied =
NOT (implied);
487 LOG (
"vivify analyzing %s",
LOGLIT (not_implied));
505 LOG (
"vivify analyzing %s",
LOGLIT (other));
512 if (
solver->marks[other] <= 0)
519 LOGCLS (reason,
"vivify subsuming");
520 *subsuming_ptr = reason;
529 const unsigned lit =
NOT (not_lit);
536 LOG (
"vivify analyzing decision %s",
LOGLIT (not_lit));
539 const unsigned other = a->
reason;
540 if (marks[
lit] > 0 && marks[other] > 0) {
543 *subsuming_ptr = kissat_binary_conflict (
solver,
lit, other);
557 clause *reason = kissat_dereference_clause (
solver, ref);
563 if (marks[other] <= 0)
581 LOGCLS (reason,
"vivify subsuming");
582 *subsuming_ptr = reason;
588 LOG (
"vivification analysis %s redundant clause",
589 redundant ?
"used" :
"without");
590 LOGTMP (
"vivification analysis");
592 *redundant_ptr = redundant;
597 LOG (
"reset vivification conflict analysis");
600 const unsigned idx =
IDX (
lit);
608static bool vivify_shrinkable (
kissat *
solver, unsigneds *sorted,
615 unsigned count_implied = 0;
619 LOG (
"vivification unassigned %s thus shrinking",
LOGLIT (
lit));
623 LOG (
"vivification implied satisfied %s",
LOGLIT (
lit));
625 LOG (
"at least one implied literal with conflict thus shrinking");
628 if (count_implied++) {
629 LOG (
"at least two implied literals thus shrinking");
634 const unsigned idx =
IDX (
lit);
638 LOG (
"vivification non-analyzed %s thus shrinking",
LOGLIT (
lit));
642 LOG (
"vivification implied falsified %s thus shrinking",
648 LOG (
"vivification learned clause not shrinkable");
653 LOG (
"vivification learns unit clause");
668 LOG (
"vivification learns binary clause");
678static void swap_first_literal_with_best_watch (
kissat *
solver,
682 unsigned *best_ptr = lits;
683 unsigned first = *best_ptr, best = first;
685 unsigned best_level =
LEVEL (best);
686 const unsigned *
const end = lits +
size;
687 for (
unsigned *
p = lits + 1;
value < 0 &&
p != end;
p++) {
692 if (
level <= best_level)
699 if (best_ptr == lits)
707 unsigned *lits = c->
lits;
709 kissat_unwatch_blocking (
solver, lits[0], ref);
710 kissat_unwatch_blocking (
solver, lits[1], ref);
715 unsigned *lits = c->
lits;
717 swap_first_literal_with_best_watch (
solver, lits, size);
718 swap_first_literal_with_best_watch (
solver, lits + 1, size - 1);
719 kissat_watch_blocking (
solver, lits[0], lits[1], ref);
720 kissat_watch_blocking (
solver, lits[1], lits[0], ref);
726 LOG (
"vivification learns large clause");
734 vivify_unwatch_clause (
solver, c);
740 kissat_mark_removed_literal (
solver,
lit);
743 unsigneds *learned = &
solver->clause;
744 const unsigned old_size = c->
size;
745 const unsigned new_size =
SIZE_STACK (*learned);
748 unsigned *lits = c->
lits;
766 LOGCLS (c,
"vivified shrunken after conflict");
769 LOGCLS (c,
"vivified shrunken after implied");
773 vivify_watch_clause (
solver, c);
779 vivify_learn_unit (
solver, c);
781 vivify_learn_binary (
solver, c);
783 vivify_learn_large (
solver, c, implied);
786static void binary_strengthen_after_instantiation (
kissat *
solver,
789 LOG (
"vivification instantiation yields binary clause");
807 LOGBINARY (first, second,
"vivified strengthened through instantiation");
822 LOG (
"vivification instantiation yields large clause");
828 vivify_unwatch_clause (
solver, c);
831 const unsigned old_size = c->
size;
833 unsigned new_size = 0, *lits = c->
lits;
834 for (
unsigned i = 0; i != old_size; i++) {
835 const unsigned lit = lits[i];
838 kissat_mark_removed_literal (
solver,
lit);
839 }
else if (kissat_fixed (
solver,
lit) >= 0) {
840 lits[new_size++] =
lit;
855 LOGCLS (c,
"vivified strengthened through instantiation");
858 vivify_watch_clause (
solver, c);
861static void vivify_strengthen_after_instantiation (
kissat *
solver,
869 binary_strengthen_after_instantiation (
solver, c, remove);
871 large_strengthen_after_instantiation (
solver, c, remove);
876 LOG (
"marking sorted literals");
877 unsigneds *sorted = &
vivifier->sorted;
885 LOG (
"unmarking sorted literals");
886 unsigneds *sorted = &
vivifier->sorted;
893static void reestablish_watch_invariant_for_candidate (
kissat *
solver,
900 unsigned first = lits[0];
901 unsigned second = lits[1];
902 const signed char first_val =
VALUE (first);
903 const signed char second_val =
VALUE (second);
904 unsigned first_level = first_val ?
LEVEL (first) : 0;
905 unsigned second_level = second_val ?
LEVEL (second) : 0;
907 if (first_val >= 0 && second_val >= 0)
909 if (first_val < 0 && !second_val)
910 new_level = first_level;
911 else if (first_val < 0 && second_val > 0) {
912 if (first_level >= second_level)
914 new_level = first_level;
915 }
else if (second_val < 0 && !first_val)
916 new_level = second_level;
917 else if (second_val < 0 && first_val > 0) {
918 if (second_level >= first_level)
920 new_level = second_level;
923 new_level =
MIN (first_level, second_level);
926 LOGCLS (
candidate,
"reestablish watch invariant by backtracking to %u",
943 "vivifying unsorted counted candidate");
945 unsigneds *sorted = &
vivifier->sorted;
962 const unsigned non_false =
SIZE_STACK (*sorted);
969 LOG (
"all literals root level unassigned");
971 LOG (
"found %u root level non-falsified literals", non_false);
974 if (non_false == 2) {
1004 if (a->
reason != cand_ref)
1009 LOG (
"non-reason candidate clause");
1011 LOG (
"candidate is the reason of %s",
LOGLIT (unit));
1014 LOG (
"forced to backtrack to level %u",
level - 1);
1021 unsigned *counts =
vivifier->counts;
1022 vivify_sort_stack_by_counts (
solver, sorted, counts);
1027 counts,
"vivifying sorted redundant glue %u",
1031 counts,
"vivifying sorted irredundant");
1034 vivify_mark_sorted_literals (
vivifier);
1043 const unsigned not_lit =
NOT (
lit);
1045 LOG (
"reusing assumption %s",
LOGLIT (not_lit));
1046 INC (vivify_reused);
1047 INC (vivify_probes);
1052 LOG (
"forced to backtrack to decision level %u",
level - 1);
1067 LOG (
"literal %s already initially satisfied",
LOGLIT (
lit));
1075 const unsigned not_lit =
NOT (
lit);
1076 INC (vivify_probes);
1081 const unsigned *
p =
solver->propagate;
1087 const signed char *
const marks =
solver->marks;
1089 const unsigned other = *
p++;
1090 const signed char mark = marks[other];
1092 LOG (
"literal %s already implied satisfied",
LOGLIT (other));
1094 goto EXIT_ASSUMPTION_LOOP;
1098EXIT_ASSUMPTION_LOOP:;
1102 LOG (
"vivification assumptions propagate without conflict nor "
1103 "producing an implied literal");
1114 if (lit_trail > better_implied_trail)
1116 better_implied_trail = lit_trail;
1117 better_implied =
lit;
1119 if (better_implied != implied) {
1120 LOG (
"better implied satisfied literal %s at level %u",
1122 implied = better_implied;
1126 unsigned level_after_assumptions =
solver->level;
1130 bool redundant =
false;
1134 vivify_unmark_sorted_literals (
vivifier);
1144 LOG (
"vivify candidate with smaller glue than subsuming clause");
1147 INC (vivified_subred);
1148 INC (vivified_subsumed);
1154 INC (vivified_subirr);
1155 INC (vivified_subsumed);
1164 solver->statistics_.clauses_redundant--;
1166 solver->statistics_.clauses_irredundant++;
1167 INC (vivified_promoted);
1168 LOGCLS (subsuming,
"vivification promoted from redundant to");
1171 INC (vivified_subirr);
1172 INC (vivified_subsumed);
1175 }
else if (vivify_shrinkable (
solver, sorted, conflict)) {
1177 INC (vivified_shrunken);
1179 INC (vivified_shrunkred);
1181 INC (vivified_shrunkirr);
1186 INC (vivified_implied);
1188 }
else if ((conflict || implied !=
INVALID_LIT) &&
1192 INC (vivified_asym);
1196 "no vivification instantiation with implied literal %s",
1207 LOG (
"trying vivification instantiation of %s#%u respectively %s#%u",
1216 LOG (
"vivification instantiation succeeded");
1218 INC (vivified_instantiated);
1220 INC (vivified_instred);
1222 INC (vivified_instirr);
1225 LOG (
"vivification instantiation failed");
1232 if (conflict &&
solver->level == level_after_assumptions) {
1233 LOG (
"forcing backtracking at least one level after conflict");
1242 INC (vivified_tier1);
1245 INC (vivified_tier2);
1248 INC (vivified_tier3);
1252 INC (vivified_irredundant);
1257 LOG (
"vivification %s", res ?
"succeeded" :
"failed");
1274 schedule_vivification_candidates (
vivifier);
1277 sort_vivification_candidates (
vivifier);
1280 solver,
"not sorting %s vivification candidates",
vivifier->name);
1285 uint64_t start =
solver->statistics_.probing_ticks;
1286 uint64_t delta = limit - start;
1288 "vivification %s effort limit %" PRIu64
" = %" PRIu64
1289 " + %" PRIu64
" 'probing_ticks'",
1290 vivifier->name, limit, start, delta);
1294 "scheduled %zu clauses %.0f%% of %zu", scheduled,
1295 kissat_percent (scheduled, total), total);
1300 const uint64_t probing_ticks =
solver->statistics_.probing_ticks;
1301 if (probing_ticks > limit) {
1303 "vivification %s ticks limit %" PRIu64
1304 " hit after %" PRIu64
" 'probing_ticks'",
1305 vivifier->name, limit, probing_ticks);
1316 if (
solver->inconsistent)
1324 "vivified %zu clauses %.0f%% out of %zu tried",
1328 if (!
solver->inconsistent) {
1332 "%zu clauses remain %.0f%% out of %zu scheduled",
1333 remain, kissat_percent (remain, scheduled), scheduled);
1336 size_t prioritized = 0;
1345 "no remaining prioritized clauses");
1348 "keeping all %zu remaining clauses "
1349 "prioritized %.0f%%",
1350 prioritized, kissat_percent (prioritized, remain));
1353 "no untried clauses remain");
1403 if (
solver->inconsistent)
1413 double tier1_budget =
GET_OPTION (vivifytier1);
1414 double tier2_budget =
GET_OPTION (vivifytier2);
1415 double tier3_buget =
GET_OPTION (vivifytier3);
1417 tier1_budget = tier2_budget = tier3_buget = 0;
1418 double sum = irr_budget + tier1_budget + tier2_budget + tier3_buget;
1423 INC (vivifications);
1424#if !defined(KISSAT_NDEBUG) || defined(METRICS)
1426 solver->vivifying =
true;
1430 const uint64_t total = limit -
solver->statistics_.probing_ticks;
1431 limit =
solver->statistics_.probing_ticks;
1432 unsigned tier1_limit = vivify_tier1_limit (
solver);
1433 unsigned tier2_limit = vivify_tier2_limit (
solver);
1434 if (tier1_budget && tier2_budget && tier1_limit == tier2_limit) {
1435 tier1_budget += tier2_budget, tier2_budget = 0;
1436 LOG (
"vivification tier1 matches tier2 "
1437 "thus using tier2 budget for tier1");
1444 limit += (total * tier1_budget) / sum;
1447 if (tier2_budget && !
solver->inconsistent &&
1449 limit += (total * tier2_budget) / sum;
1452 if (tier3_buget && !
solver->inconsistent &&
1454 limit += (total * tier3_buget) / sum;
1457 if (irr_budget && !
solver->inconsistent &&
1459 limit += (total * irr_budget) / sum;
1460 vivify_irredundant (&
vivifier, limit);
1470 if (
solver->statistics_.probing_ticks < limit) {
1471 uint64_t delta = limit -
solver->statistics_.probing_ticks;
1473 "has %" PRIu64
" ticks left %.2f%%", delta,
1474 kissat_percent (delta, total));
1476 uint64_t delta =
solver->statistics_.probing_ticks - limit;
1478 "exceeded by %" PRIu64
" ticks %.2f%%", delta,
1479 kissat_percent (delta, total));
1482#if !defined(KISSAT_NDEBUG) || defined(METRICS)
1484 solver->vivifying =
false;
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_calloc(kissat *solver, size_t n, size_t size)
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
ABC_NAMESPACE_HEADER_START typedef word ward
void kissat_learned_unit(kissat *solver, unsigned lit)
void kissat_backtrack_without_updating_phases(kissat *solver, unsigned new_level)
#define all_stack(T, E, S)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define REMOVE_CHECKER_CLAUSE(...)
#define CHECK_AND_ADD_STACK(...)
#define CHECK_SHRINK_CLAUSE(...)
reference kissat_new_redundant_clause(kissat *solver, unsigned glue)
reference kissat_new_irredundant_clause(kissat *solver)
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
void kissat_new_binary_clause(kissat *solver, unsigned first, unsigned second)
void kissat_update_last_irredundant(kissat *solver, clause *irredundant)
void kissat_internal_assume(kissat *solver, unsigned lit)
bool kissat_recompute_and_promote(kissat *solver, clause *c)
void kissat_mark_added_literals(kissat *solver, unsigned size, unsigned *lits)
#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 SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
#define LOGCOUNTEDREFLITS(...)
#define LOGCOUNTEDCLS(...)
#define kissat_extremely_verbose(...)
#define kissat_very_verbose(...)
#define kissat_phase(...)
#define SHRINK_CLAUSE_IN_PROOF(...)
#define DELETE_CLAUSE_FROM_PROOF(...)
#define ADD_STACK_TO_PROOF(...)
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
ABC_NAMESPACE_HEADER_START typedef unsigned reference
#define IRREDUNDANT_CLAUSES
#define REDUNDANT_CLAUSES
unsigned count[COUNTREF_COUNTS]
#define vivify_terminated_3
#define vivify_terminated_5
#define vivify_terminated_2
#define vivify_terminated_1
#define vivify_terminated_4
#define MORE_OCCURRENCES(A, B)
#define MAX_COUNTREF_SIZE
#define RANK_COUNTREF_BY_VIVIFY(CR)
#define WORSE_CANDIDATE(A, B)
#define RANK_COUNTREF_BY_INVERSE_SIZE(CR)
void kissat_vivify(kissat *solver)
#define LD_MAX_COUNTREF_SIZE
#define RANK_COUNTREF_BY_COUNT(CR)
void kissat_watch_large_clauses(kissat *solver)
void kissat_flush_large_watches(kissat *solver)