ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
sweep.c
Go to the documentation of this file.
1#include "sweep.h"
2#include "dense.h"
3#include "inline.h"
4#include "kitten.h"
5#include "logging.h"
6#include "print.h"
7#include "promote.h"
8#include "propdense.h"
9#include "proprobe.h"
10#include "random.h"
11#include "rank.h"
12#include "report.h"
13#include "terminate.h"
14
15#include <inttypes.h>
16#include <string.h>
17
19
20struct sweeper {
22 unsigned *depths;
23 unsigned *reprs;
24 unsigned *next, *prev;
25 unsigned first, last;
26 unsigned encoded;
27 unsigned save;
28 unsigneds vars;
29 references refs;
30 unsigneds clause;
31 unsigneds backbone;
32 unsigneds partition;
33 unsigneds core[2];
34 struct {
35 uint64_t ticks;
36 unsigned clauses, depth, vars;
38};
39
40typedef struct sweeper sweeper;
41
42static int sweep_solve (sweeper *sweeper) {
44 kitten *kitten = solver->kitten;
46 INC (sweep_solved);
47 int res = kitten_solve (kitten);
48 if (res == 10)
49 INC (sweep_sat);
50 if (res == 20)
51 INC (sweep_unsat);
52 return res;
53}
54
55static void set_kitten_ticks_limit (sweeper *sweeper) {
56 uint64_t remaining = 0;
58 if (solver->statistics_.kitten_ticks < sweeper->limit.ticks)
59 remaining = sweeper->limit.ticks - solver->statistics_.kitten_ticks;
60 LOG ("'kitten_ticks' remaining %" PRIu64, remaining);
61 kitten_set_ticks_limit (solver->kitten, remaining);
62}
63
64static bool kitten_ticks_limit_hit (sweeper *sweeper, const char *when) {
66 if (solver->statistics_.kitten_ticks >= sweeper->limit.ticks) {
67 LOG ("'kitten_ticks' limit of %" PRIu64 " ticks hit after %" PRIu64
68 " ticks during %s",
69 sweeper->limit.ticks, solver->statistics_.kitten_ticks, when);
70 return true;
71 }
72#ifndef LOGGING
73 (void) when;
74#endif
75 return false;
76}
77
78static void init_sweeper (kissat *solver, sweeper *sweeper) {
80 sweeper->encoded = 0;
81 CALLOC (unsigned, sweeper->depths, VARS);
82 NALLOC (unsigned, sweeper->reprs, LITS);
83 for (all_literals (lit))
84 sweeper->reprs[lit] = lit;
85 NALLOC (unsigned, sweeper->prev, VARS);
86 memset (sweeper->prev, 0xff, VARS * sizeof *sweeper->prev);
87 NALLOC (unsigned, sweeper->next, VARS);
88 memset (sweeper->next, 0xff, VARS * sizeof *sweeper->next);
89#ifndef KISSAT_NDEBUG
90 for (all_variables (idx))
92 for (all_variables (idx))
94#endif
101 INIT_STACK (sweeper->core[0]);
102 INIT_STACK (sweeper->core[1]);
103 KISSAT_assert (!solver->kitten);
104 solver->kitten = kitten_embedded (solver);
108
109 unsigned completed = solver->statistics_.sweep_completed;
110 const unsigned max_completed = 32;
111 if (completed > max_completed)
112 completed = max_completed;
113
114 uint64_t vars_limit = GET_OPTION (sweepvars);
115 vars_limit <<= completed;
116 const unsigned max_vars_limit = GET_OPTION (sweepmaxvars);
117 if (vars_limit > max_vars_limit)
118 vars_limit = max_vars_limit;
119 sweeper->limit.vars = vars_limit;
120 kissat_extremely_verbose (solver, "sweeper variable limit %u",
122
123 uint64_t depth_limit = solver->statistics_.sweep_completed;
124 depth_limit += GET_OPTION (sweepdepth);
125 const unsigned max_depth = GET_OPTION (sweepmaxdepth);
126 if (depth_limit > max_depth)
127 depth_limit = max_depth;
128 sweeper->limit.depth = depth_limit;
129 kissat_extremely_verbose (solver, "sweeper depth limit %u",
131
132 uint64_t clause_limit = GET_OPTION (sweepclauses);
133 clause_limit <<= completed;
134 const unsigned max_clause_limit = GET_OPTION (sweepmaxclauses);
135 if (clause_limit > max_clause_limit)
136 clause_limit = max_clause_limit;
137 sweeper->limit.clauses = clause_limit;
138 kissat_extremely_verbose (solver, "sweeper clause limit %u",
140
141 if (GET_OPTION (sweepcomplete)) {
142 sweeper->limit.ticks = UINT64_MAX;
143 kissat_extremely_verbose (solver, "unlimited sweeper ticks limit");
144 } else {
145 SET_EFFORT_LIMIT (ticks_limit, sweep, kitten_ticks);
146 sweeper->limit.ticks = ticks_limit;
147 }
148 set_kitten_ticks_limit (sweeper);
149}
150
151static unsigned release_sweeper (sweeper *sweeper) {
153
154 unsigned merged = 0;
155 for (all_variables (idx)) {
156 if (!ACTIVE (idx))
157 continue;
158 const unsigned lit = LIT (idx);
159 if (sweeper->reprs[lit] != lit)
160 merged++;
161 }
173 kitten_release (solver->kitten);
174 solver->kitten = 0;
176 return merged;
177}
178
179static void clear_sweeper (sweeper *sweeper) {
181 LOG ("clearing sweeping environment");
182 kitten_clear (solver->kitten);
184 for (all_stack (unsigned, idx, sweeper->vars)) {
186 sweeper->depths[idx] = 0;
187 }
189 for (all_stack (reference, ref, sweeper->refs)) {
190 clause *c = kissat_dereference_clause (solver, ref);
191 KISSAT_assert (c->swept);
192 c->swept = false;
193 }
197 sweeper->encoded = 0;
198 set_kitten_ticks_limit (sweeper);
199}
200
201static unsigned sweep_repr (sweeper *sweeper, unsigned lit) {
202 unsigned res;
203 {
204 unsigned prev = lit;
205 while ((res = sweeper->reprs[prev]) != prev)
206 prev = res;
207 }
208 if (res == lit)
209 return res;
210#if defined(LOGGING) || !defined(KISSAT_NDEBUG)
212#endif
213 LOG ("sweeping repr[%s] = %s", LOGLIT (lit), LOGLIT (res));
214 {
215 const unsigned not_res = NOT (res);
216 unsigned next, prev = lit;
217 ;
218 while ((next = sweeper->reprs[prev]) != res) {
219 const unsigned not_prev = NOT (prev);
220 sweeper->reprs[not_prev] = not_res;
221 sweeper->reprs[prev] = res;
222 prev = next;
223 }
224 KISSAT_assert (sweeper->reprs[NOT (prev)] == not_res);
225 }
226 return res;
227}
228
229static void add_literal_to_environment (sweeper *sweeper, unsigned depth,
230 unsigned lit) {
231 const unsigned repr = sweep_repr (sweeper, lit);
232 if (repr != lit)
233 return;
235 const unsigned idx = IDX (lit);
236 if (sweeper->depths[idx])
237 return;
238 KISSAT_assert (depth < UINT_MAX);
239 sweeper->depths[idx] = depth + 1;
240 PUSH_STACK (sweeper->vars, idx);
241 LOG ("sweeping[%u] adding literal %s", depth, LOGLIT (lit));
242}
243
244static void sweep_clause (sweeper *sweeper, unsigned depth) {
247 for (all_stack (unsigned, lit, sweeper->clause))
248 add_literal_to_environment (sweeper, depth, lit);
252 sweeper->encoded++;
253}
254
255static void sweep_binary (sweeper *sweeper, unsigned depth, unsigned lit,
256 unsigned other) {
257 if (sweep_repr (sweeper, lit) != lit)
258 return;
259 if (sweep_repr (sweeper, other) != other)
260 return;
262 LOGBINARY (lit, other, "sweeping[%u]", depth);
263 value *values = solver->values;
264 KISSAT_assert (!values[lit]);
265 const value other_value = values[other];
266 if (other_value > 0) {
267 LOGBINARY (lit, other, "skipping satisfied");
268 return;
269 }
270 const unsigned *depths = sweeper->depths;
271 const unsigned other_idx = IDX (other);
272 const unsigned other_depth = depths[other_idx];
273 const unsigned lit_idx = IDX (lit);
274 const unsigned lit_depth = depths[lit_idx];
275 if (other_depth && other_depth < lit_depth) {
276 LOGBINARY (lit, other, "skipping depth %u copied", other_depth);
277 return;
278 }
279 KISSAT_assert (!other_value);
282 PUSH_STACK (sweeper->clause, other);
283 sweep_clause (sweeper, depth);
284}
285
286static void sweep_reference (sweeper *sweeper, unsigned depth,
287 reference ref) {
290 clause *c = kissat_dereference_clause (solver, ref);
291 if (c->swept)
292 return;
293 if (c->garbage)
294 return;
295 LOGCLS (c, "sweeping[%u]", depth);
296 value *values = solver->values;
297 for (all_literals_in_clause (lit, c)) {
298 const value value = values[lit];
299 if (value > 0) {
302 return;
303 }
304 if (value < 0)
305 continue;
307 }
308 PUSH_STACK (sweeper->refs, ref);
309 c->swept = true;
310 sweep_clause (sweeper, depth);
311}
312
313static void save_core_clause (void *state, bool learned, size_t size,
314 const unsigned *lits) {
315 sweeper *sweeper = (struct sweeper*)state;
317 if (solver->inconsistent)
318 return;
319 const value *const values = solver->values;
320 unsigneds *core = sweeper->core + sweeper->save;
321 size_t saved = SIZE_STACK (*core);
322 const unsigned *end = lits + size;
323 unsigned non_false = 0;
324 for (const unsigned *p = lits; p != end; p++) {
325 const unsigned lit = *p;
326 const value value = values[lit];
327 if (value > 0) {
328 LOGLITS (size, lits, "extracted %s satisfied lemma", LOGLIT (lit));
329 RESIZE_STACK (*core, saved);
330 return;
331 }
332 PUSH_STACK (*core, lit);
333 if (value < 0)
334 continue;
335 if (!learned && ++non_false > 1) {
336 LOGLITS (size, lits, "ignoring extracted original clause");
337 RESIZE_STACK (*core, saved);
338 return;
339 }
340 }
341#ifdef LOGGING
342 unsigned *saved_lits = BEGIN_STACK (*core) + saved;
343 size_t saved_size = SIZE_STACK (*core) - saved;
344 LOGLITS (saved_size, saved_lits, "saved core[%u]", sweeper->save);
345#endif
347}
348
349static void add_core (sweeper *sweeper, unsigned core_idx) {
351 if (solver->inconsistent)
352 return;
353 LOG ("check and add extracted core[%u] lemmas to proof", core_idx);
354 KISSAT_assert (core_idx == 0 || core_idx == 1);
355 unsigneds *core = sweeper->core + core_idx;
356 const value *const values = solver->values;
357
358 unsigned *q = BEGIN_STACK (*core);
359 const unsigned *const end_core = END_STACK (*core), *p = q;
360
361 while (p != end_core) {
362 const unsigned *c = p;
363 while (*p != INVALID_LIT)
364 p++;
365#ifdef LOGGING
366 size_t old_size = p - c;
367 LOGLITS (old_size, c, "simplifying extracted core[%u] lemma", core_idx);
368#endif
369 bool satisfied = false;
370 unsigned unit = INVALID_LIT;
371
372 unsigned *d = q;
373
374 for (const unsigned *l = c; !satisfied && l != p; l++) {
375 const unsigned lit = *l;
376 const value value = values[lit];
377 if (value > 0) {
378 satisfied = true;
379 break;
380 }
381 if (!value)
382 unit = *q++ = lit;
383 }
384
385 size_t new_size = q - d;
386 p++;
387
388 if (satisfied) {
389 q = d;
390 LOG ("not adding satisfied clause");
391 continue;
392 }
393
394 if (!new_size) {
395 LOG ("sweeping produced empty clause");
398 solver->inconsistent = true;
399 CLEAR_STACK (*core);
400 return;
401 }
402
403 if (new_size == 1) {
404 q = d;
405 KISSAT_assert (unit != INVALID_LIT);
406 LOG ("sweeping produced unit %s", LOGLIT (unit));
407 CHECK_AND_ADD_UNIT (unit);
408 ADD_UNIT_TO_PROOF (unit);
409 kissat_assign_unit (solver, unit, "sweeping backbone reason");
410 INC (sweep_units);
411 continue;
412 }
413
414 *q++ = INVALID_LIT;
415
416 KISSAT_assert (new_size > 1);
417 LOGLITS (new_size, d, "adding extracted core[%u] lemma", core_idx);
418 CHECK_AND_ADD_LITS (new_size, d);
419 ADD_LITS_TO_PROOF (new_size, d);
420 }
422#ifndef LOGGING
423 (void) core_idx;
424#endif
425}
426
427static void save_core (sweeper *sweeper, unsigned core) {
429 LOG ("saving extracted core[%u] lemmas", core);
430 KISSAT_assert (core == 0 || core == 1);
432 sweeper->save = core;
434 kitten_traverse_core_clauses (solver->kitten, sweeper, save_core_clause);
435}
436
437static void clear_core (sweeper *sweeper, unsigned core_idx) {
439 if (solver->inconsistent)
440 return;
441#if defined(LOGGING) || !defined(KISSAT_NDEBUG) || !defined(KISSAT_NPROOFS)
442 KISSAT_assert (core_idx == 0 || core_idx == 1);
443 LOG ("clearing core[%u] lemmas", core_idx);
444#endif
445 unsigneds *core = sweeper->core + core_idx;
446#ifdef CHECKING_OR_PROVING
447 LOG ("deleting sub-solver core clauses");
448 const unsigned *const end = END_STACK (*core);
449 const unsigned *c = BEGIN_STACK (*core);
450 for (const unsigned *p = c; c != end; c = ++p) {
451 while (*p != INVALID_LIT)
452 p++;
453 const size_t size = p - c;
454 KISSAT_assert (size > 1);
455 REMOVE_CHECKER_LITS (size, c);
456 DELETE_LITS_FROM_PROOF (size, c);
457 }
458#endif
459 CLEAR_STACK (*core);
460}
461
462static void save_add_clear_core (sweeper *sweeper) {
463 save_core (sweeper, 0);
464 add_core (sweeper, 0);
465 clear_core (sweeper, 0);
466}
467
468#define LOGBACKBONE(MESSAGE) \
469 LOGLITSET (SIZE_STACK (sweeper->backbone), \
470 BEGIN_STACK (sweeper->backbone), MESSAGE)
471
472#define LOGPARTITION(MESSAGE) \
473 LOGLITPART (SIZE_STACK (sweeper->partition), \
474 BEGIN_STACK (sweeper->partition), MESSAGE)
475
476static void init_backbone_and_partition (sweeper *sweeper) {
478 LOG ("initializing backbone and equivalent literals candidates");
479 for (all_stack (unsigned, idx, sweeper->vars)) {
480 if (!ACTIVE (idx))
481 continue;
482 const unsigned lit = LIT (idx);
483 const unsigned not_lit = NOT (lit);
484 const signed char tmp = kitten_value (solver->kitten, lit);
485 const unsigned candidate = (tmp < 0) ? not_lit : lit;
486 LOG ("sweeping candidate %s", LOGLIT (candidate));
489 }
491
492 LOGBACKBONE ("initialized backbone candidates");
493 LOGPARTITION ("initialized equivalence candidates");
494}
495
496static void sweep_empty_clause (sweeper *sweeper) {
498 save_add_clear_core (sweeper);
500}
501
502static void sweep_refine_partition (sweeper *sweeper) {
504 LOG ("refining partition");
505 kitten *kitten = solver->kitten;
506 unsigneds old_partition = sweeper->partition;
507 unsigneds new_partition;
508 INIT_STACK (new_partition);
509 const value *const values = solver->values;
510 const unsigned *const old_begin = BEGIN_STACK (old_partition);
511 const unsigned *const old_end = END_STACK (old_partition);
512#ifdef LOGGING
513 unsigned old_classes = 0;
514 unsigned new_classes = 0;
515#endif
516 for (const unsigned *p = old_begin, *q; p != old_end; p = q + 1) {
517 unsigned assigned_true = 0, other;
518 for (q = p; (other = *q) != INVALID_LIT; q++) {
519 if (sweep_repr (sweeper, other) != other)
520 continue;
521 if (values[other])
522 continue;
523 signed char value = kitten_value (kitten, other);
524 if (!value)
525 LOG ("dropping sub-solver unassigned %s", LOGLIT (other));
526 else if (value > 0) {
527 PUSH_STACK (new_partition, other);
528 assigned_true++;
529 }
530 }
531#ifdef LOGGING
532 LOG ("refining class %u of size %zu", old_classes, (size_t) (q - p));
533 old_classes++;
534#endif
535 if (assigned_true == 0)
536 LOG ("no positive literal in class");
537 else if (assigned_true == 1) {
538#ifdef LOGGING
539 other =
540#else
541 (void)
542#endif
543 POP_STACK (new_partition);
544 LOG ("dropping singleton class %s", LOGLIT (other));
545 } else {
546 LOG ("%u positive literal in class", assigned_true);
547 PUSH_STACK (new_partition, INVALID_LIT);
548#ifdef LOGGING
549 new_classes++;
550#endif
551 }
552
553 unsigned assigned_false = 0;
554 for (q = p; (other = *q) != INVALID_LIT; q++) {
555 if (sweep_repr (sweeper, other) != other)
556 continue;
557 if (values[other])
558 continue;
559 signed char value = kitten_value (kitten, other);
560 if (value < 0) {
561 PUSH_STACK (new_partition, other);
562 assigned_false++;
563 }
564 }
565
566 if (assigned_false == 0)
567 LOG ("no negative literal in class");
568 else if (assigned_false == 1) {
569#ifdef LOGGING
570 other =
571#else
572 (void)
573#endif
574 POP_STACK (new_partition);
575 LOG ("dropping singleton class %s", LOGLIT (other));
576 } else {
577 LOG ("%u negative literal in class", assigned_false);
578 PUSH_STACK (new_partition, INVALID_LIT);
579#ifdef LOGGING
580 new_classes++;
581#endif
582 }
583 }
584 RELEASE_STACK (old_partition);
585 sweeper->partition = new_partition;
586 LOG ("refined %u classes into %u", old_classes, new_classes);
587 LOGPARTITION ("refined equivalence candidates");
588}
589
590static void sweep_refine_backbone (sweeper *sweeper) {
592 LOG ("refining backbone candidates");
593 const unsigned *const end = END_STACK (sweeper->backbone);
594 unsigned *q = BEGIN_STACK (sweeper->backbone);
595 const value *const values = solver->values;
596 kitten *kitten = solver->kitten;
597 for (const unsigned *p = q; p != end; p++) {
598 const unsigned lit = *p;
599 if (values[lit])
600 continue;
601 signed char value = kitten_value (kitten, lit);
602 if (!value)
603 LOG ("dropping sub-solver unassigned %s", LOGLIT (lit));
604 else if (value >= 0)
605 *q++ = lit;
606 }
608 LOGBACKBONE ("refined backbone candidates");
609}
610
611static void sweep_refine (sweeper *sweeper) {
612#ifdef LOGGING
614#endif
616 LOG ("no need to refine empty backbone candidates");
617 else
618 sweep_refine_backbone (sweeper);
620 LOG ("no need to refine empty partition candidates");
621 else
622 sweep_refine_partition (sweeper);
623}
624
625static void flip_backbone_literals (struct sweeper *sweeper) {
626 struct kissat *solver = sweeper->solver;
627 const unsigned max_rounds = GET_OPTION (sweepfliprounds);
628 if (!max_rounds)
629 return;
631 struct kitten *kitten = solver->kitten;
632 if (kitten_status (kitten) != 10)
633 return;
634#ifdef LOGGING
635 unsigned total_flipped = 0;
636#endif
637 unsigned flipped, round = 0;
638 do {
639 round++;
640 flipped = 0;
641 unsigned *begin = BEGIN_STACK (sweeper->backbone), *q = begin;
642 const unsigned *const end = END_STACK (sweeper->backbone), *p = q;
643 while (p != end) {
644 const unsigned lit = *p++;
645 INC (sweep_flip_backbone);
647 LOG ("flipping backbone candidate %s succeeded", LOGLIT (lit));
648#ifdef LOGGING
649 total_flipped++;
650#endif
651 INC (sweep_flipped_backbone);
652 flipped++;
653 } else {
654 LOG ("flipping backbone candidate %s failed", LOGLIT (lit));
655 *q++ = lit;
656 }
657 }
659 LOG ("flipped %u backbone candidates in round %u", flipped, round);
660
662 break;
663 if (solver->statistics_.kitten_ticks > sweeper->limit.ticks)
664 break;
665 } while (flipped && round < max_rounds);
666 LOG ("flipped %u backbone candidates in total in %u rounds",
667 total_flipped, round);
668}
669
670static bool sweep_backbone_candidate (sweeper *sweeper, unsigned lit) {
672 LOG ("trying backbone candidate %s", LOGLIT (lit));
673 kitten *kitten = solver->kitten;
674 signed char value = kitten_fixed (kitten, lit);
675 if (value) {
676 INC (sweep_fixed_backbone);
677 LOG ("literal %s already fixed", LOGLIT (lit));
678 KISSAT_assert (value > 0);
679 return false;
680 }
681
682 INC (sweep_flip_backbone);
684 INC (sweep_flipped_backbone);
685 LOG ("flipping %s succeeded", LOGLIT (lit));
686 LOGBACKBONE ("refined backbone candidates");
687 return false;
688 }
689
690 LOG ("flipping %s failed", LOGLIT (lit));
691 const unsigned not_lit = NOT (lit);
692 INC (sweep_solved_backbone);
693 kitten_assume (kitten, not_lit);
694 int res = sweep_solve (sweeper);
695 if (res == 10) {
696 LOG ("sweeping backbone candidate %s failed", LOGLIT (lit));
697 sweep_refine (sweeper);
698 INC (sweep_sat_backbone);
699 return false;
700 }
701
702 if (res == 20) {
703 LOG ("sweep unit %s", LOGLIT (lit));
704 save_add_clear_core (sweeper);
705 INC (sweep_unsat_backbone);
706 return true;
707 }
708
709 INC (sweep_unknown_backbone);
710
711 LOG ("sweeping backbone candidate %s failed", LOGLIT (lit));
712 return false;
713}
714
715static void add_binary (kissat *solver, unsigned lit, unsigned other) {
717}
718
719static bool scheduled_variable (sweeper *sweeper, unsigned idx) {
720#ifndef KISSAT_NDEBUG
721 kissat *const solver = sweeper->solver;
723#endif
724 return sweeper->prev[idx] != INVALID_IDX || sweeper->first == idx;
725}
726
727static void schedule_inner (sweeper *sweeper, unsigned idx) {
728 kissat *const solver = sweeper->solver;
730 if (!ACTIVE (idx))
731 return;
732 const unsigned next = sweeper->next[idx];
733 if (next != INVALID_IDX) {
734 LOG ("rescheduling inner %s as last", LOGVAR (idx));
735 const unsigned prev = sweeper->prev[idx];
736 KISSAT_assert (sweeper->prev[next] == idx);
737 sweeper->prev[next] = prev;
738 if (prev == INVALID_IDX) {
739 KISSAT_assert (sweeper->first == idx);
740 sweeper->first = next;
741 } else {
742 KISSAT_assert (sweeper->next[prev] == idx);
743 sweeper->next[prev] = next;
744 }
745 const unsigned last = sweeper->last;
746 if (last == INVALID_IDX) {
748 sweeper->first = idx;
749 } else {
751 sweeper->next[last] = idx;
752 }
753 sweeper->prev[idx] = last;
754 sweeper->next[idx] = INVALID_IDX;
755 sweeper->last = idx;
756 } else if (sweeper->last != idx) {
757 LOG ("scheduling inner %s as last", LOGVAR (idx));
758 const unsigned last = sweeper->last;
759 if (last == INVALID_IDX) {
761 sweeper->first = idx;
762 } else {
764 sweeper->next[last] = idx;
765 }
767 sweeper->prev[idx] = last;
768 sweeper->last = idx;
769 } else
770 LOG ("keeping inner %s scheduled as last", LOGVAR (idx));
771}
772
773static void schedule_outer (sweeper *sweeper, unsigned idx) {
774#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
775 kissat *const solver = sweeper->solver;
776#endif
778 KISSAT_assert (!scheduled_variable (sweeper, idx));
779 KISSAT_assert (ACTIVE (idx));
780 const unsigned first = sweeper->first;
781 if (first == INVALID_IDX) {
783 sweeper->last = idx;
784 } else {
786 sweeper->prev[first] = idx;
787 }
789 sweeper->next[idx] = first;
790 sweeper->first = idx;
791 LOG ("scheduling outer %s as first", LOGVAR (idx));
792}
793
794static unsigned next_scheduled (sweeper *sweeper) {
795#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
796 kissat *const solver = sweeper->solver;
797#endif
798 unsigned res = sweeper->last;
799 if (res == INVALID_IDX) {
800 LOG ("no more scheduled variables left");
801 return INVALID_IDX;
802 }
804 LOG ("dequeuing next scheduled %s", LOGVAR (res));
805 const unsigned prev = sweeper->prev[res];
807 sweeper->prev[res] = INVALID_IDX;
808 if (prev == INVALID_IDX) {
809 KISSAT_assert (sweeper->first == res);
811 } else {
812 KISSAT_assert (sweeper->next[prev] == res);
813 sweeper->next[prev] = INVALID_IDX;
814 }
815 sweeper->last = prev;
816 return res;
817}
818
819#define all_scheduled(IDX) \
820 unsigned IDX = sweeper->first, NEXT_##IDX; \
821 IDX != INVALID_IDX && (NEXT_##IDX = sweeper->next[IDX], true); \
822 IDX = NEXT_##IDX
823
824static void substitute_connected_clauses (sweeper *sweeper, unsigned lit,
825 unsigned repr) {
827 if (solver->inconsistent)
828 return;
829 value *const values = solver->values;
830 if (values[lit])
831 return;
832 if (values[repr])
833 return;
834 LOG ("substituting %s with %s in all irredundant clauses", LOGLIT (lit),
835 LOGLIT (repr));
836
837 KISSAT_assert (lit != repr);
838 KISSAT_assert (lit != NOT (repr));
839
840#ifdef CHECKING_OR_PROVING
841 const bool checking_or_proving = kissat_checking_or_proving (solver);
843 KISSAT_assert (EMPTY_STACK (solver->removed));
844#endif
845
846 unsigneds *const delayed = &solver->delayed;
847 KISSAT_assert (EMPTY_STACK (*delayed));
848
849 {
850 watches *lit_watches = &WATCHES (lit);
851 watch *const begin_watches = BEGIN_WATCHES (*lit_watches);
852 const watch *const end_watches = END_WATCHES (*lit_watches);
853
854 watch *q = begin_watches;
855 const watch *p = q;
856
857 while (p != end_watches) {
858 const watch head = *q++ = *p++;
859 if (head.type.binary) {
860 const unsigned other = head.binary.lit;
861 const value other_value = values[other];
862 if (other == NOT (repr))
863 continue;
864 if (other_value < 0)
865 break;
866 if (other_value > 0)
867 continue;
868 if (other == repr) {
871 kissat_assign_unit (solver, lit, "substituted binary clause");
872 INC (sweep_units);
873 break;
874 }
875 CHECK_AND_ADD_BINARY (repr, other);
876 ADD_BINARY_TO_PROOF (repr, other);
877 REMOVE_CHECKER_BINARY (lit, other);
879 PUSH_STACK (*delayed, head.raw);
880 watch src = {.raw = head.raw};
881 watch dst = {.raw = head.raw};
882 src.binary.lit = lit;
883 dst.binary.lit = repr;
884 watches *other_watches = &WATCHES (other);
885 kissat_substitute_large_watch (solver, other_watches, src, dst);
886 q--;
887 } else {
888 const reference ref = head.large.ref;
890 clause *c = kissat_dereference_clause (solver, ref);
891 if (c->garbage)
892 continue;
893
894 bool satisfied = false;
895 bool repr_already_watched = false;
896 const unsigned not_repr = NOT (repr);
897#ifndef KISSAT_NDEBUG
898 bool found = false;
899#endif
900 for (all_literals_in_clause (other, c)) {
901 if (other == lit) {
902#ifndef KISSAT_NDEBUG
903 KISSAT_assert (!found);
904 found = true;
905#endif
906 PUSH_STACK (solver->clause, repr);
907 continue;
908 }
909 KISSAT_assert (other != NOT (lit));
910 if (other == repr) {
911 KISSAT_assert (!repr_already_watched);
912 repr_already_watched = true;
913 continue;
914 }
915 if (other == not_repr) {
916 satisfied = true;
917 break;
918 }
919 const value tmp = values[other];
920 if (tmp < 0)
921 continue;
922 if (tmp > 0) {
923 satisfied = true;
924 break;
925 }
926 PUSH_STACK (solver->clause, other);
927 }
928
929 if (satisfied) {
930 CLEAR_STACK (solver->clause);
932 continue;
933 }
934 KISSAT_assert (found);
935
936 const unsigned new_size = SIZE_STACK (solver->clause);
937
938 if (new_size == 0) {
939 LOGCLS (c, "substituted empty clause");
940 KISSAT_assert (!solver->inconsistent);
941 solver->inconsistent = true;
944 break;
945 }
946
947 if (new_size == 1) {
948 LOGCLS (c, "reduces to unit");
949 const unsigned unit = POP_STACK (solver->clause);
950 CHECK_AND_ADD_UNIT (unit);
951 ADD_UNIT_TO_PROOF (unit);
952 kissat_assign_unit (solver, unit, "substituted large clause");
953 INC (sweep_units);
954 break;
955 }
956
957 CHECK_AND_ADD_STACK (solver->clause);
958 ADD_STACK_TO_PROOF (solver->clause);
961
962 if (!c->redundant)
964 BEGIN_STACK (solver->clause));
965
966 if (new_size == 2) {
967 const unsigned second = POP_STACK (solver->clause);
968 const unsigned first = POP_STACK (solver->clause);
969 LOGCLS (c, "reduces to binary clause %s %s", LOGLIT (first),
970 LOGLIT (second));
971 KISSAT_assert (first == repr || second == repr);
972 const unsigned other = first ^ second ^ repr;
973 const watch src = {.raw = head.raw};
974 watch dst = kissat_binary_watch (repr);
975 watches *other_watches = &WATCHES (other);
976 kissat_substitute_large_watch (solver, other_watches, src, dst);
977 KISSAT_assert (solver->statistics_.clauses_irredundant);
978 solver->statistics_.clauses_irredundant--;
979 KISSAT_assert (solver->statistics_.clauses_binary < UINT64_MAX);
980 solver->statistics_.clauses_binary++;
981 dst.binary.lit = other;
982 PUSH_STACK (*delayed, dst.raw);
983 const size_t bytes = kissat_actual_bytes_of_clause (c);
984 ADD (arena_garbage, bytes);
985 c->garbage = true;
986 q--;
987 continue;
988 }
989
990 KISSAT_assert (2 < new_size);
991 const unsigned old_size = c->size;
992 KISSAT_assert (new_size <= old_size);
993
994 const unsigned *const begin = BEGIN_STACK (solver->clause);
995 const unsigned *const end = END_STACK (solver->clause);
996
997 unsigned *lits = c->lits;
998 unsigned *q = lits;
999
1000 for (const unsigned *p = begin; p != end; p++) {
1001 const unsigned other = *p;
1002 *q++ = other;
1003 }
1004
1005 if (new_size < old_size) {
1006 c->size = new_size;
1007 c->searched = 2;
1008 if (c->redundant && c->glue >= new_size)
1009 kissat_promote_clause (solver, c, new_size - 1);
1010 if (!c->shrunken) {
1011 c->shrunken = true;
1012 lits[old_size - 1] = INVALID_LIT;
1013 }
1014 }
1015
1016 LOGCLS (c, "substituted");
1017
1018 if (!repr_already_watched)
1019 PUSH_STACK (*delayed, head.raw);
1020 CLEAR_STACK (solver->clause);
1021 q--;
1022 }
1023 }
1024 while (p != end_watches)
1025 *q++ = *p++;
1026 SET_END_OF_WATCHES (*lit_watches, q);
1027 }
1028 {
1029 const unsigned *const begin_delayed = BEGIN_STACK (*delayed);
1030 const unsigned *const end_delayed = END_STACK (*delayed);
1031 for (const unsigned *p = begin_delayed; p != end_delayed; p++) {
1032 const watch head = {.raw = *p};
1033 watches *repr_watches = &WATCHES (repr);
1034 PUSH_WATCHES (*repr_watches, head);
1035 }
1036
1037 CLEAR_STACK (*delayed);
1038 }
1039
1040#ifdef CHECKING_OR_PROVING
1041 if (checking_or_proving) {
1042 CLEAR_STACK (solver->added);
1043 CLEAR_STACK (solver->removed);
1044 }
1045#endif
1046}
1047
1048static void sweep_remove (sweeper *sweeper, unsigned lit) {
1051 unsigneds *partition = &sweeper->partition;
1052 unsigned *const begin_partition = BEGIN_STACK (*partition), *p;
1053 const unsigned *const end_partition = END_STACK (*partition);
1054 for (p = begin_partition; *p != lit; p++)
1055 KISSAT_assert (p + 1 != end_partition);
1056 unsigned *begin_class = p;
1057 while (begin_class != begin_partition && begin_class[-1] != INVALID_LIT)
1058 begin_class--;
1059 const unsigned *end_class = p;
1060 while (*end_class != INVALID_LIT)
1061 end_class++;
1062 const unsigned size = end_class - begin_class;
1063 LOG ("removing non-representative %s from equivalence class of size %u",
1064 LOGLIT (lit), size);
1065 KISSAT_assert (size > 1);
1066 unsigned *q = begin_class;
1067 if (size == 2) {
1068 LOG ("completely squashing equivalence class of %s", LOGLIT (lit));
1069 for (const unsigned *r = end_class + 1; r != end_partition; r++)
1070 *q++ = *r;
1071 } else {
1072 for (const unsigned *r = begin_class; r != end_partition; r++)
1073 if (r != p)
1074 *q++ = *r;
1075 }
1076 SET_END_OF_STACK (*partition, q);
1077#ifndef LOGGING
1078 (void) solver;
1079#endif
1080}
1081
1082static void flip_partition_literals (struct sweeper *sweeper) {
1083 struct kissat *solver = sweeper->solver;
1084 const unsigned max_rounds = GET_OPTION (sweepfliprounds);
1085 if (!max_rounds)
1086 return;
1088 struct kitten *kitten = solver->kitten;
1089 if (kitten_status (kitten) != 10)
1090 return;
1091#ifdef LOGGING
1092 unsigned total_flipped = 0;
1093#endif
1094 unsigned flipped, round = 0;
1095 do {
1096 round++;
1097 flipped = 0;
1098 unsigned *begin = BEGIN_STACK (sweeper->partition), *dst = begin;
1099 const unsigned *const end = END_STACK (sweeper->partition), *src = dst;
1100 while (src != end) {
1101 const unsigned *end_src = src;
1102 while (KISSAT_assert (end_src != end), *end_src != INVALID_LIT)
1103 end_src++;
1104 unsigned size = end_src - src;
1105 KISSAT_assert (size > 1);
1106 unsigned *q = dst;
1107 for (const unsigned *p = src; p != end_src; p++) {
1108 const unsigned lit = *p;
1110 LOG ("flipping equivalence candidate %s succeeded", LOGLIT (lit));
1111#ifdef LOGGING
1112 total_flipped++;
1113#endif
1114 flipped++;
1115 if (--size < 2)
1116 break;
1117 } else {
1118 LOG ("flipping equivalence candidate %s failed", LOGLIT (lit));
1119 *q++ = lit;
1120 }
1121 }
1122 if (size > 1) {
1123 *q++ = INVALID_LIT;
1124 dst = q;
1125 }
1126 src = end_src + 1;
1127 }
1129 LOG ("flipped %u equivalence candidates in round %u", flipped, round);
1130
1132 break;
1133 if (solver->statistics_.kitten_ticks > sweeper->limit.ticks)
1134 break;
1135 } while (flipped && round < max_rounds);
1136 LOG ("flipped %u equivalence candidates in total in %u rounds",
1137 total_flipped, round);
1138}
1139
1140static bool sweep_equivalence_candidates (sweeper *sweeper, unsigned lit,
1141 unsigned other) {
1143 LOG ("trying equivalence candidates %s = %s", LOGLIT (lit),
1144 LOGLIT (other));
1145 const unsigned not_other = NOT (other);
1146 const unsigned not_lit = NOT (lit);
1147 kitten *kitten = solver->kitten;
1148 const unsigned *const begin = BEGIN_STACK (sweeper->partition);
1149 unsigned *const end = END_STACK (sweeper->partition);
1150 KISSAT_assert (begin + 3 <= end);
1151 KISSAT_assert (end[-3] == lit);
1152 KISSAT_assert (end[-2] == other);
1153 const unsigned third = (end - begin == 3) ? INVALID_LIT : end[-4];
1154 const int status = kitten_status (kitten);
1155 if (status == 10 && kitten_flip_literal (kitten, lit)) {
1156 INC (sweep_flip_equivalences);
1157 INC (sweep_flipped_equivalences);
1158 LOG ("flipping %s succeeded", LOGLIT (lit));
1159 if (third == INVALID_LIT) {
1160 LOG ("squashing equivalence class of %s", LOGLIT (lit));
1162 } else {
1163 LOG ("removing %s from equivalence class of %s", LOGLIT (lit),
1164 LOGLIT (other));
1165 end[-3] = other;
1166 end[-2] = INVALID_LIT;
1168 }
1169 LOGPARTITION ("refined equivalence candidates");
1170 return false;
1171 } else if (status == 10 && kitten_flip_literal (kitten, other)) {
1172 ADD (sweep_flip_equivalences, 2);
1173 INC (sweep_flipped_equivalences);
1174 LOG ("flipping %s succeeded", LOGLIT (other));
1175 if (third == INVALID_LIT) {
1176 LOG ("squashing equivalence class of %s", LOGLIT (lit));
1178 } else {
1179 LOG ("removing %s from equivalence class of %s", LOGLIT (other),
1180 LOGLIT (lit));
1181 end[-2] = INVALID_LIT;
1183 }
1184 LOGPARTITION ("refined equivalence candidates");
1185 return false;
1186 }
1187 if (status == 10)
1188 ADD (sweep_flip_equivalences, 2);
1189 LOG ("flipping %s and %s both failed", LOGLIT (lit), LOGLIT (other));
1190 kitten_assume (kitten, not_lit);
1191 kitten_assume (kitten, other);
1192 INC (sweep_solved_equivalences);
1193 int res = sweep_solve (sweeper);
1194 if (res == 10) {
1195 INC (sweep_sat_equivalences);
1196 LOG ("first sweeping implication %s -> %s failed", LOGLIT (other),
1197 LOGLIT (lit));
1198 sweep_refine (sweeper);
1199 } else if (!res) {
1200 INC (sweep_unknown_equivalences);
1201 LOG ("first sweeping implication %s -> %s hit ticks limit",
1202 LOGLIT (other), LOGLIT (lit));
1203 }
1204
1205 if (res != 20)
1206 return false;
1207
1208 INC (sweep_unsat_equivalences);
1209 LOG ("first sweeping implication %s -> %s succeeded", LOGLIT (other),
1210 LOGLIT (lit));
1211
1212 save_core (sweeper, 0);
1213
1215 kitten_assume (kitten, not_other);
1216 res = sweep_solve (sweeper);
1217 INC (sweep_solved_equivalences);
1218 if (res == 10) {
1219 INC (sweep_sat_equivalences);
1220 LOG ("second sweeping implication %s <- %s failed", LOGLIT (other),
1221 LOGLIT (lit));
1222 sweep_refine (sweeper);
1223 } else if (!res) {
1224 INC (sweep_unknown_equivalences);
1225 LOG ("second sweeping implication %s <- %s hit ticks limit",
1226 LOGLIT (other), LOGLIT (lit));
1227 }
1228
1229 if (res != 20) {
1230 CLEAR_STACK (sweeper->core[0]);
1231 return false;
1232 }
1233
1234 INC (sweep_unsat_equivalences);
1235 LOG ("second sweeping implication %s <- %s succeeded too", LOGLIT (other),
1236 LOGLIT (lit));
1237
1238 save_core (sweeper, 1);
1239
1240 LOG ("sweep equivalence %s = %s", LOGLIT (lit), LOGLIT (other));
1241 INC (sweep_equivalences);
1242
1243 add_core (sweeper, 0);
1244 add_binary (solver, lit, not_other);
1245 clear_core (sweeper, 0);
1246
1247 add_core (sweeper, 1);
1248 add_binary (solver, not_lit, other);
1249 clear_core (sweeper, 1);
1250
1251 unsigned repr;
1252 if (lit < other) {
1253 repr = sweeper->reprs[other] = lit;
1254 sweeper->reprs[not_other] = not_lit;
1255 substitute_connected_clauses (sweeper, other, lit);
1256 substitute_connected_clauses (sweeper, not_other, not_lit);
1257 sweep_remove (sweeper, other);
1258 } else {
1259 repr = sweeper->reprs[lit] = other;
1260 sweeper->reprs[not_lit] = not_other;
1261 substitute_connected_clauses (sweeper, lit, other);
1262 substitute_connected_clauses (sweeper, not_lit, not_other);
1263 sweep_remove (sweeper, lit);
1264 }
1265
1266 const unsigned repr_idx = IDX (repr);
1267 schedule_inner (sweeper, repr_idx);
1268
1269 return true;
1270}
1271
1272static const char *sweep_variable (sweeper *sweeper, unsigned idx) {
1274 KISSAT_assert (!solver->inconsistent);
1275 if (!ACTIVE (idx))
1276 return "inactive variable";
1277 const unsigned start = LIT (idx);
1278 if (sweeper->reprs[start] != start)
1279 return "non-representative variable";
1285
1286 INC (sweep_variables);
1287
1288 LOG ("sweeping %s", LOGVAR (idx));
1289 KISSAT_assert (!VALUE (start));
1290 LOG ("starting sweeping[0]");
1291 add_literal_to_environment (sweeper, 0, start);
1292 LOG ("finished sweeping[0]");
1293 LOG ("starting sweeping[1]");
1294
1295 bool limit_reached = false;
1296 size_t expand = 0, next = 1;
1297 bool success = false;
1298 unsigned depth = 1;
1299
1300 while (!limit_reached) {
1301 if (sweeper->encoded >= sweeper->limit.clauses) {
1302 LOG ("environment clause limit reached");
1303 limit_reached = true;
1304 break;
1305 }
1306 if (expand == next) {
1307 LOG ("finished sweeping[%u]", depth);
1308 if (depth >= sweeper->limit.depth) {
1309 LOG ("environment depth limit reached");
1310 break;
1311 }
1312 next = SIZE_STACK (sweeper->vars);
1313 if (expand == next) {
1314 LOG ("completely copied all clauses");
1315 break;
1316 }
1317 depth++;
1318 LOG ("starting sweeping[%u]", depth);
1319 }
1320 const unsigned choices = next - expand;
1321 if (GET_OPTION (sweeprand) && choices > 1) {
1322 const unsigned swap =
1323 kissat_pick_random (&solver->random, 0, choices);
1324 if (swap) {
1325 unsigned *vars = sweeper->vars.begin;
1326 SWAP (unsigned, vars[expand], vars[expand + swap]);
1327 }
1328 }
1329 const unsigned idx = PEEK_STACK (sweeper->vars, expand);
1330 LOG ("traversing and adding clauses of %s", LOGVAR (idx));
1331 for (unsigned sign = 0; sign < 2; sign++) {
1332 const unsigned lit = LIT (idx) + sign;
1333 watches *watches = &WATCHES (lit);
1335 if (watch.type.binary) {
1336 const unsigned other = watch.binary.lit;
1337 sweep_binary (sweeper, depth, lit, other);
1338 } else {
1340 sweep_reference (sweeper, depth, ref);
1341 }
1342 if (SIZE_STACK (sweeper->vars) >= sweeper->limit.vars) {
1343 LOG ("environment variable limit reached");
1344 limit_reached = true;
1345 break;
1346 }
1347 }
1348 if (limit_reached)
1349 break;
1350 }
1351 expand++;
1352 }
1353 ADD (sweep_depth, depth);
1354 ADD (sweep_clauses, sweeper->encoded);
1355 ADD (sweep_environment, SIZE_STACK (sweeper->vars));
1357 "sweeping variable %d environment of "
1358 "%zu variables %u clauses depth %u",
1359 kissat_export_literal (solver, LIT (idx)),
1361 depth);
1362 int res = sweep_solve (sweeper);
1363 LOG ("sub-solver returns '%d'", res);
1364 if (res == 10) {
1365 init_backbone_and_partition (sweeper);
1366#ifndef KISSAT_QUIET
1367 uint64_t units = solver->statistics_.sweep_units;
1368 uint64_t solved = solver->statistics_.sweep_solved;
1369#endif
1370 START (sweepbackbone);
1371 while (!EMPTY_STACK (sweeper->backbone)) {
1372 if (solver->inconsistent || TERMINATED (sweep_terminated_3) ||
1373 kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1374 limit_reached = true;
1375 STOP_SWEEP_BACKBONE:
1376 STOP (sweepbackbone);
1377 goto DONE;
1378 }
1379 flip_backbone_literals (sweeper);
1381 kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1382 limit_reached = true;
1383 goto STOP_SWEEP_BACKBONE;
1384 }
1386 break;
1387 const unsigned lit = POP_STACK (sweeper->backbone);
1388 if (!ACTIVE (IDX (lit)))
1389 continue;
1390 if (sweep_backbone_candidate (sweeper, lit))
1391 success = true;
1392 }
1393 STOP (sweepbackbone);
1394#ifndef KISSAT_QUIET
1395 units = solver->statistics_.sweep_units - units;
1396 solved = solver->statistics_.sweep_solved - solved;
1398 solver,
1399 "complete swept variable %d backbone with %" PRIu64
1400 " units in %" PRIu64 " solver calls",
1401 kissat_export_literal (solver, LIT (idx)), units, solved);
1402#endif
1404#ifndef KISSAT_QUIET
1405 uint64_t equivalences = solver->statistics_.sweep_equivalences;
1406 solved = solver->statistics_.sweep_solved;
1407#endif
1408 START (sweepequivalences);
1409 while (!EMPTY_STACK (sweeper->partition)) {
1410 if (solver->inconsistent || TERMINATED (sweep_terminated_5) ||
1411 kitten_ticks_limit_hit (sweeper, "partition refinement")) {
1412 limit_reached = true;
1413 STOP_SWEEP_EQUIVALENCES:
1414 STOP (sweepequivalences);
1415 goto DONE;
1416 }
1417 flip_partition_literals (sweeper);
1419 kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1420 limit_reached = true;
1421 goto STOP_SWEEP_EQUIVALENCES;
1422 }
1424 break;
1425 if (SIZE_STACK (sweeper->partition) > 2) {
1426 const unsigned *end = END_STACK (sweeper->partition);
1427 KISSAT_assert (end[-1] == INVALID_LIT);
1428 unsigned lit = end[-3];
1429 unsigned other = end[-2];
1430 if (sweep_equivalence_candidates (sweeper, lit, other))
1431 success = true;
1432 } else
1434 }
1435 STOP (sweepequivalences);
1436#ifndef KISSAT_QUIET
1437 equivalences = solver->statistics_.sweep_equivalences - equivalences;
1438 solved = solver->statistics_.sweep_solved - solved;
1439 if (equivalences)
1441 solver,
1442 "complete swept variable %d partition with %" PRIu64
1443 " equivalences in %" PRIu64 " solver calls",
1444 kissat_export_literal (solver, LIT (idx)), equivalences, solved);
1445#endif
1446 } else if (res == 20)
1447 sweep_empty_clause (sweeper);
1448
1449DONE:
1450 clear_sweeper (sweeper);
1451
1452 if (!solver->inconsistent && !kissat_propagated (solver))
1454
1455 if (success && limit_reached)
1456 return "successfully despite reaching limit";
1457 if (!success && !limit_reached)
1458 return "unsuccessfully without reaching limit";
1459 else if (success && !limit_reached)
1460 return "successfully without reaching limit";
1461 KISSAT_assert (!success && limit_reached);
1462 return "unsuccessfully and reached limit";
1463}
1464
1466
1468 unsigned rank;
1469 unsigned idx;
1470};
1471
1472// clang-format off
1473
1474typedef STACK(sweep_candidate) sweep_candidates;
1475
1476// clang-format on
1477
1478#define RANK_SWEEP_CANDIDATE(CAND) (CAND).rank
1479
1480static bool scheduable_variable (sweeper *sweeper, unsigned idx,
1481 size_t *occ_ptr) {
1483 const unsigned lit = LIT (idx);
1484 const size_t pos = SIZE_WATCHES (WATCHES (lit));
1485 if (!pos)
1486 return false;
1487 const unsigned max_occurrences = sweeper->limit.clauses;
1488 if (pos > max_occurrences)
1489 return false;
1490 const unsigned not_lit = NOT (lit);
1491 const size_t neg = SIZE_WATCHES (WATCHES (not_lit));
1492 if (!neg)
1493 return false;
1494 if (neg > max_occurrences)
1495 return false;
1496 *occ_ptr = pos + neg;
1497 return true;
1498}
1499
1500static unsigned schedule_all_other_not_scheduled_yet (sweeper *sweeper) {
1502 sweep_candidates fresh;
1503 INIT_STACK (fresh);
1504 flags *const flags = solver->flags;
1505 const bool incomplete = solver->sweep_incomplete;
1506 for (all_variables (idx)) {
1507 struct flags *const f = flags + idx;
1508 if (!f->active)
1509 continue;
1510 if (incomplete && !f->sweep)
1511 continue;
1512 if (scheduled_variable (sweeper, idx))
1513 continue;
1514 size_t occ;
1515 if (!scheduable_variable (sweeper, idx, &occ)) {
1516 FLAGS (idx)->sweep = false;
1517 continue;
1518 }
1519 sweep_candidate cand;
1520 cand.rank = occ;
1521 cand.idx = idx;
1522 PUSH_STACK (fresh, cand);
1523 }
1524 const size_t size = SIZE_STACK (fresh);
1525 KISSAT_assert (size <= UINT_MAX);
1527 for (all_stack (sweep_candidate, cand, fresh))
1528 schedule_outer (sweeper, cand.idx);
1529 RELEASE_STACK (fresh);
1530 return size;
1531}
1532
1533static unsigned reschedule_previously_remaining (sweeper *sweeper) {
1535 flags *flags = solver->flags;
1536 unsigned rescheduled = 0;
1537 unsigneds *remaining = &solver->sweep_schedule;
1538 for (all_stack (unsigned, idx, *remaining)) {
1539 struct flags *f = flags + idx;
1540 if (!f->active)
1541 continue;
1542 if (scheduled_variable (sweeper, idx))
1543 continue;
1544 size_t occ;
1545 if (!scheduable_variable (sweeper, idx, &occ)) {
1546 f->sweep = false;
1547 continue;
1548 }
1549 schedule_inner (sweeper, idx);
1550 rescheduled++;
1551 }
1552 RELEASE_STACK (*remaining);
1553 return rescheduled;
1554}
1555
1556static unsigned incomplete_variables (sweeper *sweeper) {
1558 flags *flags = solver->flags;
1559 unsigned res = 0;
1560 for (all_variables (idx)) {
1561 struct flags *f = flags + idx;
1562 if (!f->active)
1563 continue;
1564 if (f->sweep)
1565 res++;
1566 }
1567 return res;
1568}
1569
1570static void mark_incomplete (sweeper *sweeper) {
1572 flags *flags = solver->flags;
1573 unsigned marked = 0;
1574 for (all_scheduled (idx))
1575 if (!flags[idx].sweep) {
1576 flags[idx].sweep = true;
1577 marked++;
1578 }
1579 solver->sweep_incomplete = true;
1580#ifndef KISSAT_QUIET
1582 solver, "marked %u scheduled sweeping variables as incomplete",
1583 marked);
1584#else
1585 (void) marked;
1586#endif
1587}
1588
1589static unsigned schedule_sweeping (sweeper *sweeper) {
1590 const unsigned rescheduled = reschedule_previously_remaining (sweeper);
1591 const unsigned fresh = schedule_all_other_not_scheduled_yet (sweeper);
1592 const unsigned scheduled = fresh + rescheduled;
1593 const unsigned incomplete = incomplete_variables (sweeper);
1595#ifndef KISSAT_QUIET
1596 kissat_phase (solver, "sweep", GET (sweep),
1597 "scheduled %u variables %.0f%% "
1598 "(%u rescheduled %.0f%%, %u incomplete %.0f%%)",
1599 scheduled,
1600 kissat_percent (scheduled, sweeper->solver->active),
1601 rescheduled, kissat_percent (rescheduled, scheduled),
1602 incomplete, kissat_percent (incomplete, scheduled));
1603#endif
1604 if (incomplete)
1605 KISSAT_assert (solver->sweep_incomplete);
1606 else {
1607 if (solver->sweep_incomplete)
1608 INC (sweep_completed);
1609 mark_incomplete (sweeper);
1610 }
1611 return scheduled;
1612}
1613
1614static void unschedule_sweeping (sweeper *sweeper, unsigned swept,
1615 unsigned scheduled) {
1617#ifdef KISSAT_QUIET
1618 (void) scheduled, (void) swept;
1619#endif
1620 KISSAT_assert (EMPTY_STACK (solver->sweep_schedule));
1621 KISSAT_assert (solver->sweep_incomplete);
1622 flags *flags = solver->flags;
1623 for (all_scheduled (idx))
1624 if (flags[idx].active) {
1625 PUSH_STACK (solver->sweep_schedule, idx);
1626 LOG ("untried scheduled %s", LOGVAR (idx));
1627 }
1628#ifndef KISSAT_QUIET
1629 const unsigned retained = SIZE_STACK (solver->sweep_schedule);
1631 solver, "retained %u variables %.0f%% to be swept next time",
1632 retained, kissat_percent (retained, solver->active));
1633#endif
1634 const unsigned incomplete = incomplete_variables (sweeper);
1635 if (incomplete)
1637 solver, "need to sweep %u more variables %.0f%% for completion",
1638 incomplete, kissat_percent (incomplete, solver->active));
1639 else {
1641 "no more variables needed to complete sweep");
1642 solver->sweep_incomplete = false;
1643 INC (sweep_completed);
1644 }
1645 kissat_phase (solver, "sweep", GET (sweep),
1646 "swept %u variables (%u remain %.0f%%)", swept, incomplete,
1647 kissat_percent (incomplete, scheduled));
1648}
1649
1651 if (!GET_OPTION (sweep))
1652 return false;
1653 if (solver->inconsistent)
1654 return false;
1656 return false;
1657 if (DELAYING (sweep))
1658 return false;
1659 KISSAT_assert (!solver->level);
1660 KISSAT_assert (!solver->unflushed);
1661 START (sweep);
1662 INC (sweep);
1663 statistics *statistics = &solver->statistics_;
1664 uint64_t equivalences = statistics->sweep_equivalences;
1665 uint64_t units = statistics->sweep_units;
1667 init_sweeper (solver, &sweeper);
1668 const unsigned scheduled = schedule_sweeping (&sweeper);
1669 uint64_t swept = 0, limit = 10;
1670 for (;;) {
1671 if (solver->inconsistent)
1672 break;
1674 break;
1675 if (solver->statistics_.kitten_ticks > sweeper.limit.ticks)
1676 break;
1677 unsigned idx = next_scheduled (&sweeper);
1678 if (idx == INVALID_IDX)
1679 break;
1680 FLAGS (idx)->sweep = false;
1681#ifndef KISSAT_QUIET
1682 const char *res =
1683#endif
1684 sweep_variable (&sweeper, idx);
1686 solver, "swept[%" PRIu64 "] external variable %d %s", swept,
1687 kissat_export_literal (solver, LIT (idx)), res);
1688 if (++swept == limit) {
1690 "found %" PRIu64 " equivalences and %" PRIu64
1691 " units after sweeping %" PRIu64 " variables ",
1692 statistics->sweep_equivalences - equivalences,
1693 solver->statistics_.sweep_units - units, swept);
1694 limit *= 10;
1695 }
1696 }
1697 kissat_very_verbose (solver, "swept %" PRIu64 " variables", swept);
1698 equivalences = statistics->sweep_equivalences - equivalences,
1699 units = solver->statistics_.sweep_units - units;
1700 kissat_phase (solver, "sweep", GET (sweep),
1701 "found %" PRIu64 " equivalences and %" PRIu64 " units",
1702 equivalences, units);
1703 unschedule_sweeping (&sweeper, swept, scheduled);
1704 unsigned inactive = release_sweeper (&sweeper);
1705
1706 if (!solver->inconsistent) {
1707 solver->propagate = solver->trail.begin;
1709 }
1710
1711 uint64_t eliminated = equivalences + units;
1712#ifndef KISSAT_QUIET
1713 KISSAT_assert (solver->active >= inactive);
1714 solver->active -= inactive;
1715 REPORT (!eliminated, '=');
1716 solver->active += inactive;
1717#else
1718 (void) inactive;
1719#endif
1720 if (kissat_average (eliminated, swept) < 0.001)
1721 BUMP_DELAY (sweep);
1722 else
1724 STOP (sweep);
1725 return eliminated;
1726}
1727
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define NALLOC(T, P, N)
Definition allocate.h:24
ABC_NAMESPACE_IMPL_START void kissat_assign_unit(kissat *solver, unsigned lit, const char *reason)
Definition assign.c:10
#define BEGIN_STACK(S)
Definition stack.h:46
#define RESIZE_STACK(S, NEW_SIZE)
Definition stack.h:55
#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 SET_END_OF_STACK(S, P)
Definition stack.h:62
#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 INIT_STACK(S)
Definition stack.h:22
#define STACK(TYPE)
Definition stack.h:10
#define END_STACK(S)
Definition stack.h:48
#define INVALID_LIT
#define ADD(NAME, DELTA)
#define INC(NAME)
#define CALLOC(T, P, N)
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
#define LOGLITS(...)
#define DEALLOC(P, N)
#define all_scheduled(IDX)
#define FLAGS
#define CHECK_AND_ADD_UNIT(...)
Definition check.h:155
#define REMOVE_CHECKER_CLAUSE(...)
Definition check.h:167
#define CHECK_AND_ADD_STACK(...)
Definition check.h:152
#define CHECK_AND_ADD_LITS(...)
Definition check.h:149
#define CHECK_AND_ADD_EMPTY(...)
Definition check.h:146
#define CHECK_AND_ADD_BINARY(...)
Definition check.h:137
#define REMOVE_CHECKER_LITS(...)
Definition check.h:170
#define REMOVE_CHECKER_BINARY(...)
Definition check.h:161
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_enter_dense_mode(kissat *solver, litpairs *irredundant)
Definition dense.c:101
void kissat_resume_sparse_mode(kissat *solver, bool flush_eliminated, litpairs *irredundant)
Definition dense.c:201
pcover expand()
#define ACTIVE
Definition espresso.h:129
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
void kissat_mark_added_literals(kissat *solver, unsigned size, unsigned *lits)
Definition flags.c:113
@ DONE
Definition inflate.h:51
#define VARS
Definition internal.h:250
#define all_variables(IDX)
Definition internal.h:269
#define all_literals(LIT)
Definition internal.h:274
#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 all_literals_in_clause(LIT, C)
Definition clause.h:47
#define KISSAT_assert(ignore)
Definition global.h:13
int kitten_solve(kitten *kitten)
Definition kitten.c:1818
kitten * kitten_embedded(struct kissat *kissat)
Definition kitten.c:664
void kitten_traverse_core_clauses(kitten *kitten, void *state, void(*traverse)(void *, bool, size_t, const unsigned *))
Definition kitten.c:1989
bool kitten_flip_literal(kitten *kitten, unsigned elit)
Definition kitten.c:2125
#define solver
Definition kitten.c:211
void kitten_release(kitten *kitten)
Definition kitten.c:1028
void kitten_assume(kitten *kitten, unsigned elit)
Definition kitten.c:1763
void kitten_track_antecedents(kitten *kitten)
Definition kitten.c:680
void kitten_clause(kitten *kitten, size_t size, unsigned *elits)
Definition kitten.c:1800
signed char kitten_fixed(kitten *kitten, unsigned elit)
Definition kitten.c:2107
int kitten_status(kitten *kitten)
Definition kitten.c:1870
void kitten_set_ticks_limit(kitten *kitten, uint64_t delta)
Definition kitten.c:749
unsigned kitten_compute_clausal_core(kitten *kitten, uint64_t *learned_ptr)
Definition kitten.c:1872
void kitten_randomize_phases(kitten *kitten)
Definition kitten.c:690
void kitten_clear(kitten *kitten)
Definition kitten.c:986
signed char kitten_value(kitten *kitten, unsigned elit)
Definition kitten.c:2095
#define SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
Definition limit.hpp:131
#define LOGBINARY(...)
Definition logging.h:442
#define LOGCLS(...)
Definition logging.h:415
#define LOGLIT(...)
Definition logging.hpp:99
bool sign(Lit p)
Definition SolverTypes.h:63
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 ADD_EMPTY_TO_PROOF(...)
Definition proof.h:135
#define ADD_UNIT_TO_PROOF(...)
Definition proof.h:141
#define ADD_BINARY_TO_PROOF(...)
Definition proof.h:123
#define DELETE_CLAUSE_FROM_PROOF(...)
Definition proof.h:155
#define DELETE_LITS_FROM_PROOF(...)
Definition proof.h:158
#define ADD_LITS_TO_PROOF(...)
Definition proof.h:132
#define DELETE_BINARY_FROM_PROOF(...)
Definition proof.h:149
#define ADD_STACK_TO_PROOF(...)
Definition proof.h:138
bool kissat_dense_propagate(kissat *solver)
Definition propdense.c:88
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 LIT(IDX)
Definition literal.h:31
#define VALID_INTERNAL_INDEX(IDX)
Definition literal.h:21
#define INVALID_IDX
Definition literal.h:18
#define IDX(LIT)
Definition literal.h:28
#define NOT(LIT)
Definition literal.h:33
#define GET(NAME)
Definition statistics.h:416
unsigned glue
Definition clause.h:23
bool swept
Definition clause.h:31
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
Definition flags.h:11
bool active
Definition flags.h:12
bool sweep
Definition flags.h:20
bool eliminated
Definition flags.h:16
unsigned active
Definition internal.h:108
bool inconsistent
Definition internal.h:87
kar * vars
Definition kitten.c:249
size_t lits
Definition kitten.c:232
unsigned first
Definition kitten.c:238
value * values
Definition kitten.c:252
unsigneds units
Definition kitten.c:267
int status
Definition kitten.c:216
size_t size
Definition kitten.c:246
unsigned last
Definition kitten.c:238
unsigned rank
Definition sweep.c:1468
unsigned idx
Definition sweep.c:1469
unsigneds clause
Definition sweep.c:30
unsigneds backbone
Definition sweep.c:31
unsigneds core[2]
Definition sweep.c:33
references refs
Definition sweep.c:29
unsigned save
Definition sweep.c:27
unsigned last
Definition sweep.c:25
unsigned * reprs
Definition sweep.c:23
struct sweeper::@220272220222261246232307276064033320167134062222 limit
unsigned * depths
Definition sweep.c:22
unsigneds partition
Definition sweep.c:32
unsigned first
Definition sweep.c:25
unsigned * next
Definition sweep.c:24
unsigned * prev
Definition sweep.c:24
unsigned depth
Definition sweep.c:36
unsigned encoded
Definition sweep.c:26
kissat * solver
Definition sweep.c:21
uint64_t ticks
Definition sweep.c:35
unsigned clauses
Definition sweep.c:36
unsigneds vars
Definition sweep.c:28
#define LOGPARTITION(MESSAGE)
Definition sweep.c:472
bool kissat_sweep(kissat *solver)
Definition sweep.c:1650
#define LOGBACKBONE(MESSAGE)
Definition sweep.c:468
#define RANK_SWEEP_CANDIDATE(CAND)
#define TERMINATED(BIT)
Definition terminate.h:42
#define sweep_terminated_5
Definition terminate.h:74
#define sweep_terminated_2
Definition terminate.h:71
#define sweep_terminated_6
Definition terminate.h:75
#define sweep_terminated_4
Definition terminate.h:73
#define sweep_terminated_1
Definition terminate.h:70
#define sweep_terminated_7
Definition terminate.h:76
#define sweep_terminated_3
Definition terminate.h:72
#define sweep_terminated_8
Definition terminate.h:77
Definition watch.h:41
unsigned raw
Definition watch.h:46
large_watch large
Definition watch.h:45
watch_type type
Definition watch.h:42
binary_watch binary
Definition watch.h:43
char * memset()
#define SWAP(TYPE, A, B)
Definition utilities.h:151
#define VALUE(LIT)
Definition value.h:10
void kissat_connect_irredundant_large_clauses(kissat *solver)
Definition watch.c:171
void kissat_substitute_large_watch(kissat *solver, watches *watches, watch src, watch dst)
Definition watch.c:83
#define SIZE_WATCHES(W)
Definition watch.h:104
#define BEGIN_WATCHES(WS)
Definition watch.h:115
#define PUSH_WATCHES(W, E)
Definition watch.h:106
#define END_WATCHES(WS)
Definition watch.h:118
#define SET_END_OF_WATCHES(WS, P)
Definition watch.h:128
vector watches
Definition watch.h:49
#define all_binary_large_watches(WATCH, WATCHES)
Definition watch.h:158
#define WATCHES(LIT)
Definition watch.h:137