ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_sweep.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
10 : internal (i), random (internal->opts.seed) {
11 random += internal->stats.sweep; // different seed every time
12 internal->init_sweeper (*this);
13}
14
16 // this is already called actively
17 // internal->release_sweeper (this);
18 return;
19}
20
21#define INVALID64 INT64_MAX
22#define INVALID UINT_MAX
23
25 START (sweepsolve);
27 stats.sweep_solved++;
28 int res = cadical_kitten_solve (citten);
29 if (res == 10)
30 stats.sweep_sat++;
31 if (res == 20)
32 stats.sweep_unsat++;
33 STOP (sweepsolve);
34 return res;
35}
36
38 START (sweepflip);
40 STOP (sweepflip);
41 return res;
42}
43
45 START (sweepimplicant);
47 STOP (sweepimplicant);
48 return res;
49}
50
52 uint64_t remaining = 0;
53 const uint64_t current = sweeper.current_ticks;
54 if (current < sweeper.limit.ticks)
55 remaining = sweeper.limit.ticks - current;
56 LOG ("'cadical_kitten_ticks' remaining %" PRIu64, remaining);
58}
59
61 if (c->redundant)
62 return;
63 for (const auto &lit : *c) {
64 noccs (lit)--;
65 }
66}
67
69 if (c->garbage)
70 return false;
71 if (!c->redundant)
72 return true;
73 return c->size == 2; // && !c->hyper; // could ignore hyper
74}
75
76// essentially do full occurence list as in elim.cpp
79
80 init_noccs ();
81
82 // mark satisfied irredundant clauses as garbage
83 for (const auto &c : clauses) {
84 if (!can_sweep_clause (c))
85 continue;
86 bool satisfied = false;
87 for (const auto &lit : *c) {
88 const signed char tmp = val (lit);
89 if (tmp <= 0)
90 continue;
91 if (tmp > 0) {
92 satisfied = true;
93 break;
94 }
95 }
96 if (satisfied)
97 mark_garbage (c); // forces more precise counts
98 else {
99 for (const auto &lit : *c)
100 noccs (lit)++;
101 }
102 }
103
104 init_occs ();
105
106 // Connect irredundant clauses.
107 //
108 for (const auto &c : clauses) {
109 if (!c->garbage) {
110 for (const auto &lit : *c)
111 if (active (lit))
112 occs (lit).push_back (c);
113 } else if (c->size == 2) {
114 if (!c->flushed) {
115 if (proof) {
116 c->flushed = true;
117 proof->delete_clause (c);
118 }
119 }
120 }
121 }
122}
123
124// go back to two watch scheme
131
132// propagate without watches but full occurence list
134 vector<int> &work = sweeper.propagate;
135 size_t i = 0;
136 uint64_t &ticks = sweeper.current_ticks;
137 while (i < work.size ()) {
138 int lit = work[i++];
139 LOG ("sweeping propagation of %d", lit);
140 CADICAL_assert (val (lit) > 0);
141 ticks += 1 + cache_lines (occs (-lit).size (), sizeof (Clause *));
142 const Occs &ns = occs (-lit);
143 for (const auto &c : ns) {
144 ticks++;
145 if (!can_sweep_clause (c))
146 continue;
147 int unit = 0, satisfied = 0;
148 for (const auto &other : *c) {
149 const signed char tmp = val (other);
150 if (tmp < 0)
151 continue;
152 if (tmp > 0) {
153 satisfied = other;
154 break;
155 }
156 if (unit)
157 unit = INT_MIN;
158 else
159 unit = other;
160 }
161 if (satisfied) {
162 LOG (c, "sweeping propagation of %d finds %d satisfied", lit,
163 satisfied);
164 mark_garbage (c);
166 } else if (!unit) {
167 LOG ("empty clause during sweeping propagation of %d", lit);
168 // need to set conflict = c for lrat
169 conflict = c;
171 conflict = 0;
172 break;
173 } else if (unit != INT_MIN) {
174 LOG ("new unit %d during sweeping propagation of %d", unit, lit);
175 build_chain_for_units (unit, c, 0);
176 assign_unit (unit);
177 work.push_back (unit);
178 ticks++;
179 }
180 }
181 if (unsat)
182 break;
183
184 // not necessary but should help
185 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
186 const Occs &ps = occs (lit);
187 for (const auto &c : ps) {
188 ticks++;
189 if (c->garbage)
190 continue;
191 // if (c->redundant) // TODO I assume it does not hurt to mark
192 // everything here continue;
193 LOG (c, "sweeping propagation of %d produces satisfied", lit);
194 mark_garbage (c);
196 }
197 }
198 work.clear ();
199}
200
202 const uint64_t current =
204 if (current >= sweeper.limit.ticks) {
205 LOG ("'cadical_kitten_ticks' limit of %" PRIu64 " ticks hit after %" PRIu64
206 " ticks during %s",
207 sweeper.limit.ticks, current, when);
208 return true;
209 }
210#ifndef LOGGING
211 (void) when;
212#endif
213 return false;
214}
215
217 sweeper.encoded = 0;
218 enlarge_zero (sweeper.depths, max_var + 1);
219 sweeper.reprs = new int[2 * max_var + 1];
221 enlarge_zero (sweeper.prev, max_var + 1);
222 enlarge_zero (sweeper.next, max_var + 1);
223 for (const auto &lit : lits)
224 sweeper.reprs[lit] = lit;
226 sweeper.current_ticks =
227 2 *
228 clauses
229 .size (); // initialize with the cost of building full occ list.
230 sweeper.current_ticks +=
231 2 + 2 * cache_lines (clauses.size (), sizeof (Clause *));
235
236 sweep_dense_mode_and_watch_irredundant (); // full occurence list
237
238 if (lrat) {
239 sweeper.prev_units.push_back (0);
240 for (const auto &idx : vars) {
241 sweeper.prev_units.push_back (val (idx) != 0);
242 }
243 }
244
245 unsigned completed = stats.sweep_completed;
246 const unsigned max_completed = 32;
247 if (completed > max_completed)
248 completed = max_completed;
249
250 uint64_t vars_limit = opts.sweepvars;
251 vars_limit <<= completed;
252 const unsigned max_vars_limit = opts.sweepmaxvars;
253 if (vars_limit > max_vars_limit)
254 vars_limit = max_vars_limit;
255 sweeper.limit.vars = vars_limit;
256 VERBOSE (3, "sweeper variable limit %u", sweeper.limit.vars);
257
258 uint64_t depth_limit = stats.sweep_completed;
259 depth_limit += opts.sweepdepth;
260 const unsigned max_depth = opts.sweepmaxdepth;
261 if (depth_limit > max_depth)
262 depth_limit = max_depth;
263 sweeper.limit.depth = depth_limit;
264 VERBOSE (3, "sweeper depth limit %u", sweeper.limit.depth);
265
266 uint64_t clause_limit = opts.sweepclauses;
267 clause_limit <<= completed;
268 const unsigned max_clause_limit = opts.sweepmaxclauses;
269 if (clause_limit > max_clause_limit)
270 clause_limit = max_clause_limit;
271 sweeper.limit.clauses = clause_limit;
272 VERBOSE (3, "sweeper clause limit %u", sweeper.limit.clauses);
273}
274
276
278 delete[] sweeper.reprs;
279
287 erase_vector (sweeper.prev_units);
288 for (unsigned i = 0; i < 2; i++)
290
292 citten = 0;
293 stats.ticks.sweep += sweeper.current_ticks;
295 return;
296}
297
299 LOG ("clearing sweeping environment");
301
303 for (auto &idx : sweeper.vars) {
305 sweeper.depths[idx] = 0;
306 }
307 sweeper.vars.clear ();
308 for (auto c : sweeper.clauses) {
309 CADICAL_assert (c->swept);
310 c->swept = false;
311 }
312 sweeper.clauses.clear ();
313 sweeper.backbone.clear ();
314 sweeper.partition.clear ();
315 sweeper.encoded = 0;
317}
318
320 int res;
321 {
322 int prev = lit;
323 while ((res = sweeper.reprs[prev]) != prev)
324 prev = res;
325 }
326 if (res == lit)
327 return res;
328 LOG ("sweeping repr[%d] = %d", lit, res);
329 {
330 const int not_res = -res;
331 int next, prev = lit;
332 while ((next = sweeper.reprs[prev]) != res) {
333 const int not_prev = -prev;
334 sweeper.reprs[not_prev] = not_res;
335 sweeper.reprs[prev] = res;
336 prev = next;
337 }
338 CADICAL_assert (sweeper.reprs[-prev] == not_res);
339 }
340 return res;
341}
342
344 int lit) {
345 const int repr = sweep_repr (sweeper, lit);
346 if (repr != lit)
347 return;
348 const int idx = abs (lit);
349 if (sweeper.depths[idx])
350 return;
351 CADICAL_assert (depth < UINT_MAX);
352 sweeper.depths[idx] = depth + 1;
353 CADICAL_assert (idx);
354 sweeper.vars.push_back (idx);
355 LOG ("sweeping[%u] adding literal %d", depth, lit);
356}
357
359 // TODO: CADICAL_assertion fails, check if this an issue or can be avoided
360 // CADICAL_assert (sweeper.clause.size () > 1);
361 for (const auto &lit : sweeper.clause)
364 sweeper.clause.size (), sweeper.clause.data ());
365 sweeper.clause.clear ();
366 if (opts.sweepcountbinary || sweeper.clause.size () > 2)
368}
369
370void Internal::sweep_clause (Sweeper &sweeper, unsigned depth, Clause *c) {
371 if (c->swept)
372 return;
374 LOG (c, "sweeping[%u]", depth);
375 CADICAL_assert (sweeper.clause.empty ());
376 for (const auto &lit : *c) {
377 const signed char tmp = val (lit);
378 if (tmp > 0) {
379 mark_garbage (c);
381 sweeper.clause.clear ();
382 return;
383 }
384 if (tmp < 0) {
385 if (lrat)
386 sweeper.prev_units[abs (lit)] = true;
387 continue;
388 }
389 sweeper.clause.push_back (lit);
390 }
391 c->swept = true;
392 sweep_add_clause (sweeper, depth);
393 sweeper.clauses.push_back (c);
394}
395
396extern "C" {
397static void save_core_clause (void *state, unsigned id, bool learned,
398 size_t size, const unsigned *lits) {
399 Sweeper *sweeper = (Sweeper *) state;
400 Internal *internal = sweeper->internal;
401 if (internal->unsat)
402 return;
405 if (learned) {
406 pc.sweep_id = INVALID; // necessary
407 pc.cad_id = INVALID64; // delay giving ids
408 } else {
409 pc.sweep_id = id; // necessary
410 CADICAL_assert (id < sweeper->clauses.size ());
411 pc.cad_id = sweeper->clauses[id]->id;
412 }
413 pc.kit_id = 0;
414 pc.learned = learned;
415 const unsigned *end = lits + size;
416 for (const unsigned *p = lits; p != end; p++) {
417 pc.literals.push_back (internal->citten2lit (*p)); // conversion
418 }
419#ifdef LOGGING
420 LOG (pc.literals, "traced %s",
421 pc.learned == true ? "learned" : "original");
422#endif
423 core.push_back (pc);
424}
425
426static void save_core_clause_with_lrat (void *state, unsigned cid,
427 unsigned id, bool learned,
428 size_t size, const unsigned *lits,
429 size_t chain_size,
430 const unsigned *chain) {
431 Sweeper *sweeper = (Sweeper *) state;
432 Internal *internal = sweeper->internal;
433 if (internal->unsat)
434 return;
436 vector<Clause *> &clauses = sweeper->clauses;
438 pc.kit_id = cid;
439 pc.learned = learned;
440 pc.sweep_id = INVALID;
441 pc.cad_id = INVALID64;
442 if (!learned) {
443 CADICAL_assert (size);
444 CADICAL_assert (!chain_size);
445 CADICAL_assert (id < clauses.size ());
446 pc.sweep_id = id;
447 CADICAL_assert (id < clauses.size ());
448 pc.cad_id = clauses[id]->id;
449 for (const auto &lit : *clauses[id]) {
450 pc.literals.push_back (lit);
451 }
452 } else {
453 CADICAL_assert (chain_size);
454 pc.sweep_id = INVALID;
455 pc.cad_id = INVALID64; // delay giving ids
456 const unsigned *end = lits + size;
457 for (const unsigned *p = lits; p != end; p++) {
458 pc.literals.push_back (internal->citten2lit (*p)); // conversion
459 }
460 for (const unsigned *p = chain + chain_size; p != chain; p--) {
461 pc.chain.push_back (*(p - 1));
462 }
463 }
464#ifdef LOGGING
465 if (learned)
466 LOG (pc.literals, "traced %s",
467 pc.learned == true ? "learned" : "original");
468 else {
469 CADICAL_assert (id < clauses.size ());
470 LOG (clauses[id], "traced");
471 }
472#endif
473 core.push_back (pc);
474}
475
476static int citten_terminate (void *data) {
477 return ((Internal *) data)->terminated_asynchronously ();
478}
479
480} // end extern C
481
486 if (external->terminator)
487 cadical_kitten_set_terminator (citten, internal, citten_terminate);
488#ifdef LOGGING
489 if (opts.log)
490 cadical_kitten_set_logging (citten);
491#endif
492}
493
494void Internal::add_core (Sweeper &sweeper, unsigned core_idx) {
495 if (unsat)
496 return;
497 LOG ("check and add extracted core[%u] lemmas to proof", core_idx);
498 CADICAL_assert (core_idx == 0 || core_idx == 1);
499 vector<sweep_proof_clause> &core = sweeper.core[core_idx];
500
502
503 unsigned unsat_size = 0;
504 for (auto &pc : core) {
505 unsat_size++;
506
507 if (!pc.learned) {
508 LOG (pc.literals,
509 "not adding already present core[%u] cadical_kitten[%u] clause",
510 core_idx, pc.kit_id);
511 continue;
512 }
513
514 LOG (pc.literals, "adding extracted core[%u] cadical_kitten[%u] lemma",
515 core_idx, pc.kit_id);
516
517 const unsigned new_size = pc.literals.size ();
518
519 if (lrat) {
520 CADICAL_assert (pc.cad_id == INVALID64);
521 for (auto &cid : pc.chain) {
522 int64_t id = 0;
523 for (const auto &cpc : core) {
524 if (cpc.kit_id == cid) {
525 if (cpc.learned)
526 id = cpc.cad_id;
527 else {
528 id = cpc.cad_id;
529 CADICAL_assert (cpc.cad_id == sweeper.clauses[cpc.sweep_id]->id);
530 CADICAL_assert (!sweeper.clauses[cpc.sweep_id]->garbage);
531 // avoid duplicate ids of units with seen flags
532 for (const auto &lit : cpc.literals) {
533 if (val (lit) >= 0)
534 continue;
535 if (flags (lit).seen)
536 continue;
537 const int idx = abs (lit);
538 if (sweeper.prev_units[idx]) {
539 int64_t uid = unit_id (-lit);
540 lrat_chain.push_back (uid);
541 analyzed.push_back (lit);
542 flags (lit).seen = true;
543 }
544 }
545 }
546 break;
547 }
548 }
549 CADICAL_assert (id);
550 if (id != INVALID64)
551 lrat_chain.push_back (id);
552 }
554 }
555
556 if (!new_size) {
557 LOG ("sweeping produced empty clause");
559 core.resize (unsat_size);
560 return;
561 }
562
563 if (new_size == 1) {
564 int unit = pc.literals[0];
565 if (val (unit) > 0) {
566 LOG ("already assigned sweeping unit %d", unit);
567 lrat_chain.clear ();
568 } else if (val (unit) < 0) {
569 LOG ("falsified sweeping unit %d leads to empty clause", unit);
570 if (lrat) {
571 int64_t id = unit_id (-unit);
572 lrat_chain.push_back (id);
573 }
575 core.resize (unsat_size);
576 return;
577 } else {
578 LOG ("sweeping produced unit %d", unit);
579 assign_unit (unit);
580 stats.sweep_units++;
581 sweeper.propagate.push_back (unit);
582 }
583 if (proof && lrat)
584 pc.cad_id = unit_id (unit);
585 continue;
586 }
587
588 CADICAL_assert (new_size > 1);
589 CADICAL_assert (pc.learned);
590
591 if (proof) {
592 pc.cad_id = ++clause_id;
593 proof->add_derived_clause (pc.cad_id, true, pc.literals, lrat_chain);
594 lrat_chain.clear ();
595 }
596 }
597}
598
599void Internal::save_core (Sweeper &sweeper, unsigned core) {
600 LOG ("saving extracted core[%u] lemmas", core);
601 CADICAL_assert (core == 0 || core == 1);
602 CADICAL_assert (sweeper.core[core].empty ());
603 sweeper.save = core;
605 if (lrat)
606 cadical_kitten_trace_core (citten, &sweeper, save_core_clause_with_lrat);
607 else
609 save_core_clause);
610}
611
612void Internal::clear_core (Sweeper &sweeper, unsigned core_idx) {
613 CADICAL_assert (core_idx == 0 || core_idx == 1);
614 LOG ("clearing core[%u] lemmas", core_idx);
615 vector<sweep_proof_clause> &core = sweeper.core[core_idx];
616 if (proof) {
617 LOG ("deleting sub-solver core clauses");
618 for (auto &pc : core) {
619 if (pc.learned && pc.literals.size () > 1)
620 proof->delete_clause (pc.cad_id, true, pc.literals);
621 }
622 }
623 core.clear ();
624}
625
631
633 LOG ("initializing backbone and equivalent literals candidates");
634 sweeper.backbone.clear ();
635 sweeper.partition.clear ();
636 for (const auto &idx : sweeper.vars) {
637 if (!active (idx))
638 continue;
639 CADICAL_assert (idx > 0);
640 const int lit = idx;
641 const int not_lit = -lit;
642 const signed char tmp = cadical_kitten_signed_value (citten, lit);
643 const int candidate = (tmp < 0) ? not_lit : lit;
644 LOG ("sweeping candidate %d", candidate);
645 sweeper.backbone.push_back (candidate);
646 sweeper.partition.push_back (candidate);
647 }
648 sweeper.partition.push_back (0);
649
650 LOG (sweeper.backbone, "initialized backbone candidates");
651 LOG (sweeper.partition, "initialized equivalence candidates");
652}
653
659
661 LOG ("refining partition");
662 vector<int> &old_partition = sweeper.partition;
663 vector<int> new_partition;
664 auto old_begin = old_partition.begin ();
665 const auto old_end = old_partition.end ();
666#ifdef LOGGING
667 unsigned old_classes = 0;
668 unsigned new_classes = 0;
669#endif
670 for (auto p = old_begin, q = p; p != old_end; p = q + 1) {
671 unsigned assigned_true = 0;
672 int other;
673 for (q = p; (other = *q) != 0; q++) {
674 if (sweep_repr (sweeper, other) != other)
675 continue;
676 if (val (other))
677 continue;
678 signed char value = cadical_kitten_signed_value (citten, other);
679 if (!value)
680 LOG ("dropping sub-solver unassigned %d", other);
681 else if (value > 0) {
682 new_partition.push_back (other);
683 assigned_true++;
684 }
685 }
686#ifdef LOGGING
687 LOG ("refining class %u of size %zu", old_classes, (size_t) (q - p));
688 old_classes++;
689#endif
690 if (assigned_true == 0)
691 LOG ("no positive literal in class");
692 else if (assigned_true == 1) {
693#ifdef LOGGING
694 other =
695#else
696 (void)
697#endif
698 new_partition.back ();
699 new_partition.pop_back ();
700 LOG ("dropping singleton class %d", other);
701 } else {
702 LOG ("%u positive literal in class", assigned_true);
703 new_partition.push_back (0);
704#ifdef LOGGING
705 new_classes++;
706#endif
707 }
708
709 unsigned assigned_false = 0;
710 for (q = p; (other = *q) != 0; q++) {
711 if (sweep_repr (sweeper, other) != other)
712 continue;
713 if (val (other))
714 continue;
715 signed char value = cadical_kitten_signed_value (citten, other);
716 if (value < 0) {
717 new_partition.push_back (other);
718 assigned_false++;
719 }
720 }
721
722 if (assigned_false == 0)
723 LOG ("no negative literal in class");
724 else if (assigned_false == 1) {
725#ifdef LOGGING
726 other =
727#else
728 (void)
729#endif
730 new_partition.back ();
731 new_partition.pop_back ();
732 LOG ("dropping singleton class %d", other);
733 } else {
734 LOG ("%u negative literal in class", assigned_false);
735 new_partition.push_back (0);
736#ifdef LOGGING
737 new_classes++;
738#endif
739 }
740 }
741 old_partition.swap (new_partition);
742 LOG ("refined %u classes into %u", old_classes, new_classes);
743}
744
746 LOG ("refining backbone candidates");
747 const auto end = sweeper.backbone.end ();
748 auto q = sweeper.backbone.begin ();
749 for (auto p = q; p != end; p++) {
750 const int lit = *p;
751 if (val (lit))
752 continue;
754 if (!value)
755 LOG ("dropping sub-solver unassigned %d", lit);
756 else if (value > 0)
757 *q++ = lit;
758 }
759 sweeper.backbone.resize (q - sweeper.backbone.begin ());
760}
761
764 if (sweeper.backbone.empty ())
765 LOG ("no need to refine empty backbone candidates");
766 else
768 if (sweeper.partition.empty ())
769 LOG ("no need to refine empty partition candidates");
770 else
772}
773
775 const unsigned max_rounds = opts.sweepfliprounds;
776 if (!max_rounds)
777 return;
779 if (cadical_kitten_status (citten) != 10)
780 return;
781#ifdef LOGGING
782 unsigned total_flipped = 0;
783#endif
784 unsigned flipped, round = 0;
785 do {
786 round++;
787 flipped = 0;
788 bool refine = false;
789 auto begin = sweeper.backbone.begin (), q = begin, p = q;
790 const auto end = sweeper.backbone.end ();
791 bool limit_hit = false;
792 while (p != end) {
793 const int lit = *p++;
794 stats.sweep_flip_backbone++;
795 if (limit_hit || terminated_asynchronously ()) {
796 break;
797 } else if (sweep_flip (lit)) {
798 LOG ("flipping backbone candidate %d succeeded", lit);
799#ifdef LOGGING
800 total_flipped++;
801#endif
802 stats.sweep_flipped_backbone++;
803 flipped++;
804 } else {
805 LOG ("flipping backbone candidate %d failed", lit);
806 *q++ = lit;
807 }
808 }
809 while (p != end)
810 *q++ = *p++;
811 sweeper.backbone.resize (q - sweeper.backbone.begin ());
812 LOG ("flipped %u backbone candidates in round %u", flipped, round);
813
814 if (limit_hit)
815 break;
817 break;
818 if (cadical_kitten_ticks_limit_hit (sweeper, "backbone flipping"))
819 break;
820 if (refine)
822 } while (flipped && round < max_rounds);
823 LOG ("flipped %u backbone candidates in total in %u rounds",
824 total_flipped, round);
825}
826
828 const int not_lit = -lit;
829 stats.sweep_solved_backbone++;
831 int res = sweep_solve ();
832 if (!res) {
833 stats.sweep_unknown_backbone++;
834 return false;
835 }
836 CADICAL_assert (res == 20);
837 LOG ("sweep unit %d", lit);
839 stats.sweep_unsat_backbone++;
840 return true;
841}
842
844 LOG ("trying backbone candidate %d", lit);
846 if (value) {
847 stats.sweep_fixed_backbone++;
848 CADICAL_assert (value > 0);
849 if (val (lit) <= 0) {
851 } else
852 LOG ("literal %d already fixed", lit);
853 return false;
854 }
855
856 int res = cadical_kitten_status (citten);
857 if (res != 10) {
858 LOG ("not flipping due to status %d != 10", res);
859 }
860 stats.sweep_flip_backbone++;
861 if (res == 10 && sweep_flip (lit)) {
862 stats.sweep_flipped_backbone++;
863 LOG ("flipping %d succeeded", lit);
864 // LOGBACKBONE ("refined backbone candidates");
865 return false;
866 }
867
868 LOG ("flipping %d failed", lit);
869 const int not_lit = -lit;
870 stats.sweep_solved_backbone++;
872 res = sweep_solve ();
873 if (res == 10) {
874 LOG ("sweeping backbone candidate %d failed", lit);
876 stats.sweep_sat_backbone++;
877 return false;
878 }
879
880 if (res == 20) {
881 LOG ("sweep unit %d", lit);
884 stats.sweep_unsat_backbone++;
885 return true;
886 }
887
888 stats.sweep_unknown_backbone++;
889
890 LOG ("sweeping backbone candidate %d failed", lit);
891 return false;
892}
893
894// at this point the binary (lit or other) is already present
895// in the proof via 'add_core'.
896// We just copy it as an irredundant clause, call weaken minus
897// and push it on the extension stack.
898//
900 int other) {
902 if (unsat)
903 return 0; // sanity check, should be fuzzed
904
905 CADICAL_assert (!val (lit) && !val (other));
906 if (val (lit) || val (other))
907 return 0;
908
909 if (lrat) {
910 for (const auto &plit : pc.literals) {
911 if (val (plit)) {
912 int64_t id = unit_id (-plit);
913 lrat_chain.push_back (id);
914 }
915 }
916 lrat_chain.push_back (pc.cad_id);
917 }
918 clause.push_back (lit);
919 clause.push_back (other);
920 const int64_t id = ++clause_id;
921 if (proof) {
922 proof->add_derived_clause (id, false, clause, lrat_chain);
923 proof->weaken_minus (id, clause);
924 }
925 external->push_binary_clause_on_extension_stack (id, lit, other);
926 clause.clear ();
927 lrat_chain.clear ();
928 return id;
929}
930
932 if (unsat)
933 return;
934 if (!proof)
935 return;
936 vector<int> bin;
937 bin.push_back (sb.lit);
938 bin.push_back (sb.other);
939 proof->delete_clause (sb.id, false, bin);
940}
941
943 return sweeper.prev[idx] != 0 || sweeper.first == idx;
944}
945
947 CADICAL_assert (idx);
948 if (!active (idx))
949 return;
950 const int next = sweeper.next[idx];
951 if (next != 0) {
952 LOG ("rescheduling inner %d as last", idx);
953 const unsigned prev = sweeper.prev[idx];
954 CADICAL_assert (sweeper.prev[next] == idx);
955 sweeper.prev[next] = prev;
956 if (prev == 0) {
958 sweeper.first = next;
959 } else {
960 CADICAL_assert (sweeper.next[prev] == idx);
961 sweeper.next[prev] = next;
962 }
963 const unsigned last = sweeper.last;
964 if (last == 0) {
966 sweeper.first = idx;
967 } else {
969 sweeper.next[last] = idx;
970 }
971 sweeper.prev[idx] = last;
972 sweeper.next[idx] = 0;
973 sweeper.last = idx;
974 } else if (sweeper.last != idx) {
975 LOG ("scheduling inner %d as last", idx);
976 const unsigned last = sweeper.last;
977 if (last == 0) {
979 sweeper.first = idx;
980 } else {
982 sweeper.next[last] = idx;
983 }
984 CADICAL_assert (sweeper.next[idx] == 0);
985 sweeper.prev[idx] = last;
986 sweeper.last = idx;
987 } else
988 LOG ("keeping inner %d scheduled as last", idx);
989}
990
993 CADICAL_assert (active (idx));
994 const int first = sweeper.first;
995 if (first == 0) {
997 sweeper.last = idx;
998 } else {
999 CADICAL_assert (sweeper.prev[first] == 0);
1000 sweeper.prev[first] = idx;
1001 }
1002 CADICAL_assert (sweeper.prev[idx] == 0);
1003 sweeper.next[idx] = first;
1004 sweeper.first = idx;
1005 LOG ("scheduling outer %d as first", idx);
1006}
1007
1009 int res = sweeper.last;
1010 if (res == 0) {
1011 LOG ("no more scheduled variables left");
1012 return 0;
1013 }
1014 CADICAL_assert (res > 0);
1015 LOG ("dequeuing next scheduled %d", res);
1016 const unsigned prev = sweeper.prev[res];
1017 CADICAL_assert (sweeper.next[res] == 0);
1018 sweeper.prev[res] = 0;
1019 if (prev == 0) {
1020 CADICAL_assert (sweeper.first == res);
1021 sweeper.first = 0;
1022 } else {
1023 CADICAL_assert (sweeper.next[prev] == res);
1024 sweeper.next[prev] = 0;
1025 }
1026 sweeper.last = prev;
1027 return res;
1028}
1029
1031 if (!lrat)
1032 return;
1033 for (const auto &lit : *c) {
1034 CADICAL_assert (val (lit) <= 0);
1035 if (val (lit) < 0) {
1036 int64_t id = unit_id (-lit);
1037 lrat_chain.push_back (id);
1038 }
1039 }
1040 lrat_chain.push_back (id);
1041 lrat_chain.push_back (c->id);
1042}
1043
1044#define all_scheduled(IDX) \
1045 int IDX = sweeper.first, NEXT_##IDX; \
1046 IDX != 0 && (NEXT_##IDX = sweeper.next[IDX], true); \
1047 IDX = NEXT_##IDX
1048
1049// Substitute equivalences in clauses (see
1050// 'sweep_substitute_new_equivalences' for explanation)
1052 int repr, int64_t id) {
1053 if (unsat)
1054 return;
1055 if (val (lit))
1056 return;
1057 if (val (repr))
1058 return;
1059 LOG ("substituting %d with %d in all irredundant clauses", lit, repr);
1060
1061 CADICAL_assert (lit != repr);
1062 CADICAL_assert (lit != -repr);
1063
1065 CADICAL_assert (active (repr));
1066
1067 uint64_t &ticks = sweeper.current_ticks;
1068
1069 {
1070 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
1071 Occs &ns = occs (lit);
1072 auto const begin = ns.begin ();
1073 const auto end = ns.end ();
1074 auto q = begin;
1075 auto p = q;
1076 while (p != end) {
1077 Clause *c = *q++ = *p++;
1078 ticks++;
1079 if (c->garbage)
1080 continue;
1081 CADICAL_assert (clause.empty ());
1082 bool satisfied = false;
1083 bool repr_already_watched = false;
1084 const int not_repr = -repr;
1085#ifndef CADICAL_NDEBUG
1086 bool found = false;
1087#endif
1088 for (const auto &other : *c) {
1089 if (other == lit) {
1090#ifndef CADICAL_NDEBUG
1091 CADICAL_assert (!found);
1092 found = true;
1093#endif
1094 clause.push_back (repr);
1095 continue;
1096 }
1097 CADICAL_assert (other != -lit);
1098 if (other == repr) {
1099 CADICAL_assert (!repr_already_watched);
1100 repr_already_watched = true;
1101 continue;
1102 }
1103 if (other == not_repr) {
1104 satisfied = true;
1105 break;
1106 }
1107 const signed char tmp = val (other);
1108 if (tmp < 0)
1109 continue;
1110 if (tmp > 0) {
1111 satisfied = true;
1112 break;
1113 }
1114 clause.push_back (other);
1115 }
1116 if (satisfied) {
1117 clause.clear ();
1118 mark_garbage (c);
1120 continue;
1121 }
1122 CADICAL_assert (found);
1123 const unsigned new_size = clause.size ();
1124 sweep_substitute_lrat (c, id);
1125 if (new_size == 0) {
1126 LOG (c, "substituted empty clause");
1129 break;
1130 }
1131 ticks++;
1132 if (new_size == 1) {
1133 LOG (c, "reduces to unit");
1134 const int unit = clause[0];
1135 clause.clear ();
1136 assign_unit (unit);
1137 sweeper.propagate.push_back (unit);
1138 mark_garbage (c);
1140 stats.sweep_units++;
1141 break;
1142 }
1143 CADICAL_assert (c->size >= 2);
1144 if (!c->redundant)
1145 mark_removed (c);
1146 uint64_t new_id = ++clause_id;
1147 if (proof) {
1148 proof->add_derived_clause (new_id, c->redundant, clause,
1149 lrat_chain);
1150 proof->delete_clause (c);
1151 }
1152 c->id = new_id;
1153 lrat_chain.clear ();
1154 size_t l;
1155 int *literals = c->literals;
1156 for (l = 0; l < clause.size (); l++)
1157 literals[l] = clause[l];
1158 int flushed = c->size - (int) l;
1159 if (flushed) {
1160 LOG ("flushed %d literals", flushed);
1161 (void) shrink_clause (c, l);
1162 } else if (likely_to_be_kept_clause (c))
1163 mark_added (c);
1164 LOG (c, "substituted");
1165 if (!repr_already_watched) {
1166 occs (repr).push_back (c);
1167 noccs (repr)++;
1168 }
1169 clause.clear ();
1170 q--;
1171 }
1172 while (p != end)
1173 *q++ = *p++;
1174 ns.resize (q - ns.begin ());
1175 }
1176}
1177
1178// In contrast to kissat we substitute the equivalences explicitely after
1179// every successful round of sweeping. This is necessary in order to extract
1180// valid LRAT proofs for subsequent rounds of sweeping.
1182 if (unsat)
1183 return;
1184
1185 unsigned count = 0;
1186 CADICAL_assert (lrat_chain.empty ());
1187
1188 for (const auto &sb : sweeper.binaries) {
1189 count++;
1190 const auto lit = sb.lit;
1191 const auto other = sb.other;
1192 if (abs (lit) < abs (other)) {
1193 substitute_connected_clauses (sweeper, -other, lit, sb.id);
1194 } else {
1195 substitute_connected_clauses (sweeper, -lit, other, sb.id);
1196 }
1197 CADICAL_assert (lrat_chain.empty ());
1198 if (val (lit) < 0) {
1199 if (lrat) {
1200 const int64_t lid = unit_id (-lit);
1201 lrat_chain.push_back (lid);
1202 }
1203 if (!val (other)) {
1204 if (lrat)
1205 lrat_chain.push_back (sb.id);
1206 assign_unit (other);
1207 } else if (val (other) < 0) {
1208 if (lrat) {
1209 const int64_t oid = unit_id (-other);
1210 lrat_chain.push_back (oid);
1211 lrat_chain.push_back (sb.id);
1212 }
1214 return;
1215 }
1216 } else if (val (other) < 0) {
1217 if (!val (lit)) {
1218 if (lrat) {
1219 const int64_t oid = unit_id (-other);
1220 lrat_chain.push_back (oid);
1221 lrat_chain.push_back (sb.id);
1222 }
1223 assign_unit (lit);
1224 } else
1225 CADICAL_assert (val (lit) > 0);
1226 }
1227 lrat_chain.clear ();
1229 if (count == 2) {
1230 if (!val (lit) && !val (other)) {
1231 const auto idx = abs (lit) < abs (other) ? abs (other) : abs (lit);
1232 if (!flags (idx).fixed ())
1233 mark_substituted (idx);
1234 }
1235 count = 0;
1236 }
1237 CADICAL_assert (lrat_chain.empty ());
1238 }
1239 sweeper.binaries.clear ();
1240}
1241
1244 vector<int> &partition = sweeper.partition;
1245 const auto begin_partition = partition.begin ();
1246 auto p = begin_partition;
1247 const auto end_partition = partition.end ();
1248 for (; *p != lit; p++)
1249 CADICAL_assert (p + 1 != end_partition);
1250 auto begin_class = p;
1251 while (begin_class != begin_partition && begin_class[-1] != 0)
1252 begin_class--;
1253 auto end_class = p;
1254 while (*end_class != 0)
1255 end_class++;
1256 const unsigned size = end_class - begin_class;
1257 LOG ("removing non-representative %d from equivalence class of size %u",
1258 lit, size);
1259 CADICAL_assert (size > 1);
1260 auto q = begin_class;
1261 if (size == 2) {
1262 LOG ("completely squashing equivalence class of %d", lit);
1263 for (auto r = end_class + 1; r != end_partition; r++)
1264 *q++ = *r;
1265 } else {
1266 for (auto r = begin_class; r != end_partition; r++)
1267 if (r != p)
1268 *q++ = *r;
1269 }
1270 partition.resize (q - partition.begin ());
1271}
1272
1274 const unsigned max_rounds = opts.sweepfliprounds;
1275 if (!max_rounds)
1276 return;
1278 if (cadical_kitten_status (citten) != 10)
1279 return;
1280#ifdef LOGGING
1281 unsigned total_flipped = 0;
1282#endif
1283 unsigned flipped, round = 0;
1284 do {
1285 round++;
1286 flipped = 0;
1287 bool refine = false;
1288 bool limit_hit = false;
1289 auto begin = sweeper.partition.begin (), dst = begin, src = dst;
1290 const auto end = sweeper.partition.end ();
1291 while (src != end) {
1292 auto end_src = src;
1293 while (CADICAL_assert (end_src != end), *end_src != 0)
1294 end_src++;
1295 unsigned size = end_src - src;
1296 CADICAL_assert (size > 1);
1297 auto q = dst;
1298 for (auto p = src; p != end_src; p++) {
1299 const int lit = *p;
1300 if (limit_hit) {
1301 *q++ = lit;
1302 continue;
1303 } else if (cadical_kitten_ticks_limit_hit (sweeper, "partition flipping")) {
1304 *q++ = lit;
1305 limit_hit = true;
1306 continue;
1307 } else if (sweep_flip (lit)) {
1308 LOG ("flipping equivalence candidate %d succeeded", lit);
1309#ifdef LOGGING
1310 total_flipped++;
1311#endif
1312 flipped++;
1313 if (--size < 2)
1314 break;
1315 } else {
1316 LOG ("flipping equivalence candidate %d failed", lit);
1317 *q++ = lit;
1318 }
1319 stats.sweep_flip_equivalences++;
1320 }
1321 if (size > 1) {
1322 *q++ = 0;
1323 dst = q;
1324 }
1325 src = end_src + 1;
1326 }
1327 stats.sweep_flipped_equivalences += flipped;
1328 sweeper.partition.resize (dst - sweeper.partition.begin ());
1329 LOG ("flipped %u equivalence candidates in round %u", flipped, round);
1331 break;
1332 if (cadical_kitten_ticks_limit_hit (sweeper, "partition flipping"))
1333 break;
1334 if (refine)
1336 } while (flipped && round < max_rounds);
1337 LOG ("flipped %u equivalence candidates in total in %u rounds",
1338 total_flipped, round);
1339}
1340
1342 int other) {
1343 LOG ("trying equivalence candidates %d = %d", lit, other);
1344 const auto begin = sweeper.partition.begin ();
1345 auto const end = sweeper.partition.end ();
1346 CADICAL_assert (begin + 3 <= end);
1347 CADICAL_assert (end[-3] == lit);
1348 CADICAL_assert (end[-2] == other);
1349 const int third = (end - begin == 3) ? 0 : end[-4];
1350 int res = cadical_kitten_status (citten);
1351 if (res == 10) {
1352 stats.sweep_flip_equivalences++;
1353 if (sweep_flip (lit)) {
1354 stats.sweep_flipped_equivalences++;
1355 LOG ("flipping %d succeeded", lit);
1356 if (third == 0) {
1357 LOG ("squashing equivalence class of %d", lit);
1358 sweeper.partition.resize (sweeper.partition.size () - 3);
1359 } else {
1360 LOG ("removing %d from equivalence class of %d", lit, other);
1361 end[-3] = other;
1362 end[-2] = 0;
1363 sweeper.partition.resize (sweeper.partition.size () - 1);
1364 }
1365 return false;
1366 }
1367 stats.sweep_flip_equivalences++;
1368 if (sweep_flip (other)) {
1369 stats.sweep_flipped_equivalences++;
1370 LOG ("flipping %d succeeded", other);
1371 if (third == 0) {
1372 LOG ("squashing equivalence class of %d", lit);
1373 sweeper.partition.resize (sweeper.partition.size () - 3);
1374 } else {
1375 LOG ("removing %d from equivalence class of %d", other, lit);
1376 end[-2] = 0;
1377 sweeper.partition.resize (sweeper.partition.size () - 1);
1378 }
1379 return false;
1380 }
1381 }
1382 // frozen variables are not allowed to be eliminated.
1383 // It might still be beneficial to learn the binaries, if they
1384 // really are equivalent, but we avoid the issue by not trying
1385 // for equivalence at all if the non-representative is frozen.
1386 // i.e., the higher absolute value
1387 if (abs (lit) > abs (other) && frozen (lit)) {
1388 if (third == 0) {
1389 LOG ("squashing equivalence class of %d", lit);
1390 sweeper.partition.resize (sweeper.partition.size () - 3);
1391 } else {
1392 LOG ("removing %d from equivalence class of %d", lit, other);
1393 end[-3] = other;
1394 end[-2] = 0;
1395 sweeper.partition.resize (sweeper.partition.size () - 1);
1396 }
1397 return false;
1398 } else if (abs (other) > abs (lit) && frozen (other)) {
1399 if (third == 0) {
1400 LOG ("squashing equivalence class of %d", lit);
1401 sweeper.partition.resize (sweeper.partition.size () - 3);
1402 } else {
1403 LOG ("removing %d from equivalence class of %d", lit, other);
1404 end[-2] = 0;
1405 sweeper.partition.resize (sweeper.partition.size () - 1);
1406 }
1407 return false;
1408 }
1409
1410 const int not_other = -other;
1411 const int not_lit = -lit;
1412 LOG ("flipping %d and %d both failed", lit, other);
1415 stats.sweep_solved_equivalences++;
1416 res = sweep_solve ();
1417 if (res == 10) {
1418 stats.sweep_sat_equivalences++;
1419 LOG ("first sweeping implication %d -> %d failed", other, lit);
1421 } else if (!res) {
1422 stats.sweep_unknown_equivalences++;
1423 LOG ("first sweeping implication %d -> %d hit ticks limit", other, lit);
1424 }
1425
1426 if (res != 20)
1427 return false;
1428
1429 stats.sweep_unsat_equivalences++;
1430 LOG ("first sweeping implication %d -> %d succeeded", other, lit);
1431
1432 save_core (sweeper, 0);
1433
1436 res = sweep_solve ();
1437 stats.sweep_solved_equivalences++;
1438 if (res == 10) {
1439 stats.sweep_sat_equivalences++;
1440 LOG ("second sweeping implication %d <- %d failed", other, lit);
1442 } else if (!res) {
1443 stats.sweep_unknown_equivalences++;
1444 LOG ("second sweeping implication %d <- %d hit ticks limit", other,
1445 lit);
1446 }
1447
1448 if (res != 20) {
1449 sweeper.core[0].clear ();
1450 return false;
1451 }
1452
1453 CADICAL_assert (res == 20);
1454
1455 stats.sweep_unsat_equivalences++;
1456 LOG ("second sweeping implication %d <- %d succeeded too", other, lit);
1457
1458 save_core (sweeper, 1);
1459
1460 LOG ("sweep equivalence %d = %d", lit, other);
1461
1462 // If cadical_kitten behaves as expected, the two binaries of the equivalence
1463 // should be stored at sweeper.core[i].back () for i in {0, 1}.
1464 // We pick the smaller absolute valued literal as representative and
1465 // store the equivalence .
1466 add_core (sweeper, 0);
1467 add_core (sweeper, 1);
1468 if (!val (lit) && !val (other)) {
1469 CADICAL_assert (sweeper.core[0].size ());
1470 CADICAL_assert (sweeper.core[1].size ());
1471 stats.sweep_equivalences++;
1472 sweep_binary bin1;
1473 sweep_binary bin2;
1474 if (abs (lit) > abs (other)) {
1475 bin1.lit = lit;
1476 bin1.other = not_other;
1477 bin2.lit = not_lit;
1478 bin2.other = other;
1479 bin1.id = add_sweep_binary (sweeper.core[0].back (), lit, not_other);
1480 bin2.id = add_sweep_binary (sweeper.core[1].back (), not_lit, other);
1481 } else {
1482 bin1.lit = not_other;
1483 bin1.other = lit;
1484 bin2.lit = other;
1485 bin2.other = not_lit;
1486 bin1.id = add_sweep_binary (sweeper.core[0].back (), not_other, lit);
1487 bin2.id = add_sweep_binary (sweeper.core[1].back (), other, not_lit);
1488 }
1489 if (bin1.id && bin2.id) {
1490 sweeper.binaries.push_back (bin1);
1491 sweeper.binaries.push_back (bin2);
1492 }
1493 }
1494
1495 int repr;
1496 if (abs (lit) < abs (other)) {
1497 repr = sweeper.reprs[other] = lit;
1498 sweeper.reprs[not_other] = not_lit;
1499 sweep_remove (sweeper, other);
1500 } else {
1501 repr = sweeper.reprs[lit] = other;
1502 sweeper.reprs[not_lit] = not_other;
1504 }
1505 clear_core (sweeper, 0);
1506 clear_core (sweeper, 1);
1507
1508 const int repr_idx = abs (repr);
1509 schedule_inner (sweeper, repr_idx);
1510
1511 return true;
1512}
1513
1516 if (!active (idx))
1517 return "inactive variable";
1518 const int start = idx;
1519 if (sweeper.reprs[start] != start)
1520 return "non-representative variable";
1521 CADICAL_assert (sweeper.vars.empty ());
1522 CADICAL_assert (sweeper.clauses.empty ());
1523 CADICAL_assert (sweeper.backbone.empty ());
1524 CADICAL_assert (sweeper.partition.empty ());
1526
1527 stats.sweep_variables++;
1528
1529 LOG ("sweeping %d", idx);
1530 CADICAL_assert (!val (start));
1531 LOG ("starting sweeping[0]");
1533 LOG ("finished sweeping[0]");
1534 LOG ("starting sweeping[1]");
1535
1536 bool limit_reached = false;
1537 size_t expand = 0, next = 1;
1538 bool success = false;
1539 unsigned depth = 1;
1540
1541 uint64_t &ticks = sweeper.current_ticks;
1542 while (!limit_reached) {
1544 LOG ("environment clause limit reached");
1545 limit_reached = true;
1546 break;
1547 }
1548 if (expand == next) {
1549 LOG ("finished sweeping[%u]", depth);
1550 if (depth >= sweeper.limit.depth) {
1551 LOG ("environment depth limit reached");
1552 break;
1553 }
1554 next = sweeper.vars.size ();
1555 if (expand == next) {
1556 LOG ("completely copied all clauses");
1557 break;
1558 }
1559 depth++;
1560 LOG ("starting sweeping[%u]", depth);
1561 }
1562 const unsigned choices = next - expand;
1563 if (opts.sweeprand && choices > 1) {
1564 const unsigned swaps = sweeper.random.pick_int (0, choices - 1);
1565 if (swaps) {
1566 CADICAL_assert (expand + swaps < sweeper.vars.size ());
1567 swap (sweeper.vars[expand], sweeper.vars[expand + swaps]);
1568 }
1569 }
1570 const int idx = sweeper.vars[expand];
1571 LOG ("traversing and adding clauses of %d", idx);
1572 for (unsigned sign = 0; sign < 2; sign++) {
1573 const int lit = sign ? -idx : idx;
1574 ticks += 1 + cache_lines (occs (lit).size (), sizeof (Clause *));
1575 Occs &ns = occs (lit);
1576 for (auto c : ns) {
1577 ticks++;
1578 if (!can_sweep_clause (c))
1579 continue;
1580 sweep_clause (sweeper, depth, c);
1581 if (sweeper.vars.size () >= sweeper.limit.vars) {
1582 LOG ("environment variable limit reached");
1583 limit_reached = true;
1584 break;
1585 }
1586 }
1587 if (limit_reached)
1588 break;
1589 }
1590 expand++;
1591 }
1592 stats.sweep_depth += depth;
1593 stats.sweep_clauses += sweeper.encoded;
1594 stats.sweep_environment += sweeper.vars.size ();
1595 VERBOSE (3,
1596 "sweeping variable %d environment of "
1597 "%zu variables %u clauses depth %u",
1598 externalize (idx), sweeper.vars.size (), sweeper.encoded, depth);
1599
1600 int res;
1601 if (sweeper.vars.size () == 1) {
1602 LOG ("not sweeping literal %d with environment size 1", idx);
1603 goto DONE;
1604 }
1605 res = sweep_solve ();
1606 LOG ("sub-solver returns '%d'", res);
1607 if (res == 10) {
1609#ifndef CADICAL_QUIET
1610 uint64_t units = stats.sweep_units;
1611 uint64_t solved = stats.sweep_solved;
1612#endif
1613 START (sweepbackbone);
1614 while (sweeper.backbone.size ()) {
1615 if (unsat || terminated_asynchronously () ||
1616 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1617 limit_reached = true;
1618 STOP_SWEEP_BACKBONE:
1619 STOP (sweepbackbone);
1620 goto DONE;
1621 }
1624 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1625 limit_reached = true;
1626 goto STOP_SWEEP_BACKBONE;
1627 }
1628 if (sweeper.backbone.empty ())
1629 break;
1630 const int lit = sweeper.backbone.back ();
1631 sweeper.backbone.pop_back ();
1632 if (!active (lit))
1633 continue;
1635 success = true;
1636 }
1637 STOP (sweepbackbone);
1638#ifndef CADICAL_QUIET
1639 units = stats.sweep_units - units;
1640 solved = stats.sweep_solved - solved;
1641#endif
1642 VERBOSE (3,
1643 "complete swept variable %d backbone with %" PRIu64
1644 " units in %" PRIu64 " solver calls",
1645 externalize (idx), units, solved);
1646 CADICAL_assert (sweeper.backbone.empty ());
1647#ifndef CADICAL_QUIET
1648 uint64_t equivalences = stats.sweep_equivalences;
1649 solved = stats.sweep_solved;
1650#endif
1651 START (sweepequivalences);
1652 while (sweeper.partition.size ()) {
1653 if (unsat || terminated_asynchronously () ||
1654 cadical_kitten_ticks_limit_hit (sweeper, "partition refinement")) {
1655 limit_reached = true;
1656 STOP_SWEEP_EQUIVALENCES:
1657 STOP (sweepequivalences);
1658 goto DONE;
1659 }
1662 cadical_kitten_ticks_limit_hit (sweeper, "backbone refinement")) {
1663 limit_reached = true;
1664 goto STOP_SWEEP_EQUIVALENCES;
1665 }
1666 if (sweeper.partition.empty ())
1667 break;
1668 if (sweeper.partition.size () > 2) {
1669 const auto end = sweeper.partition.end ();
1670 CADICAL_assert (end[-1] == 0);
1671 int lit = end[-3];
1672 int other = end[-2];
1674 success = true;
1675 } else
1676 sweeper.partition.clear ();
1677 }
1678 STOP (sweepequivalences);
1679#ifndef CADICAL_QUIET
1680 equivalences = stats.sweep_equivalences - equivalences;
1681 solved = stats.sweep_solved - solved;
1682 if (equivalences)
1683 VERBOSE (3,
1684 "complete swept variable %d partition with %" PRIu64
1685 " equivalences in %" PRIu64 " solver calls",
1686 externalize (idx), equivalences, solved);
1687#endif
1688 } else if (res == 20)
1690
1691DONE:
1693
1694 if (!unsat)
1696 if (!unsat)
1698
1699 if (success && limit_reached)
1700 return "successfully despite reaching limit";
1701 if (!success && !limit_reached)
1702 return "unsuccessfully without reaching limit";
1703 else if (success && !limit_reached)
1704 return "successfully without reaching limit";
1705 CADICAL_assert (!success && limit_reached);
1706 return "unsuccessfully and reached limit";
1707}
1708
1710 unsigned rank;
1711 int idx;
1712};
1713
1716 CADICAL_assert (a.rank && b.rank);
1717 CADICAL_assert (a.idx > 0 && b.idx > 0);
1718 if (a.rank < b.rank)
1719 return true;
1720 if (b.rank < a.rank)
1721 return false;
1722 return a.idx < b.idx;
1723 }
1724};
1725
1727 size_t *occ_ptr) {
1728 const int lit = idx;
1729 const size_t pos = noccs (lit);
1730 if (!pos)
1731 return false;
1732 const unsigned max_occurrences = sweeper.limit.clauses;
1733 if (pos > max_occurrences)
1734 return false;
1735 const int not_lit = -lit;
1736 const size_t neg = noccs (not_lit);
1737 if (!neg)
1738 return false;
1739 if (neg > max_occurrences)
1740 return false;
1741 *occ_ptr = pos + neg;
1742 return true;
1743}
1744
1747 for (const auto &idx : vars) {
1748 Flags &f = flags (idx);
1749 if (!f.active ())
1750 continue;
1751 if (sweep_incomplete && !f.sweep)
1752 continue;
1753 if (scheduled_variable (sweeper, idx))
1754 continue;
1755 size_t occ;
1756 if (!scheduable_variable (sweeper, idx, &occ)) {
1757 f.sweep = false;
1758 continue;
1759 }
1760 sweep_candidate cand;
1761 cand.rank = occ;
1762 cand.idx = idx;
1763 fresh.push_back (cand);
1764 }
1765 const size_t size = fresh.size ();
1766 CADICAL_assert (size <= UINT_MAX);
1767 sort (fresh.begin (), fresh.end (), rank_sweep_candidate ());
1768 for (auto &cand : fresh)
1769 schedule_outer (sweeper, cand.idx);
1770 return size;
1771}
1772
1774 unsigned rescheduled = 0;
1775 for (const auto &idx : sweep_schedule) {
1776 Flags &f = flags (idx);
1777 if (!f.active ())
1778 continue;
1779 if (scheduled_variable (sweeper, idx))
1780 continue;
1781 size_t occ;
1782 if (!scheduable_variable (sweeper, idx, &occ)) {
1783 f.sweep = false;
1784 continue;
1785 }
1786 schedule_inner (sweeper, idx);
1787 rescheduled++;
1788 }
1789 sweep_schedule.clear ();
1790 return rescheduled;
1791}
1792
1794 unsigned res = 0;
1795 for (const auto &idx : vars) {
1796 Flags &f = flags (idx);
1797 if (!f.active ())
1798 continue;
1799 if (f.sweep)
1800 res++;
1801 }
1802 return res;
1803}
1804
1806 unsigned marked = 0;
1807 for (all_scheduled (idx)) {
1808 if (!flags (idx).sweep) {
1809 flags (idx).sweep = true;
1810 marked++;
1811 }
1812 }
1813 sweep_incomplete = true;
1814#ifndef CADICAL_QUIET
1815 VERBOSE (2, "marked %u scheduled sweeping variables as incomplete",
1816 marked);
1817#else
1818 (void) marked;
1819#endif
1820}
1821
1823 const unsigned rescheduled = reschedule_previously_remaining (sweeper);
1824 const unsigned fresh = schedule_all_other_not_scheduled_yet (sweeper);
1825 const unsigned scheduled = fresh + rescheduled;
1826 const unsigned incomplete = incomplete_variables ();
1827#ifndef CADICAL_QUIET
1828 PHASE ("sweep", stats.sweep,
1829 "scheduled %u variables %.0f%% "
1830 "(%u rescheduled %.0f%%, %u incomplete %.0f%%)",
1831 scheduled, percent (scheduled, active ()), rescheduled,
1832 percent (rescheduled, scheduled), incomplete,
1833 percent (incomplete, scheduled));
1834#endif
1835 if (incomplete)
1837 else {
1838 if (sweep_incomplete)
1839 stats.sweep_completed++;
1841 }
1842 return scheduled;
1843}
1844
1846 unsigned scheduled) {
1847#ifdef CADICAL_QUIET
1848 (void) scheduled, (void) swept;
1849#endif
1850 CADICAL_assert (sweep_schedule.empty ());
1852 for (all_scheduled (idx))
1853 if (active (idx)) {
1854 sweep_schedule.push_back (idx);
1855 LOG ("untried scheduled %d", idx);
1856 }
1857#ifndef CADICAL_QUIET
1858 const unsigned retained = sweep_schedule.size ();
1859#endif
1860 VERBOSE (3, "retained %u variables %.0f%% to be swept next time",
1861 retained, percent (retained, active ()));
1862 const unsigned incomplete = incomplete_variables ();
1863 if (incomplete)
1864 VERBOSE (3, "need to sweep %u more variables %.0f%% for completion",
1865 incomplete, percent (incomplete, active ()));
1866 else {
1867 VERBOSE (3, "no more variables needed to complete sweep");
1868 sweep_incomplete = false;
1869 stats.sweep_completed++;
1870 }
1871 PHASE ("sweep", stats.sweep, "swept %u variables (%u remain %.0f%%)",
1872 swept, incomplete, percent (incomplete, scheduled));
1873}
1874
1876 if (!opts.sweep)
1877 return false;
1878 if (unsat)
1879 return false;
1881 return false;
1882 if (delaying_sweep.bumpreasons.delay ()) { // TODO need to fix Delay
1883 last.sweep.ticks = stats.ticks.search[0] + stats.ticks.search[1];
1884 return false;
1885 }
1886 delaying_sweep.bumpreasons.bypass_delay ();
1887 SET_EFFORT_LIMIT (tickslimit, sweep, !opts.sweepcomplete);
1888 delaying_sweep.bumpreasons.unbypass_delay ();
1889
1892 stats.sweep++;
1893 uint64_t equivalences = stats.sweep_equivalences;
1894 uint64_t units = stats.sweep_units;
1895 Sweeper sweeper = Sweeper (this);
1896 if (opts.sweepcomplete)
1897 sweeper.limit.ticks = INT64_MAX;
1898 else
1899 sweeper.limit.ticks = tickslimit - stats.ticks.sweep;
1901 const unsigned scheduled = schedule_sweeping (sweeper);
1902 uint64_t swept = 0, limit = 10;
1903 for (;;) {
1904 if (unsat)
1905 break;
1907 break;
1908 if (cadical_kitten_ticks_limit_hit (sweeper, "sweeping loop"))
1909 break;
1910 int idx = next_scheduled (sweeper);
1911 if (idx == 0)
1912 break;
1913 flags (idx).sweep = false;
1914#ifndef CADICAL_QUIET
1915 const char *res =
1916#endif
1917 sweep_variable (sweeper, idx);
1918 VERBOSE (2, "swept[%" PRIu64 "] external variable %d %s", swept,
1919 externalize (idx), res);
1920 if (++swept == limit) {
1921 VERBOSE (2,
1922 "found %" PRIu64 " equivalences and %" PRIu64
1923 " units after sweeping %" PRIu64 " variables ",
1924 stats.sweep_equivalences - equivalences,
1925 stats.sweep_units - units, swept);
1926 limit *= 10;
1927 }
1928 }
1929 VERBOSE (2, "swept %" PRIu64 " variables", swept);
1930 equivalences = stats.sweep_equivalences - equivalences,
1931 units = stats.sweep_units - units;
1932 PHASE ("sweep", stats.sweep,
1933 "found %" PRIu64 " equivalences and %" PRIu64 " units",
1934 equivalences, units);
1935 unschedule_sweeping (sweeper, swept, scheduled);
1937
1938 if (!unsat) {
1939 propagated = 0;
1940 if (!propagate ()) {
1942 }
1943 }
1944
1945 uint64_t eliminated = equivalences + units;
1946 report ('=', !eliminated);
1947
1948 if (relative (eliminated, swept) < 0.001) {
1949 delaying_sweep.bumpreasons.bump_delay ();
1950 } else {
1951 delaying_sweep.bumpreasons.reduce_delay ();
1952 }
1954 return eliminated;
1955}
1956
1957} // namespace CaDiCaL
1958
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
void cadical_kitten_assume_signed(cadical_kitten *cadical_kitten, int elit)
void cadical_kitten_traverse_core_clauses_with_id(cadical_kitten *cadical_kitten, void *state, void(*traverse)(void *state, unsigned, bool learned, size_t, const unsigned *))
unsigned cadical_kitten_compute_clausal_core(cadical_kitten *cadical_kitten, uint64_t *learned_ptr)
cadical_kitten * cadical_kitten_init(void)
#define LOG(...)
int cadical_kitten_flip_and_implicant_for_signed_literal(cadical_kitten *cadical_kitten, int elit)
uint64_t cadical_kitten_current_ticks(cadical_kitten *cadical_kitten)
void cadical_kitten_set_ticks_limit(cadical_kitten *cadical_kitten, uint64_t delta)
ABC_NAMESPACE_IMPL_START typedef signed char value
signed char cadical_kitten_signed_value(cadical_kitten *cadical_kitten, int selit)
int cadical_kitten_solve(cadical_kitten *cadical_kitten)
void cadical_kitten_trace_core(cadical_kitten *cadical_kitten, void *state, void(*trace)(void *, unsigned, unsigned, bool, size_t, const unsigned *, size_t, const unsigned *))
void cadical_kitten_set_terminator(cadical_kitten *cadical_kitten, void *data, int(*terminator)(void *))
void cadical_kitten_clear(cadical_kitten *cadical_kitten)
void citten_clause_with_id(cadical_kitten *cadical_kitten, unsigned id, size_t size, int *elits)
void cadical_kitten_randomize_phases(cadical_kitten *cadical_kitten)
int cadical_kitten_status(cadical_kitten *cadical_kitten)
bool cadical_kitten_flip_signed_literal(cadical_kitten *cadical_kitten, int elit)
void cadical_kitten_release(cadical_kitten *cadical_kitten)
signed char cadical_kitten_fixed_signed(cadical_kitten *cadical_kitten, int elit)
void cadical_kitten_track_antecedents(cadical_kitten *cadical_kitten)
#define all_scheduled(IDX)
#define INVALID64
pcover expand()
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
@ DONE
Definition inflate.h:51
#define SET_EFFORT_LIMIT(LIMIT, NAME, THRESHHOLD)
Definition limit.hpp:131
#define PHASE(...)
Definition message.hpp:52
#define VERBOSE(...)
Definition message.hpp:58
int sign(int lit)
Definition util.hpp:22
double relative(double a, double b)
Definition util.hpp:20
vector< Clause * > Occs
Definition occs.hpp:18
const char * flags()
void erase_vector(std::vector< T > &v)
Definition util.hpp:90
double percent(double a, double b)
Definition util.hpp:21
unsigned long long size
Definition giaNewBdd.h:39
#define STOP(P)
Definition profile.hpp:158
#define START_SIMPLIFIER(S, M)
Definition profile.hpp:172
#define STOP_SIMPLIFIER(S, M)
Definition profile.hpp:197
#define START(P)
Definition profile.hpp:150
int lit
Definition satVec.h:130
bool active() const
Definition flags.hpp:69
void citten_clear_track_log_terminate()
void save_add_clear_core(Sweeper &sweeper)
External * external
Definition internal.hpp:312
int64_t cache_lines(size_t bytes)
Definition internal.hpp:722
unsigned schedule_all_other_not_scheduled_yet(Sweeper &sweeper)
void sweep_dense_propagate(Sweeper &sweeper)
void unschedule_sweeping(Sweeper &sweeper, unsigned swept, unsigned scheduled)
vector< int > analyzed
Definition internal.hpp:267
void sweep_refine(Sweeper &sweeper)
int next_scheduled(Sweeper &sweeper)
void sweep_update_noccs(Clause *c)
unsigned incomplete_variables()
void add_literal_to_environment(Sweeper &sweeper, unsigned depth, int)
void sweep_substitute_lrat(Clause *c, int64_t id)
unsigned reschedule_previously_remaining(Sweeper &sweeper)
void mark_garbage(Clause *)
vector< int64_t > lrat_chain
Definition internal.hpp:210
cadical_kitten * citten
Definition internal.hpp:277
bool scheduled_variable(Sweeper &sweeper, int idx)
void report(char type, int verbose_level=0)
bool cadical_kitten_ticks_limit_hit(Sweeper &sweeper, const char *when)
void sweep_add_clause(Sweeper &sweeper, unsigned depth)
void sweep_remove(Sweeper &sweeper, int lit)
Flags & flags(int lit)
Definition internal.hpp:454
int fixed(int lit)
bool terminated_asynchronously(int factor=1)
const Sange lits
Definition internal.hpp:325
void mark_removed(int lit)
unsigned schedule_sweeping(Sweeper &sweeper)
int externalize(int lit)
void sweep_set_cadical_kitten_ticks_limit(Sweeper &sweeper)
bool can_sweep_clause(Clause *c)
void mark_substituted(int)
void schedule_outer(Sweeper &sweeper, int idx)
void clear_sweeper(Sweeper &sweeper)
bool frozen(int lit)
void release_sweeper(Sweeper &sweeper)
const char * sweep_variable(Sweeper &sweeper, int idx)
int sweep_flip_and_implicant(int)
void sweep_empty_clause(Sweeper &sweeper)
void sweep_substitute_new_equivalences(Sweeper &sweeper)
signed char val(int lit) const
bool limit(const char *name, int)
signed char marked(int lit) const
Definition internal.hpp:478
int64_t unit_id(int lit) const
Definition internal.hpp:434
void init_sweeper(Sweeper &sweeper)
vector< int > sweep_schedule
Definition internal.hpp:274
bool sweep_extract_fixed(Sweeper &sweeper, int lit)
bool active(int lit)
Definition internal.hpp:360
void save_core(Sweeper &sweeper, unsigned core)
void sweep_refine_backbone(Sweeper &sweeper)
void sweep_refine_partition(Sweeper &sweeper)
int64_t & noccs(int lit)
Definition internal.hpp:466
void sweep_dense_mode_and_watch_irredundant()
void clear_core(Sweeper &sweeper, unsigned core_idx)
int sweep_repr(Sweeper &sweeper, int lit)
void init_backbone_and_partition(Sweeper &sweeper)
vector< Clause * > clauses
Definition internal.hpp:283
void flip_backbone_literals(struct Sweeper &sweeper)
const Range vars
Definition internal.hpp:324
int64_t add_sweep_binary(sweep_proof_clause, int lit, int other)
void substitute_connected_clauses(Sweeper &sweeper, int lit, int other, int64_t id)
void add_core(Sweeper &sweeper, unsigned core_idx)
bool scheduable_variable(Sweeper &sweeper, int idx, size_t *occ_ptr)
void delete_sweep_binary(const sweep_binary &sb)
Occs & occs(int lit)
Definition internal.hpp:465
Internal * internal
Definition internal.hpp:311
size_t shrink_clause(Clause *, int new_size)
int citten2lit(unsigned ulit)
Definition internal.hpp:421
void schedule_inner(Sweeper &sweeper, int idx)
void sweep_clause(Sweeper &sweeper, unsigned depth, Clause *)
void mark_added(int lit, int size, bool redundant)
void flip_partition_literals(struct Sweeper &sweeper)
bool likely_to_be_kept_clause(Clause *c)
bool sweep_backbone_candidate(Sweeper &sweeper, int lit)
bool sweep_equivalence_candidates(Sweeper &sweeper, int lit, int other)
void build_chain_for_units(int lit, Clause *reason, bool forced)
void mark_incomplete(Sweeper &sweeper)
vector< int > clause
Definition internal.hpp:260
void connect_watches(bool irredundant_only=false)
Random random
Definition sweep.hpp:37
Sweeper(Internal *internal)
Internal * internal
Definition sweep.hpp:36
bool operator()(sweep_candidate a, sweep_candidate b) const
vector< int > literals
Definition sweep.hpp:17
unsigneds clause
Definition sweep.c:30
unsigneds backbone
Definition sweep.c:31
unsigneds core[2]
Definition sweep.c:33
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
uint64_t ticks
Definition sweep.c:35
unsigned clauses
Definition sweep.c:36
unsigneds vars
Definition sweep.c:28
unsigned size
Definition vector.h:35
struct sweeper sweeper
Definition sweep.c:40
struct vector vector
Definition vector.h:24