ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
vivify.c
Go to the documentation of this file.
1#include "vivify.h"
2#include "allocate.h"
3#include "backtrack.h"
4#include "collect.h"
5#include "colors.h"
6#include "decide.h"
7#include "deduce.h"
8#include "inline.h"
9#include "print.h"
10#include "promote.h"
11#include "proprobe.h"
12#include "rank.h"
13#include "report.h"
14#include "sort.h"
15#include "terminate.h"
16#include "tiers.h"
17#include "trail.h"
18
19#include "cover.h"
20
21#include <inttypes.h>
22#include <string.h>
23
25
26static inline bool more_occurrences (unsigned *counts, unsigned a,
27 unsigned b) {
28 const unsigned s = counts[a], t = counts[b];
29 return ((t - s) | ((b - a) & ~(s - t))) >> 31;
30}
31
32#define MORE_OCCURRENCES(A, B) more_occurrences (counts, (A), (B))
33
34static void vivify_sort_lits_by_counts (kissat *solver, size_t size,
35 unsigned *lits, unsigned *counts) {
36 SORT (unsigned, size, lits, MORE_OCCURRENCES);
37}
38
39static void vivify_sort_stack_by_counts (kissat *solver, unsigneds *stack,
40 unsigned *counts) {
41 const size_t size = SIZE_STACK (*stack);
42 unsigned *lits = BEGIN_STACK (*stack);
43 vivify_sort_lits_by_counts (solver, size, lits, counts);
44}
45
46static void vivify_sort_clause_by_counts (kissat *solver, clause *c,
47 unsigned *counts) {
48 vivify_sort_lits_by_counts (solver, c->size, c->lits, counts);
49}
50
51static inline void count_literal (unsigned lit, unsigned *counts) {
52 counts[lit] += counts[lit] < (unsigned) INT_MAX;
53}
54
55static void count_clause (clause *c, unsigned *counts) {
57 count_literal (lit, counts);
58}
59
60static bool simplify_vivification_candidate (kissat *solver,
61 clause *const c) {
62 KISSAT_assert (!solver->level);
63 CLEAR_STACK (solver->clause);
64
65 const value *const values = solver->values;
66
67 for (all_literals_in_clause (lit, c)) {
68 const value value = values[lit];
69 if (value > 0) {
70 LOGCLS (c, "vivification %s satisfied candidate", LOGLIT (lit));
72 return true;
73 }
74 if (!value)
75 PUSH_STACK (solver->clause, lit);
76 }
77
78 unsigned non_false = SIZE_STACK (solver->clause);
79 KISSAT_assert (non_false <= c->size);
80 if (non_false == c->size)
81 return false;
82
83 if (non_false == 2) {
84 const unsigned first = PEEK_STACK (solver->clause, 0);
85 const unsigned second = PEEK_STACK (solver->clause, 1);
86 LOGBINARY (first, second, "vivification shrunken candidate");
87 kissat_new_binary_clause (solver, first, second);
89 return true;
90 }
91
92 KISSAT_assert (2 < non_false);
93
95 ADD_STACK_TO_PROOF (solver->clause);
96
99
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];
104 const value value = values[lit];
105 KISSAT_assert (value <= 0);
106 if (!value)
107 lits[new_size++] = lit;
108 }
109
110 KISSAT_assert (2 < new_size);
111 KISSAT_assert (new_size == non_false);
112 KISSAT_assert (new_size < old_size);
113
114 c->size = new_size;
115 c->searched = 2;
116
117 if (c->redundant && c->glue >= new_size)
118 kissat_promote_clause (solver, c, new_size - 1);
119 if (!c->shrunken) {
120 c->shrunken = true;
121 lits[old_size - 1] = INVALID_LIT;
122 }
123
124 LOGCLS (c, "vivification shrunken candidate");
125 LOG ("vivification candidate does not need to be simplified");
126
127 return false;
128}
129
130static unsigned vivify_tier1_limit (kissat *solver) {
131 return GET_OPTION (vivifyfocusedtiers) ? solver->tier1[0] : TIER1;
132}
133
134static unsigned vivify_tier2_limit (kissat *solver) {
135 return GET_OPTION (vivifyfocusedtiers) ? solver->tier2[0] : TIER2;
136}
137
138#define COUNTREF_COUNTS 1
139#define LD_MAX_COUNTREF_SIZE 31
140#define MAX_COUNTREF_SIZE ((1u << LD_MAX_COUNTREF_SIZE) - 1)
141
142struct countref {
143 unsigned vivify : 1;
147};
148
149typedef struct countref countref;
150typedef STACK (countref) countrefs;
151
152struct vivifier {
153 kissat *solver;
154 unsigned *counts;
155 references schedule;
156 size_t scheduled, tried, vivified;
157 countrefs countrefs;
158 unsigneds sorted;
159#ifndef KISSAT_QUIET
160 const char *mode;
161 const char *name;
162 char tag;
163#endif
164 int tier;
165};
166
167typedef struct vivifier vivifier;
168
169static void init_vivifier (kissat *solver, vivifier *vivifier) {
170 vivifier->solver = solver;
171 vivifier->counts = (unsigned*)kissat_calloc (solver, LITS, sizeof (unsigned));
172 INIT_STACK (vivifier->schedule);
173 INIT_STACK (vivifier->countrefs);
174 INIT_STACK (vivifier->sorted);
175 LOG ("initialized vivifier");
176}
177
178static void set_vivifier_mode (vivifier *vivifier, int tier) {
179 vivifier->tier = tier;
180#ifndef KISSAT_QUIET
181 switch (tier) {
182 case 1:
183 vivifier->mode = "vivify-tier1";
184 vivifier->name = "tier1";
185 vivifier->tag = 'u';
186 break;
187 case 2:
188 vivifier->mode = "vivify-tier2";
189 vivifier->name = "tier2";
190 vivifier->tag = 'v';
191 break;
192 case 3:
193 KISSAT_assert (tier == 3);
194 vivifier->mode = "vivify-tier3";
195 vivifier->name = "tier3";
196 vivifier->tag = 'w';
197 break;
198 default:
199 KISSAT_assert (tier == 0);
200 vivifier->mode = "vivify-irredundant";
201 vivifier->name = "irredundant";
202 vivifier->tag = 'x';
203 break;
204 }
205#ifdef LOGGING
206 kissat *solver = vivifier->solver;
207 LOG ("set vivifier tier %d mode '%s' with tag '%c'", tier, vivifier->mode,
208 vivifier->tag);
209#endif
210#endif
211}
212
213static void clear_vivifier (vivifier *vivifier) {
214 kissat *solver = vivifier->solver;
215 LOG ("clearing vivifier");
216 unsigned *counts = vivifier->counts;
217 memset (counts, 0, LITS * sizeof *counts);
218 CLEAR_STACK (vivifier->schedule);
219 CLEAR_STACK (vivifier->countrefs);
220 CLEAR_STACK (vivifier->sorted);
221}
222
223static void release_vivifier (vivifier *vivifier) {
224 kissat *solver = vivifier->solver;
225 LOG ("releasing vivifier");
226 unsigned *counts = vivifier->counts;
227 kissat_dealloc (solver, counts, LITS, sizeof *counts);
228 RELEASE_STACK (vivifier->schedule);
229 RELEASE_STACK (vivifier->countrefs);
230 RELEASE_STACK (vivifier->sorted);
231}
232
233static void schedule_vivification_candidates (vivifier *vivifier) {
234 kissat *solver = vivifier->solver;
235 LOG ("scheduling vivification candidates");
236 int tier = vivifier->tier;
237 unsigned lower_glue_limit, upper_glue_limit;
238 unsigned tier1 = vivify_tier1_limit (solver);
239 unsigned tier2 = MAX (tier1, vivify_tier2_limit (solver));
240 KISSAT_assert (tier1 <= tier2);
241 switch (tier) {
242 case 1:
243 lower_glue_limit = 0;
244 upper_glue_limit = tier1;
245 break;
246 case 2:
247 lower_glue_limit = tier1 < tier2 ? tier1 + 1 : 0;
248 upper_glue_limit = tier2;
249 break;
250 case 3:
251 lower_glue_limit = tier2 + 1;
252 upper_glue_limit = UINT_MAX;
253 break;
254 default:
255 KISSAT_assert (tier == 0);
256 lower_glue_limit = 0;
257 upper_glue_limit = UINT_MAX;
258 break;
259 }
260 KISSAT_assert (lower_glue_limit <= upper_glue_limit);
261 ward *const arena = BEGIN_STACK (solver->arena);
262 size_t prioritized = 0;
263 unsigned *counts = vivifier->counts;
264 references *schedule = &vivifier->schedule;
265 for (unsigned prioritize = 0; prioritize < 2; prioritize++) {
266 for (all_clauses (c)) {
267 if (c->garbage)
268 continue;
269 if (prioritize)
270 count_clause (c, counts);
271 if (tier) {
272 if (!c->redundant)
273 continue;
274 if (c->glue < lower_glue_limit)
275 continue;
276 if (c->glue > upper_glue_limit)
277 continue;
278 } else if (c->redundant)
279 continue;
280 if (c->vivify != prioritize)
281 continue;
282 if (simplify_vivification_candidate (solver, c))
283 continue;
284 if (prioritize)
285 prioritized++;
286 const reference ref = (ward *) c - arena;
287 PUSH_STACK (*schedule, ref);
288 }
289 }
290 CLEAR_STACK (solver->clause);
291 size_t scheduled = SIZE_STACK (*schedule);
292 if (prioritized) {
293 kissat_phase (solver, vivifier->mode, GET (vivifications),
294 "prioritized %zu clauses %.0f%%", prioritized,
295 kissat_percent (prioritized, scheduled));
296 } else {
297 kissat_phase (solver, vivifier->mode, GET (vivifications),
298 "prioritizing all %zu scheduled clauses", scheduled);
299 for (all_stack (reference, ref, *schedule)) {
300 clause *c = (clause *) (arena + ref);
301 KISSAT_assert (kissat_clause_in_arena (solver, c));
302 c->vivify = true;
303 }
304 }
305 vivifier->scheduled = scheduled;
306 vivifier->tried = vivifier->vivified = 0;
307}
308
309static inline bool worse_candidate (kissat *solver, unsigned *counts,
310 reference r, reference s) {
311 const clause *const c = kissat_dereference_clause (solver, r);
312 const clause *const d = kissat_dereference_clause (solver, s);
313
314 if (!c->vivify && d->vivify)
315 return true;
316
317 if (c->vivify && !d->vivify)
318 return false;
319
320 unsigned const *p = BEGIN_LITS (c);
321 unsigned const *q = BEGIN_LITS (d);
322 const unsigned *const e = END_LITS (c);
323 const unsigned *const f = END_LITS (d);
324
325 unsigned a = INVALID_LIT, b = INVALID_LIT;
326
327 while (p != e && q != f) {
328 a = *p++;
329 b = *q++;
330 const unsigned u = counts[a];
331 const unsigned v = counts[b];
332 if (u < v)
333 return true;
334 if (u > v)
335 return false;
336 }
337
338 if (p != e && q == f)
339 return true;
340
341 if (p == e && q != f)
342 return false;
343
344 KISSAT_assert (p == e && q == f);
345
346 if (a < b)
347 return true;
348 if (a > b)
349 return false;
350
351 return r < s;
352}
353
354#define WORSE_CANDIDATE(A, B) worse_candidate (solver, counts, (A), (B))
355
356static void
357sort_vivification_candidates_after_sorting_literals (vivifier *vivifier) {
358 kissat *solver = vivifier->solver;
359 unsigned *counts = vivifier->counts;
360 references *schedule = &vivifier->schedule;
362}
363
364static void sort_scheduled_candidate_literals (vivifier *vivifier) {
365 kissat *solver = vivifier->solver;
366 unsigned *counts = vivifier->counts;
367 references *schedule = &vivifier->schedule;
368 for (all_stack (reference, ref, *schedule)) {
369 clause *c = kissat_dereference_clause (solver, ref);
370 vivify_sort_clause_by_counts (solver, c, counts);
371 }
372}
373
374static inline void init_countref (countref *cr, clause *c, reference ref,
375 unsigned *counts) {
378 cr->size = c->size;
379 cr->vivify = c->vivify;
380 cr->ref = ref;
381 unsigned lits[COUNTREF_COUNTS];
382 for (unsigned i = 0; i != COUNTREF_COUNTS; i++) {
383 unsigned best = INVALID_LIT;
384 unsigned best_count = 0;
385 for (all_literals_in_clause (lit, c)) {
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;
390 break;
391 }
392 if(continue_with_next_literal) {
393 continue;
394 }
395 const unsigned lit_count = counts[lit];
396 KISSAT_assert (lit_count);
397 if (lit_count <= best_count)
398 continue;
399 best_count = lit_count;
400 best = lit;
401 }
402 KISSAT_assert (best != INVALID_LIT);
403 KISSAT_assert (best_count);
404 cr->count[i] = best_count;
405 lits[i] = best;
406 }
407}
408
409static void init_countrefs (vivifier *vivifier) {
410 kissat *const solver = vivifier->solver;
411 references *schedule = &vivifier->schedule;
412 countrefs *countrefs = &vivifier->countrefs;
413 unsigned *counts = vivifier->counts;
414 KISSAT_assert (EMPTY_STACK (*countrefs));
415 for (all_stack (reference, ref, *schedule)) {
416 clause *c = kissat_dereference_clause (solver, ref);
418 init_countref (&countref, c, ref, counts);
419 PUSH_STACK (*countrefs, countref);
420 }
421 RELEASE_STACK (*schedule);
422}
423
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]))
428
429static void rank_vivification_candidates (vivifier *vivifier) {
430 kissat *solver = vivifier->solver;
431 countrefs *countrefs = &vivifier->countrefs;
432 RADIX_STACK (countref, unsigned, *countrefs,
434 for (unsigned i = 0; i != COUNTREF_COUNTS; i++)
435 RADIX_STACK (countref, unsigned, *countrefs, RANK_COUNTREF_BY_COUNT);
436 RADIX_STACK (countref, unsigned, *countrefs, RANK_COUNTREF_BY_VIVIFY);
437}
438
439static void copy_countrefs (vivifier *vivifier) {
440 kissat *solver = vivifier->solver;
441 references *schedule = &vivifier->schedule;
442 countrefs *countrefs = &vivifier->countrefs;
443 KISSAT_assert (EMPTY_STACK (*schedule));
444 for (all_stack (countref, cr, *countrefs))
445 PUSH_STACK (*schedule, cr.ref);
446 RELEASE_STACK (*countrefs);
447}
448
449static void sort_vivification_candidates (vivifier *vivifier) {
450#ifndef KISSAT_QUIET
451 kissat *solver = vivifier->solver;
452#endif
453 START (vivifysort);
454 if (vivifier->tier) {
456 solver, "sorting %s vivification candidates precisely",
457 vivifier->name);
458 sort_scheduled_candidate_literals (vivifier);
459 sort_vivification_candidates_after_sorting_literals (vivifier);
460 } else {
462 solver,
463 "sorting %s vivification candidates imprecisely "
464 "by first %u literals",
465 vivifier->name, (unsigned) COUNTREF_COUNTS);
466 init_countrefs (vivifier);
467 rank_vivification_candidates (vivifier);
468 copy_countrefs (vivifier);
469 }
470 STOP (vivifysort);
471}
472
473static void vivify_deduce (vivifier *vivifier, clause *candidate,
474 clause *conflict, unsigned implied,
475 clause **subsuming_ptr, bool *redundant_ptr) {
476 kissat *solver = vivifier->solver;
477 LOG ("starting vivification conflict analysis");
478 bool redundant = false;
479 bool subsumes = false;
480
481 KISSAT_assert (solver->level);
482 KISSAT_assert (EMPTY_STACK (solver->clause));
483 KISSAT_assert (EMPTY_STACK (solver->analyzed));
484
485 if (implied != INVALID_LIT) {
486 unsigned not_implied = NOT (implied);
487 LOG ("vivify analyzing %s", LOGLIT (not_implied));
488 assigned *const a = ASSIGNED (not_implied);
489 KISSAT_assert (a->level);
491 a->analyzed = true;
492 PUSH_STACK (solver->analyzed, not_implied);
493 PUSH_STACK (solver->clause, implied);
494 } else {
495 clause *reason = conflict ? conflict : candidate;
496 KISSAT_assert (reason), KISSAT_assert (!reason->garbage);
497 if (reason->redundant)
498 redundant = true;
499 subsumes = (reason != candidate);
500 for (all_literals_in_clause (other, reason)) {
501 KISSAT_assert (VALUE (other) < 0);
502 const value value = kissat_fixed (solver, other);
503 if (value < 0)
504 continue;
505 LOG ("vivify analyzing %s", LOGLIT (other));
507 assigned *const a = ASSIGNED (other);
508 KISSAT_assert (a->level);
510 a->analyzed = true;
511 PUSH_STACK (solver->analyzed, other);
512 if (solver->marks[other] <= 0)
513 subsumes = false;
514 }
515 if (reason != candidate && reason->redundant)
517 if (subsumes) {
518 LOGCLS (candidate, "vivify subsumed");
519 LOGCLS (reason, "vivify subsuming");
520 *subsuming_ptr = reason;
521 return;
522 }
523 }
524
525 const mark *const marks = solver->marks;
526 size_t analyzed = 0;
527 while (analyzed < SIZE_STACK (solver->analyzed)) {
528 const unsigned not_lit = PEEK_STACK (solver->analyzed, analyzed);
529 const unsigned lit = NOT (not_lit);
530 KISSAT_assert (VALUE (lit) > 0);
531 analyzed++;
532 assigned *a = ASSIGNED (lit);
533 KISSAT_assert (a->level);
535 if (a->reason == DECISION_REASON) {
536 LOG ("vivify analyzing decision %s", LOGLIT (not_lit));
537 PUSH_STACK (solver->clause, not_lit);
538 } else if (a->binary) {
539 const unsigned other = a->reason;
540 if (marks[lit] > 0 && marks[other] > 0) {
541 LOGCLS (candidate, "vivify subsumed");
542 LOGBINARY (lit, other, "vivify subsuming"); // Might be jumped!
543 *subsuming_ptr = kissat_binary_conflict (solver, lit, other);
544 return;
545 }
546 KISSAT_assert (VALUE (other) < 0);
547 assigned *b = ASSIGNED (other);
548 KISSAT_assert (b->level);
549 if (b->analyzed)
550 continue;
551 LOGBINARY (lit, other, "vivify analyzing %s reason", LOGLIT (lit));
552 b->analyzed = true;
553 PUSH_STACK (solver->analyzed, other);
554 } else {
555 const reference ref = a->reason;
556 LOGREF (ref, "vivify analyzing %s reason", LOGLIT (lit));
557 clause *reason = kissat_dereference_clause (solver, ref);
558 KISSAT_assert (reason != candidate);
559 if (reason->redundant)
560 redundant = true;
561 subsumes = true;
562 for (all_literals_in_clause (other, reason)) {
563 if (marks[other] <= 0)
564 subsumes = false;
565 if (other == lit)
566 continue;
567 KISSAT_assert (other != not_lit);
568 KISSAT_assert (VALUE (other) < 0);
569 assigned *b = ASSIGNED (other);
570 if (!b->level)
571 continue;
572 if (b->analyzed)
573 continue;
574 b->analyzed = true;
575 PUSH_STACK (solver->analyzed, other);
576 }
577 if (reason->redundant)
579 if (subsumes) {
580 LOGCLS (candidate, "vivify subsumed");
581 LOGCLS (reason, "vivify subsuming");
582 *subsuming_ptr = reason;
583 return;
584 }
585 }
586 }
587
588 LOG ("vivification analysis %s redundant clause",
589 redundant ? "used" : "without");
590 LOGTMP ("vivification analysis");
591
592 *redundant_ptr = redundant;
593}
594
595static void reset_vivify_analyzed (vivifier *vivifier) {
596 kissat *solver = vivifier->solver;
597 LOG ("reset vivification conflict analysis");
598 struct assigned *assigned = solver->assigned;
599 for (all_stack (unsigned, lit, solver->analyzed)) {
600 const unsigned idx = IDX (lit);
601 struct assigned *a = assigned + idx;
602 a->analyzed = false;
603 }
604 CLEAR_STACK (solver->analyzed);
605 CLEAR_STACK (solver->clause);
606}
607
608static bool vivify_shrinkable (kissat *solver, unsigneds *sorted,
609 clause *conflict) {
610 KISSAT_assert (SIZE_STACK (solver->clause) <= SIZE_STACK (*sorted));
611 if (SIZE_STACK (solver->clause) == SIZE_STACK (*sorted))
612 return false;
613 const assigned *const assigned = solver->assigned;
614 const value *const values = solver->values;
615 unsigned count_implied = 0;
616 for (all_stack (unsigned, lit, *sorted)) {
617 value value = values[lit];
618 if (!value) {
619 LOG ("vivification unassigned %s thus shrinking", LOGLIT (lit));
620 return true;
621 }
622 if (value > 0) {
623 LOG ("vivification implied satisfied %s", LOGLIT (lit));
624 if (conflict) {
625 LOG ("at least one implied literal with conflict thus shrinking");
626 return true;
627 }
628 if (count_implied++) {
629 LOG ("at least two implied literals thus shrinking");
630 return true;
631 }
632 } else {
633 KISSAT_assert (value < 0);
634 const unsigned idx = IDX (lit);
635 const struct assigned *const a = assigned + idx;
636 KISSAT_assert (a->level);
637 if (!a->analyzed) {
638 LOG ("vivification non-analyzed %s thus shrinking", LOGLIT (lit));
639 return true;
640 }
641 if (a->reason != DECISION_REASON) {
642 LOG ("vivification implied falsified %s thus shrinking",
643 LOGLIT (lit));
644 return true;
645 }
646 }
647 }
648 LOG ("vivification learned clause not shrinkable");
649 return false;
650}
651
652static void vivify_learn_unit (kissat *solver, clause *c) {
653 LOG ("vivification learns unit clause");
654 KISSAT_assert (SIZE_STACK (solver->clause) == 1);
656 const unsigned unit = PEEK_STACK (solver->clause, 0);
658 solver->iterating = true;
660 KISSAT_assert (!solver->level);
661 clause *conflict = kissat_probing_propagate (solver, 0, true);
662 KISSAT_assert (!conflict || solver->inconsistent);
663 INC (vivify_units);
664 (void) conflict;
665}
666
667static void vivify_learn_binary (kissat *solver, clause *c) {
668 LOG ("vivification learns binary clause");
670 KISSAT_assert (SIZE_STACK (solver->clause) == 2);
671 if (c->redundant)
673 else
676}
677
678static void swap_first_literal_with_best_watch (kissat *solver,
679 unsigned *lits,
680 unsigned size) {
681 KISSAT_assert (size);
682 unsigned *best_ptr = lits;
683 unsigned first = *best_ptr, best = first;
684 signed char value = VALUE (best);
685 unsigned best_level = LEVEL (best);
686 const unsigned *const end = lits + size;
687 for (unsigned *p = lits + 1; value < 0 && p != end; p++) {
688 unsigned lit = *p;
689 const signed char value = VALUE (lit);
690 if (value < 0) {
691 const unsigned level = LEVEL (lit);
692 if (level <= best_level)
693 continue;
694 best_level = level;
695 }
696 best_ptr = p;
697 best = lit;
698 }
699 if (best_ptr == lits)
700 return;
701 LOG ("better watch %s instead of %s", LOGLIT (best), LOGLIT (first));
702 *best_ptr = first;
703 *lits = best;
704}
705
706static void vivify_unwatch_clause (kissat *solver, clause *c) {
707 unsigned *lits = c->lits;
708 const reference ref = kissat_reference_clause (solver, c);
709 kissat_unwatch_blocking (solver, lits[0], ref);
710 kissat_unwatch_blocking (solver, lits[1], ref);
711}
712
713static void vivify_watch_clause (kissat *solver, clause *c) {
714 unsigned size = c->size;
715 unsigned *lits = c->lits;
716 const reference ref = kissat_reference_clause (solver, c);
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);
721}
722
723static void vivify_learn_large (kissat *solver, clause *c,
724 unsigned implied) {
726 LOG ("vivification learns large clause");
727
728 CHECK_AND_ADD_STACK (solver->clause);
729 ADD_STACK_TO_PROOF (solver->clause);
730
733
734 vivify_unwatch_clause (solver, c);
735
736 bool irredundant = !c->redundant;
737
738 if (irredundant) { // TODO this could be made more precise.
739 for (all_literals_in_clause (lit, c))
740 kissat_mark_removed_literal (solver, lit);
741 }
742
743 unsigneds *learned = &solver->clause;
744 const unsigned old_size = c->size;
745 const unsigned new_size = SIZE_STACK (*learned);
746 KISSAT_assert (new_size <= old_size);
747
748 unsigned *lits = c->lits;
749 memcpy (lits, BEGIN_STACK (*learned), new_size * sizeof *lits);
750
751 if (irredundant)
752 for (all_literals_in_clause (lit, c))
753 kissat_mark_added_literal (solver, lit);
754
755 KISSAT_assert (new_size < old_size);
756 if (!c->shrunken) {
757 c->shrunken = true;
758 lits[old_size - 1] = INVALID_LIT;
759 }
760 c->size = new_size;
761 if (!irredundant && c->glue >= new_size)
762 kissat_promote_clause (solver, c, new_size - 1);
763 c->searched = 2;
764
765 if (implied == INVALID_LIT) {
766 LOGCLS (c, "vivified shrunken after conflict");
768 } else {
769 LOGCLS (c, "vivified shrunken after implied");
770 KISSAT_assert (solver->level >= new_size - 1);
771 }
772
773 vivify_watch_clause (solver, c);
774}
775
776static void vivify_learn (kissat *solver, clause *c, unsigned implied) {
777 size_t size = SIZE_STACK (solver->clause);
778 if (size == 1)
779 vivify_learn_unit (solver, c);
780 else if (size == 2)
781 vivify_learn_binary (solver, c);
782 else
783 vivify_learn_large (solver, c, implied);
784}
785
786static void binary_strengthen_after_instantiation (kissat *solver,
787 clause *c,
788 unsigned remove) {
789 LOG ("vivification instantiation yields binary clause");
790 KISSAT_assert (solver->level == 3);
791
792 unsigned first = INVALID_LIT, second = INVALID_LIT;
793 for (all_literals_in_clause (lit, c))
794 if (lit != remove) {
795 KISSAT_assert (VALUE (lit) < 0);
796 if (LEVEL (lit)) {
797 if (first == INVALID_LIT)
798 first = lit;
799 else {
800 KISSAT_assert (second == INVALID_LIT);
801 second = lit;
802 }
803 }
804 }
805 KISSAT_assert (first != INVALID_LIT);
806 KISSAT_assert (second != INVALID_LIT);
807 LOGBINARY (first, second, "vivified strengthened through instantiation");
808 CLEAR_STACK (solver->clause);
809 PUSH_STACK (solver->clause, first);
810 PUSH_STACK (solver->clause, second);
811 if (c->redundant)
813 else
815
818}
819
820static void large_strengthen_after_instantiation (kissat *solver, clause *c,
821 unsigned remove) {
822 LOG ("vivification instantiation yields large clause");
823 KISSAT_assert (solver->level > 3);
824
826 CHECK_SHRINK_CLAUSE (c, remove, INVALID_LIT);
827
828 vivify_unwatch_clause (solver, c);
829
830 bool irredundant = !c->redundant;
831 const unsigned old_size = c->size;
832 KISSAT_assert (old_size > 3);
833 unsigned new_size = 0, *lits = c->lits;
834 for (unsigned i = 0; i != old_size; i++) {
835 const unsigned lit = lits[i];
836 if (lit == remove) {
837 if (irredundant)
838 kissat_mark_removed_literal (solver, lit);
839 } else if (kissat_fixed (solver, lit) >= 0) {
840 lits[new_size++] = lit;
841 if (irredundant)
842 kissat_mark_added_literal (solver, lit);
843 }
844 }
845 KISSAT_assert (2 < new_size);
846 KISSAT_assert (new_size < old_size);
847 if (!c->shrunken) {
848 c->shrunken = true;
849 lits[old_size - 1] = INVALID_LIT;
850 }
851 c->size = new_size;
852 if (!irredundant && c->glue >= new_size)
853 kissat_promote_clause (solver, c, new_size - 1);
854 c->searched = 2;
855 LOGCLS (c, "vivified strengthened through instantiation");
856
858 vivify_watch_clause (solver, c);
859}
860
861static void vivify_strengthen_after_instantiation (kissat *solver,
862 clause *c,
863 unsigned remove) {
864 KISSAT_assert (solver->level >= 3);
865 KISSAT_assert (VALUE (remove) > 0);
866 KISSAT_assert (LEVEL (remove) == solver->level);
867
868 if (solver->level == 3)
869 binary_strengthen_after_instantiation (solver, c, remove);
870 else
871 large_strengthen_after_instantiation (solver, c, remove);
872}
873
874static void vivify_mark_sorted_literals (vivifier *vivifier) {
875 kissat *solver = vivifier->solver;
876 LOG ("marking sorted literals");
877 unsigneds *sorted = &vivifier->sorted;
878 value *marks = solver->marks;
879 for (all_stack (unsigned, lit, *sorted))
880 KISSAT_assert (!marks[lit]), marks[lit] = 1, marks[NOT (lit)] = -1;
881}
882
883static void vivify_unmark_sorted_literals (vivifier *vivifier) {
884 kissat *solver = vivifier->solver;
885 LOG ("unmarking sorted literals");
886 unsigneds *sorted = &vivifier->sorted;
887 value *marks = solver->marks;
888 for (all_stack (unsigned, lit, *sorted))
889 KISSAT_assert (solver->marks[lit] > 0), KISSAT_assert (marks[NOT (lit)] < 0),
890 marks[lit] = marks[NOT (lit)] = 0;
891}
892
893static void reestablish_watch_invariant_for_candidate (kissat *solver,
894 clause *candidate) {
895 if (!solver->level)
896 return;
897 if (candidate->garbage)
898 return;
899 unsigned *lits = candidate->lits;
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;
906 unsigned new_level;
907 if (first_val >= 0 && second_val >= 0)
908 return;
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)
913 return;
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)
919 return;
920 new_level = second_level;
921 } else {
922 KISSAT_assert (first_val < 0), KISSAT_assert (second_val < 0);
923 new_level = MIN (first_level, second_level);
924 }
925 KISSAT_assert (new_level);
926 LOGCLS (candidate, "reestablish watch invariant by backtracking to %u",
927 new_level - 1);
929}
930
931static bool vivify_clause (vivifier *vivifier, clause *candidate) {
932
933 KISSAT_assert (!candidate->garbage);
934
935 kissat *solver = vivifier->solver;
936
937 KISSAT_assert (solver->probing);
938 KISSAT_assert (solver->watching);
939 KISSAT_assert (!solver->inconsistent);
940
941 LOGCLS (candidate, "vivifying candidate");
943 "vivifying unsorted counted candidate");
944
945 unsigneds *sorted = &vivifier->sorted;
946 CLEAR_STACK (*sorted);
947
949 const value value = kissat_fixed (solver, lit);
950 if (value < 0)
951 continue;
952 if (value > 0) {
953 LOGCLS (candidate, "%s satisfied", LOGLIT (lit));
955 return false;
956 }
957 PUSH_STACK (*sorted, lit);
958 }
959
960 KISSAT_assert (!candidate->garbage);
961
962 const unsigned non_false = SIZE_STACK (*sorted);
963
964 KISSAT_assert (1 < non_false);
965 KISSAT_assert (non_false <= candidate->size);
966
967#ifdef LOGGING
968 if (non_false == candidate->size)
969 LOG ("all literals root level unassigned");
970 else
971 LOG ("found %u root level non-falsified literals", non_false);
972#endif
973
974 if (non_false == 2) {
975 LOGCLS (candidate, "skipping actually binary");
976 return false;
977 }
978
979 INC (vivify_checks);
980
981 unsigned unit = INVALID_LIT;
983 const value value = VALUE (lit);
984 if (value < 0)
985 continue;
986 if (!value) {
987 unit = INVALID_LIT;
988 break;
989 }
990 KISSAT_assert (value > 0);
991 if (unit != INVALID_LIT) {
992 unit = INVALID_LIT;
993 break;
994 }
995 unit = lit;
996 }
997 reference cand_ref = kissat_reference_clause (solver, candidate);
998 if (unit != INVALID_LIT) {
999 assigned *a = ASSIGNED (unit);
1000 KISSAT_assert (a->level);
1001 if (a->binary)
1002 unit = INVALID_LIT;
1003 else {
1004 if (a->reason != cand_ref)
1005 unit = INVALID_LIT;
1006 }
1007 }
1008 if (unit == INVALID_LIT)
1009 LOG ("non-reason candidate clause");
1010 else {
1011 LOG ("candidate is the reason of %s", LOGLIT (unit));
1012 const unsigned level = LEVEL (unit);
1013 KISSAT_assert (level > 0);
1014 LOG ("forced to backtrack to level %u", level - 1);
1016 }
1017
1018 KISSAT_assert (EMPTY_STACK (solver->analyzed));
1019 KISSAT_assert (EMPTY_STACK (solver->clause));
1020
1021 unsigned *counts = vivifier->counts;
1022 vivify_sort_stack_by_counts (solver, sorted, counts);
1023
1024#ifdef LOGGING
1025 if (candidate->redundant)
1026 LOGCOUNTEDREFLITS (cand_ref, SIZE_STACK (*sorted), sorted->begin,
1027 counts, "vivifying sorted redundant glue %u",
1028 candidate->glue);
1029 else
1030 LOGCOUNTEDREFLITS (cand_ref, SIZE_STACK (*sorted), sorted->begin,
1031 counts, "vivifying sorted irredundant");
1032#endif
1033
1034 vivify_mark_sorted_literals (vivifier);
1035
1036 unsigned implied = INVALID_LIT;
1037 clause *conflict = 0;
1038 unsigned level = 0;
1039
1040 for (all_stack (unsigned, lit, *sorted)) {
1041 if (level++ < solver->level) {
1042 frame *frame = &FRAME (level);
1043 const unsigned not_lit = NOT (lit);
1044 if (frame->decision == not_lit) {
1045 LOG ("reusing assumption %s", LOGLIT (not_lit));
1046 INC (vivify_reused);
1047 INC (vivify_probes);
1048 KISSAT_assert (VALUE (lit) < 0);
1049 continue;
1050 }
1051
1052 LOG ("forced to backtrack to decision level %u", level - 1);
1054 }
1055
1056 const value value = VALUE (lit);
1057 KISSAT_assert (!value || LEVEL (lit) <= level);
1058
1059 if (value < 0) {
1061 LOG ("literal %s already falsified", LOGLIT (lit));
1062 continue;
1063 }
1064
1065 if (value > 0) {
1067 LOG ("literal %s already initially satisfied", LOGLIT (lit));
1068 implied = lit;
1069 break;
1070 }
1071
1073
1074 LOG ("literal %s unassigned", LOGLIT (lit));
1075 const unsigned not_lit = NOT (lit);
1076 INC (vivify_probes);
1077
1078 kissat_internal_assume (solver, not_lit);
1079 KISSAT_assert (solver->level >= 1);
1080
1081 const unsigned *p = solver->propagate;
1082 conflict = kissat_probing_propagate (solver, candidate, true);
1083 if (conflict)
1084 break;
1085
1086 const unsigned *end = END_ARRAY (solver->trail);
1087 const signed char *const marks = solver->marks;
1088 while (p != end) {
1089 const unsigned other = *p++;
1090 const signed char mark = marks[other];
1091 if (mark > 0) {
1092 LOG ("literal %s already implied satisfied", LOGLIT (other));
1093 implied = other;
1094 goto EXIT_ASSUMPTION_LOOP;
1095 }
1096 }
1097 }
1098EXIT_ASSUMPTION_LOOP:;
1099
1100#ifdef LOGGING
1101 if (!conflict && implied == INVALID_LIT)
1102 LOG ("vivification assumptions propagate without conflict nor "
1103 "producing an implied literal");
1104#endif
1105 KISSAT_assert (!conflict || implied == INVALID_LIT);
1106
1107 if (implied != INVALID_LIT) {
1108 unsigned better_implied = INVALID_LIT;
1109 unsigned better_implied_trail = INVALID_TRAIL;
1110 for (all_stack (unsigned, lit, *sorted)) {
1111 if (VALUE (lit) <= 0)
1112 continue;
1113 unsigned lit_trail = TRAIL (lit);
1114 if (lit_trail > better_implied_trail)
1115 continue;
1116 better_implied_trail = lit_trail;
1117 better_implied = lit;
1118 }
1119 if (better_implied != implied) {
1120 LOG ("better implied satisfied literal %s at level %u",
1121 LOGLIT (better_implied), LEVEL (better_implied));
1122 implied = better_implied;
1123 }
1124 }
1125
1126 unsigned level_after_assumptions = solver->level;
1127 KISSAT_assert (level_after_assumptions);
1128
1129 clause *subsuming = 0;
1130 bool redundant = false;
1131 vivify_deduce (vivifier, candidate, conflict, implied, &subsuming,
1132 &redundant);
1133
1134 vivify_unmark_sorted_literals (vivifier);
1135
1136 bool res;
1137
1138 if (subsuming) {
1139 KISSAT_assert (!subsuming->garbage);
1140 if (candidate->redundant) {
1141 LOGCLS (candidate, "vivification subsumed");
1143 if (subsuming->redundant && candidate->glue < subsuming->glue) {
1144 LOG ("vivify candidate with smaller glue than subsuming clause");
1145 kissat_promote_clause (solver, subsuming, candidate->glue);
1146 }
1147 INC (vivified_subred);
1148 INC (vivified_subsumed);
1149 res = true;
1150 } else if (!subsuming->redundant) {
1151 KISSAT_assert (!candidate->redundant);
1152 LOGCLS (candidate, "vivification subsumed");
1154 INC (vivified_subirr);
1155 INC (vivified_subsumed);
1156 res = true;
1157 } else {
1158 KISSAT_assert (!candidate->redundant);
1159 KISSAT_assert (subsuming->redundant);
1160 LOGCLS (candidate, "vivification subsumed");
1162 subsuming->redundant = false;
1163 KISSAT_assert (solver->statistics_.clauses_redundant);
1164 solver->statistics_.clauses_redundant--;
1165 KISSAT_assert (solver->statistics_.clauses_irredundant < UINT64_MAX);
1166 solver->statistics_.clauses_irredundant++;
1167 INC (vivified_promoted);
1168 LOGCLS (subsuming, "vivification promoted from redundant to");
1170 kissat_mark_added_literals (solver, subsuming->size, subsuming->lits);
1171 INC (vivified_subirr);
1172 INC (vivified_subsumed);
1173 res = true;
1174 }
1175 } else if (vivify_shrinkable (solver, sorted, conflict)) {
1176 vivify_learn (solver, candidate, implied);
1177 INC (vivified_shrunken);
1178 if (candidate->redundant)
1179 INC (vivified_shrunkred);
1180 else
1181 INC (vivified_shrunkirr);
1182 res = true;
1183 } else if (implied != INVALID_LIT && candidate->redundant) {
1184 LOGCLS (candidate, "vivification implied");
1186 INC (vivified_implied);
1187 res = true;
1188 } else if ((conflict || implied != INVALID_LIT) &&
1189 !candidate->redundant && !redundant) {
1190 LOGCLS (candidate, "vivification asymmetric tautology");
1192 INC (vivified_asym);
1193 res = true;
1194 } else if (implied != INVALID_LIT) {
1196 "no vivification instantiation with implied literal %s",
1197 LOGLIT (implied));
1198 KISSAT_assert (!candidate->redundant);
1199 KISSAT_assert (redundant);
1200 res = false;
1201 } else {
1202 KISSAT_assert (solver->level > 2);
1203 KISSAT_assert (solver->level == SIZE_STACK (*sorted));
1204 unsigned lit = TOP_STACK (*sorted);
1205 KISSAT_assert (VALUE (lit) < 0);
1206 KISSAT_assert (LEVEL (lit) == solver->level);
1207 LOG ("trying vivification instantiation of %s#%u respectively %s#%u",
1208 LOGLIT (lit), counts[lit], LOGLIT (NOT (lit)), counts[NOT (lit)]);
1210 conflict = 0;
1211 KISSAT_assert (!VALUE (lit));
1213 LOGCLS (candidate, "vivification instantiation candidate");
1214 conflict = kissat_probing_propagate (solver, candidate, true);
1215 if (conflict) {
1216 LOG ("vivification instantiation succeeded");
1217 vivify_strengthen_after_instantiation (solver, candidate, lit);
1218 INC (vivified_instantiated);
1219 if (candidate->redundant)
1220 INC (vivified_instred);
1221 else
1222 INC (vivified_instirr);
1223 res = true;
1224 } else {
1225 LOG ("vivification instantiation failed");
1227 res = false;
1228 }
1229 }
1230
1231 reset_vivify_analyzed (vivifier);
1232 if (conflict && solver->level == level_after_assumptions) {
1233 LOG ("forcing backtracking at least one level after conflict");
1235 }
1236 reestablish_watch_invariant_for_candidate (solver, candidate);
1237
1238 if (res) {
1239 INC (vivified);
1240 switch (vivifier->tier) {
1241 case 1:
1242 INC (vivified_tier1);
1243 break;
1244 case 2:
1245 INC (vivified_tier2);
1246 break;
1247 case 3:
1248 INC (vivified_tier3);
1249 break;
1250 default:
1251 KISSAT_assert (vivifier->tier == 0);
1252 INC (vivified_irredundant);
1253 break;
1254 }
1255 }
1256
1257 LOG ("vivification %s", res ? "succeeded" : "failed");
1258 return res;
1259}
1260
1261static void vivify_round (vivifier *vivifier, uint64_t limit) {
1262 int tier = vivifier->tier;
1263 kissat *solver = vivifier->solver;
1264
1265 if (tier && !REDUNDANT_CLAUSES)
1266 return;
1267
1268 KISSAT_assert (0 <= tier && tier <= 3);
1269 KISSAT_assert (solver->watching);
1270 KISSAT_assert (solver->probing);
1271
1273
1274 schedule_vivification_candidates (vivifier);
1275 if (GET_OPTION (vivifysort)) {
1276 if (tier || IRREDUNDANT_CLAUSES / 10 <= REDUNDANT_CLAUSES)
1277 sort_vivification_candidates (vivifier);
1278 else
1280 solver, "not sorting %s vivification candidates", vivifier->name);
1281 }
1282
1284#ifndef KISSAT_QUIET
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);
1291 const size_t total = tier ? REDUNDANT_CLAUSES : IRREDUNDANT_CLAUSES;
1292 const size_t scheduled = SIZE_STACK (vivifier->schedule);
1293 kissat_phase (solver, vivifier->mode, GET (vivifications),
1294 "scheduled %zu clauses %.0f%% of %zu", scheduled,
1295 kissat_percent (scheduled, total), total);
1296#endif
1297 KISSAT_assert (!vivifier->vivified);
1298 KISSAT_assert (!vivifier->tried);
1299 while (!EMPTY_STACK (vivifier->schedule)) {
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);
1306 break;
1307 }
1309 break;
1310 const reference ref = POP_STACK (vivifier->schedule);
1311 clause *candidate = kissat_dereference_clause (solver, ref);
1312 KISSAT_assert (!candidate->garbage);
1313 vivifier->tried++;
1314 if (vivify_clause (vivifier, candidate))
1315 vivifier->vivified++;
1316 if (solver->inconsistent)
1317 break;
1318 candidate->vivify = false;
1319 }
1320 if (solver->level)
1322#ifndef KISSAT_QUIET
1323 kissat_phase (solver, vivifier->mode, GET (vivifications),
1324 "vivified %zu clauses %.0f%% out of %zu tried",
1325 vivifier->vivified,
1326 kissat_percent (vivifier->vivified, vivifier->tried),
1327 vivifier->tried);
1328 if (!solver->inconsistent) {
1329 size_t remain = SIZE_STACK (vivifier->schedule);
1330 if (remain) {
1331 kissat_phase (solver, vivifier->mode, GET (vivifications),
1332 "%zu clauses remain %.0f%% out of %zu scheduled",
1333 remain, kissat_percent (remain, scheduled), scheduled);
1334
1335 ward *const arena = BEGIN_STACK (solver->arena);
1336 size_t prioritized = 0;
1337 while (!EMPTY_STACK (vivifier->schedule)) {
1338 const reference ref = POP_STACK (vivifier->schedule);
1339 clause *c = (clause *) (arena + ref);
1340 if (c->vivify)
1341 prioritized++;
1342 }
1343 if (!prioritized)
1344 kissat_phase (solver, vivifier->mode, GET (vivifications),
1345 "no remaining prioritized clauses");
1346 else
1347 kissat_phase (solver, vivifier->mode, GET (vivifications),
1348 "keeping all %zu remaining clauses "
1349 "prioritized %.0f%%",
1350 prioritized, kissat_percent (prioritized, remain));
1351 } else
1352 kissat_phase (solver, vivifier->mode, GET (vivifications),
1353 "no untried clauses remain");
1354 }
1355#endif
1356 REPORT (!vivifier->vivified, vivifier->tag);
1357}
1358
1359static void vivify_tier1 (vivifier *vivifier, uint64_t limit) {
1360#ifndef KISSAT_QUIET
1361 kissat *solver = vivifier->solver;
1362#endif
1363 START (vivify1);
1364 set_vivifier_mode (vivifier, 1);
1365 vivify_round (vivifier, limit);
1366 STOP (vivify1);
1367}
1368
1369static void vivify_tier2 (vivifier *vivifier, uint64_t limit) {
1370#ifndef KISSAT_QUIET
1371 kissat *solver = vivifier->solver;
1372#endif
1373 START (vivify2);
1374 clear_vivifier (vivifier);
1375 set_vivifier_mode (vivifier, 2);
1376 vivify_round (vivifier, limit);
1377 STOP (vivify2);
1378}
1379
1380static void vivify_tier3 (vivifier *vivifier, uint64_t limit) {
1381#ifndef KISSAT_QUIET
1382 kissat *solver = vivifier->solver;
1383#endif
1384 START (vivify3);
1385 clear_vivifier (vivifier);
1386 set_vivifier_mode (vivifier, 3);
1387 vivify_round (vivifier, limit);
1388 STOP (vivify3);
1389}
1390
1391static void vivify_irredundant (vivifier *vivifier, uint64_t limit) {
1392#ifndef KISSAT_QUIET
1393 kissat *solver = vivifier->solver;
1394#endif
1395 START (vivify0);
1396 clear_vivifier (vivifier);
1397 set_vivifier_mode (vivifier, 0);
1398 vivify_round (vivifier, limit);
1399 STOP (vivify0);
1400}
1401
1403 if (solver->inconsistent)
1404 return;
1405 KISSAT_assert (!solver->level);
1406 KISSAT_assert (solver->probing);
1407 KISSAT_assert (solver->watching);
1408 if (!GET_OPTION (vivify))
1409 return;
1411 return;
1412 double irr_budget = DELAYING (vivifyirr) ? 0 : GET_OPTION (vivifyirr);
1413 double tier1_budget = GET_OPTION (vivifytier1);
1414 double tier2_budget = GET_OPTION (vivifytier2);
1415 double tier3_buget = GET_OPTION (vivifytier3);
1416 if (!REDUNDANT_CLAUSES)
1417 tier1_budget = tier2_budget = tier3_buget = 0;
1418 double sum = irr_budget + tier1_budget + tier2_budget + tier3_buget;
1419 if (!sum)
1420 return;
1421
1422 START (vivify);
1423 INC (vivifications);
1424#if !defined(KISSAT_NDEBUG) || defined(METRICS)
1425 KISSAT_assert (!solver->vivifying);
1426 solver->vivifying = true;
1427#endif
1428
1429 SET_EFFORT_LIMIT (limit, vivify, probing_ticks);
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");
1438 }
1439
1440 {
1442 init_vivifier (solver, &vivifier);
1443 if (tier1_budget) {
1444 limit += (total * tier1_budget) / sum;
1445 vivify_tier1 (&vivifier, limit);
1446 }
1447 if (tier2_budget && !solver->inconsistent &&
1449 limit += (total * tier2_budget) / sum;
1450 vivify_tier2 (&vivifier, limit);
1451 }
1452 if (tier3_buget && !solver->inconsistent &&
1454 limit += (total * tier3_buget) / sum;
1455 vivify_tier3 (&vivifier, limit);
1456 }
1457 if (irr_budget && !solver->inconsistent &&
1459 limit += (total * irr_budget) / sum;
1460 vivify_irredundant (&vivifier, limit);
1461 if (kissat_average (vivifier.vivified, vivifier.tried) < 0.01)
1462 BUMP_DELAY (vivifyirr);
1463 else
1464 REDUCE_DELAY (vivifyirr);
1465 }
1466 release_vivifier (&vivifier);
1467 }
1468
1469#ifndef KISSAT_QUIET
1470 if (solver->statistics_.probing_ticks < limit) {
1471 uint64_t delta = limit - solver->statistics_.probing_ticks;
1472 kissat_phase (solver, "vivify-limit", GET (vivifications),
1473 "has %" PRIu64 " ticks left %.2f%%", delta,
1474 kissat_percent (delta, total));
1475 } else {
1476 uint64_t delta = solver->statistics_.probing_ticks - limit;
1477 kissat_phase (solver, "vivify-limit", GET (vivifications),
1478 "exceeded by %" PRIu64 " ticks %.2f%%", delta,
1479 kissat_percent (delta, total));
1480 }
1481#endif
1482#if !defined(KISSAT_NDEBUG) || defined(METRICS)
1483 KISSAT_assert (solver->vivifying);
1484 solver->vivifying = false;
1485#endif
1486 STOP (vivify);
1487}
1488
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void * kissat_calloc(kissat *solver, size_t n, size_t size)
Definition allocate.c:97
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
Definition allocate.c:114
ABC_NAMESPACE_HEADER_START typedef word ward
Definition arena.h:12
#define END_ARRAY
Definition array.h:51
void kissat_learned_unit(kissat *solver, unsigned lit)
Definition assign.c:18
#define DECISION_REASON
Definition assign.h:9
#define ASSIGNED(LIT)
Definition assign.h:31
#define INVALID_TRAIL
Definition assign.h:13
#define TRAIL(LIT)
Definition assign.h:35
#define LEVEL(LIT)
Definition assign.h:34
#define MAX(a, b)
Definition avl.h:23
void kissat_backtrack_without_updating_phases(kissat *solver, unsigned new_level)
Definition backtrack.c:74
#define BEGIN_STACK(S)
Definition stack.h:46
#define POP_STACK(S)
Definition stack.h:37
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define RELEASE_STACK(S)
Definition stack.h:71
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define PEEK_STACK(S, N)
Definition stack.h:29
#define TOP_STACK(S)
Definition stack.h:27
#define INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define INVALID_LIT
#define INC(NAME)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define REMOVE_CHECKER_CLAUSE(...)
Definition check.h:167
#define CHECK_AND_ADD_STACK(...)
Definition check.h:152
#define CHECK_SHRINK_CLAUSE(...)
Definition check.h:158
reference kissat_new_redundant_clause(kissat *solver, unsigned glue)
Definition clause.c:146
reference kissat_new_irredundant_clause(kissat *solver)
Definition clause.c:140
void kissat_mark_clause_as_garbage(kissat *solver, clause *c)
Definition clause.c:164
void kissat_new_binary_clause(kissat *solver, unsigned first, unsigned second)
Definition clause.c:122
void kissat_update_last_irredundant(kissat *solver, clause *irredundant)
Definition collect.c:200
void kissat_internal_assume(kissat *solver, unsigned lit)
Definition decide.c:237
bool kissat_recompute_and_promote(kissat *solver, clause *c)
Definition deduce.c:31
pcover irredundant()
Cube * p
Definition exorList.c:222
void kissat_mark_added_literals(kissat *solver, unsigned size, unsigned *lits)
Definition flags.c:113
#define FRAME(LEVEL)
Definition frames.h:33
#define TIER1
Definition internal.h:258
#define all_clauses(C)
Definition internal.h:279
#define TIER2
Definition internal.h:259
#define LITS
Definition internal.h:251
#define BUMP_DELAY(NAME)
Definition kimits.h:183
#define REDUCE_DELAY(NAME)
Definition kimits.h:185
#define DELAYING(NAME)
Definition kimits.h:181
#define BEGIN_LITS(C)
Definition clause.h:44
#define all_literals_in_clause(LIT, C)
Definition clause.h:47
#define END_LITS(C)
Definition clause.h:45
#define KISSAT_assert(ignore)
Definition global.h:13
#define SORT_STACK(TYPE, S, LESS)
Definition sort.h:148
#define SORT(TYPE, N, A, LESS)
Definition sort.h:135
#define solver
Definition kitten.c:211
#define SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
Definition limit.hpp:131
#define LOGREF(...)
Definition logging.h:433
#define LOGBINARY(...)
Definition logging.h:442
#define LOGCLS(...)
Definition logging.h:415
#define LOGCOUNTEDREFLITS(...)
Definition logging.h:382
#define LOGTMP(...)
Definition logging.h:463
#define LOGCOUNTEDCLS(...)
Definition logging.h:424
#define LOGLIT(...)
Definition logging.hpp:99
char * name
Definition main.h:24
unsigned long long size
Definition giaNewBdd.h:39
unsigned short ref
Definition giaNewBdd.h:38
#define GET_OPTION(N)
Definition options.h:295
#define kissat_extremely_verbose(...)
Definition print.h:53
#define kissat_very_verbose(...)
Definition print.h:52
#define kissat_phase(...)
Definition print.h:48
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
ABC_NAMESPACE_IMPL_START void kissat_promote_clause(kissat *solver, clause *c, unsigned new_glue)
Definition promote.c:7
#define SHRINK_CLAUSE_IN_PROOF(...)
Definition proof.h:145
#define DELETE_CLAUSE_FROM_PROOF(...)
Definition proof.h:155
#define ADD_STACK_TO_PROOF(...)
Definition proof.h:138
clause * kissat_probing_propagate(kissat *solver, clause *ignore, bool flush)
Definition proprobe.c:37
#define RADIX_STACK(VTYPE, RTYPE, S, RANK)
Definition rank.h:136
ABC_NAMESPACE_HEADER_START typedef unsigned reference
Definition reference.h:9
#define REPORT(...)
Definition report.h:10
int lit
Definition satVec.h:130
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
#define IRREDUNDANT_CLAUSES
Definition statistics.h:337
#define GET(NAME)
Definition statistics.h:416
#define REDUNDANT_CLAUSES
Definition statistics.h:339
bool binary
Definition assign.h:23
bool analyzed
Definition assign.h:22
unsigned reason
Definition assign.h:28
unsigned level
Definition assign.h:19
bool vivify
Definition clause.h:32
unsigned glue
Definition clause.h:23
unsigned lits[3]
Definition clause.h:39
bool redundant
Definition clause.h:28
unsigned searched
Definition clause.h:36
unsigned size
Definition clause.h:37
bool shrunken
Definition clause.h:29
bool garbage
Definition clause.h:25
unsigned size
Definition vivify.c:144
unsigned count[COUNTREF_COUNTS]
Definition vivify.c:145
unsigned vivify
Definition vivify.c:143
reference ref
Definition vivify.c:146
Definition frames.h:15
unsigned decision
Definition frames.h:17
Definition mode.h:11
#define vivify_terminated_3
Definition terminate.h:83
#define TERMINATED(BIT)
Definition terminate.h:42
#define vivify_terminated_5
Definition terminate.h:85
#define vivify_terminated_2
Definition terminate.h:82
#define vivify_terminated_1
Definition terminate.h:81
#define vivify_terminated_4
Definition terminate.h:84
char * memcpy()
char * memset()
#define MIN(a, b)
Definition util_old.h:256
signed char mark
Definition value.h:8
#define VALUE(LIT)
Definition value.h:10
#define MORE_OCCURRENCES(A, B)
Definition vivify.c:32
#define MAX_COUNTREF_SIZE
Definition vivify.c:140
#define RANK_COUNTREF_BY_VIVIFY(CR)
Definition vivify.c:425
struct vivifier vivifier
Definition vivify.c:167
#define COUNTREF_COUNTS
Definition vivify.c:138
#define WORSE_CANDIDATE(A, B)
Definition vivify.c:354
#define RANK_COUNTREF_BY_INVERSE_SIZE(CR)
Definition vivify.c:424
void kissat_vivify(kissat *solver)
Definition vivify.c:1402
#define LD_MAX_COUNTREF_SIZE
Definition vivify.c:139
#define RANK_COUNTREF_BY_COUNT(CR)
Definition vivify.c:426
#define COUNTREF_COUNTS
Definition vivify.hpp:20
void kissat_watch_large_clauses(kissat *solver)
Definition watch.c:145
void kissat_flush_large_watches(kissat *solver)
Definition watch.c:112