ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_internal.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9/*------------------------------------------------------------------------*/
10static Clause external_reason_clause;
11
19
20 private_steps (false), rephased (0), vsize (0), max_var (0),
23 level (0), vals (0), score_inc (1.0), scores (this), conflict (0),
24 ignore (0), external_reason (&external_reason_clause),
31 num_assigned (0), proof (0), opts (this),
32#ifndef CADICAL_QUIET
33 profiles (this), force_phase_messages (false),
34#endif
35 arena (this), prefix ("c "), internal (this), external (0),
37 lits (this->max_var) {
38 control.push_back (Level (0, 0));
39
40 // The 'dummy_binary' is used in 'try_to_subsume_clause' to fake a real
41 // clause, which then can be used to subsume or strengthen the given
42 // clause in one routine for both binary and non binary clauses. This
43 // fake binary clause is always kept non-redundant (and not-moved etc.)
44 // due to the following 'memset'. Only literals will be changed.
45
46 // In a previous version we used local automatic allocated 'Clause' on the
47 // stack, which became incompatible with several compilers (see the
48 // discussion on flexible array member in 'Clause.cpp').
49
50 size_t bytes = Clause::bytes (2);
51 dummy_binary = (Clause *) new char[bytes];
52 memset (dummy_binary, 0, bytes);
53 dummy_binary->size = 2;
54}
55
57 // If a memory exception ocurred a profile might still be active.
58#ifndef CADICAL_QUIET
59#define PROFILE(NAME, LEVEL) \
60 if (PROFILE_ACTIVE (NAME)) \
61 STOP (NAME);
62 PROFILES
63#undef PROFILE
64#endif
65 delete[] (char *) dummy_binary;
66 for (const auto &c : clauses)
67 delete_clause (c);
68 if (proof)
69 delete proof;
70 for (auto &tracer : tracers)
71 delete tracer;
72 for (auto &filetracer : file_tracers)
73 delete filetracer;
74 for (auto &stattracer : stat_tracers)
75 delete stattracer;
76 if (vals) {
77 vals -= vsize;
78 delete[] vals;
79 }
80}
81
82/*------------------------------------------------------------------------*/
83
84// Values in 'vals' can be accessed in the range '[-max_var,max_var]' that
85// is directly by a literal. This is crucial for performance. By shifting
86// the start of 'vals' appropriately, we achieve that negative offsets from
87// the start of 'vals' can be used. We also need to set both values at
88// 'lit' and '-lit' during assignments. In MiniSAT integer literals are
89// encoded, using the least significant bit as negation. This avoids taking
90// the 'abs ()' (as in our solution) and thus also avoids a branch in the
91// hot-spot of the solver (clause traversal in propagation). That solution
92// requires another (branch less) negation of the values though and
93// debugging is harder since literals occur only encoded in clauses.
94// The main draw-back of our solution is that we have to shift the memory
95// and access it through negative indices, which looks less clean (but still
96// as far I can tell is properly defined C / C++). You might get a warning
97// by static analyzers though. Clang with '--analyze' thought that this
98// idiom would generate a memory leak thus we use the following dummy.
99
100static signed char *ignore_clang_analyze_memory_leak_warning;
101
102void Internal::enlarge_vals (size_t new_vsize) {
103 signed char *new_vals;
104 const size_t bytes = 2u * new_vsize;
105 new_vals = new signed char[bytes]; // g++-4.8 does not like ... { 0 };
106 memset (new_vals, 0, bytes);
107 ignore_clang_analyze_memory_leak_warning = new_vals;
108 new_vals += new_vsize;
109
110 if (vals) {
111 memcpy (new_vals - max_var, vals - max_var, 2u * max_var + 1u);
112 vals -= vsize;
113 delete[] vals;
114 } else
116 vals = new_vals;
117}
118
119/*------------------------------------------------------------------------*/
120
121void Internal::enlarge (int new_max_var) {
122 // New variables can be created that can invoke enlarge anytime (via calls
123 // during ipasir-up call-backs), thus assuming (!level) is not correct
124 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
125 while (new_vsize <= (size_t) new_max_var)
126 new_vsize *= 2;
127 LOG ("enlarge internal size from %zd to new size %zd", vsize, new_vsize);
128 // Ordered in the size of allocated memory (larger block first).
129 if (lrat || frat)
130 enlarge_zero (unit_clauses_idx, 2 * new_vsize);
131 enlarge_only (wtab, 2 * new_vsize);
132 enlarge_only (vtab, new_vsize);
133 enlarge_zero (parents, new_vsize);
134 enlarge_only (links, new_vsize);
135 enlarge_zero (btab, new_vsize);
136 enlarge_zero (gtab, new_vsize);
137 enlarge_zero (stab, new_vsize);
138 enlarge_init (ptab, 2 * new_vsize, -1);
139 enlarge_only (ftab, new_vsize);
140 enlarge_vals (new_vsize);
141 vsize = new_vsize;
142 if (external)
143 enlarge_zero (relevanttab, new_vsize);
144 const signed char val = opts.phase ? 1 : -1;
145 enlarge_init (phases.saved, new_vsize, val);
146 enlarge_zero (phases.forced, new_vsize);
147 enlarge_zero (phases.target, new_vsize);
148 enlarge_zero (phases.best, new_vsize);
149 enlarge_zero (phases.prev, new_vsize);
150 enlarge_zero (phases.min, new_vsize);
151 enlarge_zero (marks, new_vsize);
152}
153
154void Internal::init_vars (int new_max_var) {
155 if (new_max_var <= max_var)
156 return;
157 // New variables can be created that can invoke enlarge anytime (via calls
158 // during ipasir-up call-backs), thus assuming (!level) is not correct
159 LOG ("initializing %d internal variables from %d to %d",
160 new_max_var - max_var, max_var + 1, new_max_var);
161 if ((size_t) new_max_var >= vsize)
162 enlarge (new_max_var);
163#ifndef CADICAL_NDEBUG
164 for (int64_t i = -new_max_var; i < -max_var; i++)
165 CADICAL_assert (!vals[i]);
166 for (unsigned i = max_var + 1; i <= (unsigned) new_max_var; i++)
168 for (uint64_t i = 2 * ((uint64_t) max_var + 1);
169 i <= 2 * (uint64_t) new_max_var + 1; i++)
170 CADICAL_assert (ptab[i] == -1);
171#endif
172 CADICAL_assert (!btab[0]);
173 int old_max_var = max_var;
174 max_var = new_max_var;
175 init_queue (old_max_var, new_max_var);
176 init_scores (old_max_var, new_max_var);
177 int initialized = new_max_var - old_max_var;
178 stats.vars += initialized;
179 stats.unused += initialized;
180 stats.inactive += initialized;
181 LOG ("finished initializing %d internal variables", initialized);
182}
183
185 CADICAL_assert (abs (lit) <= max_var);
186 if (lit) {
187 original.push_back (lit);
188 } else {
189 const int64_t id =
191 if (proof) {
192 // Use the external form of the clause for printing in proof
193 // Externalize(internalized literal) != external literal
194 CADICAL_assert (!original.size () || !external->eclause.empty ());
195 proof->add_external_original_clause (id, false, external->eclause);
196 }
197 if (internal->opts.check &&
198 (internal->opts.checkwitness || internal->opts.checkfailed)) {
199 bool forgettable = from_propagator && ext_clause_forgettable;
200 if (forgettable && opts.check) {
201 CADICAL_assert (!original.size () || !external->eclause.empty ());
202
203 // First integer is the presence-flag (even if the clause is empty)
204 external->forgettable_original[id] = {1};
205
206 for (auto const &elit : external->eclause)
207 external->forgettable_original[id].push_back (elit);
208
209 LOG (external->eclause,
210 "clause added to external forgettable map:");
211 }
212 }
213
215 original.clear ();
216 }
217}
218
219void Internal::finish_added_clause_with_id (int64_t id, bool restore) {
220 if (proof) {
221 // Use the external form of the clause for printing in proof
222 // Externalize(internalized literal) != external literal
223 CADICAL_assert (!original.size () || !external->eclause.empty ());
224 proof->add_external_original_clause (id, false, external->eclause,
225 restore);
226 }
228 original.clear ();
229}
230
231/*------------------------------------------------------------------------*/
232
233void Internal::reserve_ids (int number) {
234 // return;
235 LOG ("reserving %d ids", number);
236 CADICAL_assert (number >= 0);
238 clause_id = reserved_ids = number;
239 if (proof)
240 proof->begin_proof (reserved_ids);
241}
242
243/*------------------------------------------------------------------------*/
244
245#ifdef PROFILE_MODE
246
247// Separating these makes it easier to profile stable and unstable search.
248
249bool Internal::propagate_wrapper () {
250 if (stable)
251 return propagate_stable ();
252 else
253 return propagate_unstable ();
254}
255
256void Internal::analyze_wrapper () {
257 if (stable)
258 analyze_stable ();
259 else
260 analyze_unstable ();
261}
262
263int Internal::decide_wrapper () {
264 if (stable)
265 return decide_stable ();
266 else
267 return decide_unstable ();
268}
269
270#endif
271
272/*------------------------------------------------------------------------*/
273
274// This is the main CDCL loop with interleaved inprocessing.
275
277
278 int res = 0;
279
280 START (search);
281
282 if (stable) {
283 START (stable);
284 report ('[');
285 } else {
286 START (unstable);
287 report ('{');
288 }
289
290 while (!res) {
291 if (unsat)
292 res = 20;
293 else if (unsat_constraint)
294 res = 20;
295 else if (!propagate_wrapper ())
296 analyze_wrapper (); // propagate and analyze
297 else if (iterating)
298 iterate (); // report learned unit
299 else if (!external_propagate () || unsat) { // external propagation
300 if (unsat)
301 continue;
302 else
303 analyze ();
304 } else if (satisfied ()) { // found model
305 if (!external_check_solution () || unsat) {
306 if (unsat)
307 continue;
308 else
309 analyze ();
310 } else if (satisfied ())
311 res = 10;
312 } else if (search_limits_hit ())
313 break; // decision or conflict limit
314 else if (terminated_asynchronously ()) // externally terminated
315 break;
316 else if (restarting ())
317 restart (); // restart by backtracking
318 else if (rephasing ())
319 rephase (); // reset variable phases
320 else if (reducing ())
321 reduce (); // collect useless clauses
322 else if (inprobing ())
323 inprobe (); // schedule of inprocessing
324 else if (ineliminating ())
325 elim (); // variable elimination
326 else if (compacting ())
327 compact (); // collect variables
328 else if (conditioning ())
329 condition (); // globally blocked clauses
330 else
331 res = decide (); // next decision
332 }
333
334 if (stable) {
335 STOP (stable);
336 report (']');
337 } else {
338 STOP (unstable);
339 report ('}');
340 }
341
342 STOP (search);
343
344 return res;
345}
346
348 if (proof)
349 proof->solve_query ();
350 if (opts.ilb) {
351 if (opts.ilbassumptions)
353 stats.ilbtriggers++;
354 stats.ilbsuccess += (level > 0);
355 stats.levelsreused += level;
356 if (level) {
357 CADICAL_assert (control.size () > 1);
358 stats.literalsreused += num_assigned - control[1].trail;
359 }
360 }
363
364 int res = already_solved (); // root-level propagation is done here
365
366 int last_assumption_level = assumptions.size ();
367 if (constraint.size ())
368 last_assumption_level++;
369
370 if (!res) {
372 while (!res) {
373 if (unsat)
374 res = 20;
375 else if (unsat_constraint)
376 res = 20;
377 else if (!propagate ()) {
378 // let analyze run to get failed assumptions
379 analyze ();
380 } else if (!external_propagate () || unsat) { // external propagation
381 if (unsat)
382 continue;
383 else
384 analyze ();
385 } else if (satisfied ()) { // found model
386 if (!external_check_solution () || unsat) {
387 if (unsat)
388 continue;
389 else
390 analyze ();
391 } else if (satisfied ())
392 res = 10;
393 } else if (search_limits_hit ())
394 break; // decision or conflict limit
395 else if (terminated_asynchronously ()) // externally terminated
396 break;
397 else {
398 if (level >= last_assumption_level)
399 break;
400 res = decide ();
401 }
402 }
403 }
404
405 if (unsat || unsat_constraint)
406 res = 20;
407
408 if (!res && satisfied ())
409 res = 10;
410
411 finalize (res);
412 reset_solving ();
413 report_solving (res);
414
415 return res;
416}
417
418void Internal::implied (std::vector<int> &entrailed) {
419 int last_assumption_level = assumptions.size ();
420 if (constraint.size ())
421 last_assumption_level++;
422
423 size_t trail_limit = trail.size();
424 if (level > last_assumption_level)
425 trail_limit = control[last_assumption_level + 1].trail;
426
427 for (size_t i = 0; i < trail_limit; i++)
428 entrailed.push_back (trail[i]);
429}
430
431/*------------------------------------------------------------------------*/
432
433// Most of the limits are only initialized in the first 'solve' call and
434// increased as in a stand-alone non-incremental SAT call except for those
435// explicitly marked as being reset below.
436
438 reported = false;
439 lim.report = 0;
440 lim.recompute_tier = 5000;
441}
442
444
445 const bool incremental = lim.initialized;
446 if (incremental)
447 LOG ("reinitializing preprocessing limits incrementally");
448 else
449 LOG ("initializing preprocessing limits and increments");
450
451 const char *mode = 0;
452
453 /*----------------------------------------------------------------------*/
454
455 if (incremental)
456 mode = "keeping";
457 else {
458 last.elim.marked = -1;
459 lim.elim = stats.conflicts + scale (opts.elimint);
460 mode = "initial";
461 }
462 (void) mode;
463 LOG ("%s elim limit %" PRId64 " after %" PRId64 " conflicts", mode,
464 lim.elim, lim.elim - stats.conflicts);
465
466 // Initialize and reset elimination bounds in any case.
467
468 lim.elimbound = opts.elimboundmin;
469 LOG ("elimination bound %" PRId64 "", lim.elimbound);
470
471 /*----------------------------------------------------------------------*/
472
473 if (!incremental) {
474
475 last.ternary.marked = -1; // TODO this should not be necessary...
476
477 lim.compact = stats.conflicts + opts.compactint;
478 LOG ("initial compact limit %" PRId64 " increment %" PRId64 "",
479 lim.compact, lim.compact - stats.conflicts);
480 }
481
482 /*----------------------------------------------------------------------*/
483
484 if (incremental)
485 mode = "keeping";
486 else {
487 double delta = log10 (stats.added.irredundant);
488 delta = delta * delta;
489 lim.inprobe = stats.conflicts + opts.inprobeint * delta;
490 mode = "initial";
491 }
492 (void) mode;
493 LOG ("%s probe limit %" PRId64 " after %" PRId64 " conflicts", mode,
494 lim.inprobe, lim.inprobe - stats.conflicts);
495
496 /*----------------------------------------------------------------------*/
497
498 if (incremental)
499 mode = "keeping";
500 else {
501 lim.condition = stats.conflicts + opts.conditionint;
502 mode = "initial";
503 }
504 LOG ("%s condition limit %" PRId64 " increment %" PRId64, mode,
505 lim.condition, lim.condition - stats.conflicts);
506
507 /*----------------------------------------------------------------------*/
508
509 // Initial preprocessing rounds.
510
511 if (inc.preprocessing <= 0) {
512 lim.preprocessing = 0;
513 LOG ("no preprocessing");
514 } else {
515 lim.preprocessing = inc.preprocessing;
516 LOG ("limiting to %" PRId64 " preprocessing rounds", lim.preprocessing);
517 }
518}
519
521
522 const bool incremental = lim.initialized;
523 if (incremental)
524 LOG ("reinitializing search limits incrementally");
525 else
526 LOG ("initializing search limits and increments");
527
528 const char *mode = 0;
529
530 /*----------------------------------------------------------------------*/
531
532 if (incremental)
533 mode = "keeping";
534 else {
535 last.reduce.conflicts = -1;
536 lim.reduce = stats.conflicts + opts.reduceinit;
537 mode = "initial";
538 }
539 (void) mode;
540 LOG ("%s reduce limit %" PRId64 " after %" PRId64 " conflicts", mode,
541 lim.reduce, lim.reduce - stats.conflicts);
542
543 /*----------------------------------------------------------------------*/
544
545 if (incremental)
546 mode = "keeping";
547 else {
548 lim.flush = opts.flushint;
549 inc.flush = opts.flushint;
550 mode = "initial";
551 }
552 (void) mode;
553 LOG ("%s flush limit %" PRId64 " interval %" PRId64 "", mode, lim.flush,
554 inc.flush);
555
556 /*----------------------------------------------------------------------*/
557
558 // Initialize or reset 'rephase' limits in any case.
559
560 lim.rephase = stats.conflicts + opts.rephaseint;
561 lim.rephased[0] = lim.rephased[1] = 0;
562 LOG ("new rephase limit %" PRId64 " after %" PRId64 " conflicts",
563 lim.rephase, lim.rephase - stats.conflicts);
564
565 /*----------------------------------------------------------------------*/
566
567 // Initialize or reset 'restart' limits in any case.
568
569 lim.restart = stats.conflicts + opts.restartint;
570 LOG ("new restart limit %" PRId64 " increment %" PRId64 "", lim.restart,
571 lim.restart - stats.conflicts);
572
573 /*----------------------------------------------------------------------*/
574
575 if (!incremental) {
576 stable = opts.stabilize && opts.stabilizeonly;
577 if (stable)
578 LOG ("starting in always forced stable phase");
579 else
580 LOG ("starting in default non-stable phase");
581 init_averages ();
582 } else if (opts.stabilize && opts.stabilizeonly) {
583 LOG ("keeping always forced stable phase");
585 } else if (stable) {
586 LOG ("switching back to default non-stable phase");
587 stable = false;
588 swap_averages ();
589 } else
590 LOG ("keeping non-stable phase");
591
592 if (!incremental) {
593 inc.stabilize = 0;
594 lim.stabilize = stats.conflicts + opts.stabilizeinit;
595 LOG ("initial stabilize limit %" PRId64 " after %d conflicts",
596 lim.stabilize, (int) opts.stabilizeinit);
597 }
598
599 if (opts.stabilize && opts.reluctant) {
600 LOG ("new restart reluctant doubling sequence period %d",
601 opts.reluctant);
602 reluctant.enable (opts.reluctant, opts.reluctantmax);
603 } else
604 reluctant.disable ();
605
606 /*----------------------------------------------------------------------*/
607
608 // Conflict and decision limits.
609
610 if (inc.conflicts < 0) {
611 lim.conflicts = -1;
612 LOG ("no limit on conflicts");
613 } else {
614 lim.conflicts = stats.conflicts + inc.conflicts;
615 LOG ("conflict limit after %" PRId64 " conflicts at %" PRId64
616 " conflicts",
617 inc.conflicts, lim.conflicts);
618 }
619
620 if (inc.decisions < 0) {
621 lim.decisions = -1;
622 LOG ("no limit on decisions");
623 } else {
624 lim.decisions = stats.decisions + inc.decisions;
625 LOG ("conflict limit after %" PRId64 " decisions at %" PRId64
626 " decisions",
627 inc.decisions, lim.decisions);
628 }
629
630 /*----------------------------------------------------------------------*/
631
632 // Initial preprocessing rounds.
633
634 if (inc.localsearch <= 0) {
635 lim.localsearch = 0;
636 LOG ("no local search");
637 } else {
638 lim.localsearch = inc.localsearch;
639 LOG ("limiting to %" PRId64 " local search rounds", lim.localsearch);
640 }
641
642 /*----------------------------------------------------------------------*/
643
644 lim.initialized = true;
645}
646
647/*------------------------------------------------------------------------*/
648
650 (void) round;
651 if (unsat)
652 return false;
653 if (!max_var)
654 return false;
656 struct {
657 int64_t vars, clauses;
658 } before, after;
659 before.vars = active ();
660 before.clauses = stats.current.irredundant;
661 stats.preprocessings++;
663 preprocessing = true;
664 PHASE ("preprocessing", stats.preprocessings,
665 "starting round %d with %" PRId64 " variables and %" PRId64
666 " clauses",
667 round, before.vars, before.clauses);
668 int old_elimbound = lim.elimbound;
669 if (opts.inprobing)
670 inprobe (false);
671 if (opts.elim)
672 elim (false);
673 if (opts.condition)
674 condition (false);
675
676 after.vars = active ();
677 after.clauses = stats.current.irredundant;
679 preprocessing = false;
680 PHASE ("preprocessing", stats.preprocessings,
681 "finished round %d with %" PRId64 " variables and %" PRId64
682 " clauses",
683 round, after.vars, after.clauses);
685 report ('P');
686 if (unsat)
687 return false;
688 if (after.vars < before.vars)
689 return true;
690 if (old_elimbound < lim.elimbound)
691 return true;
692 return false;
693}
694
695// for now counts as one of the preprocessing rounds TODO: change this?
697 if (unsat)
698 return;
699 if (!max_var)
700 return;
701 if (!opts.preprocesslight)
702 return;
704 struct {
705 int64_t vars, clauses;
706 } before, after;
707 before.vars = active ();
708 before.clauses = stats.current.irredundant;
709 // stats.preprocessings++;
711 preprocessing = true;
712 PHASE ("preprocessing", stats.preprocessings,
713 "starting with %" PRId64 " variables and %" PRId64 " clauses",
714 before.vars, before.clauses);
715
716 if (extract_gates ())
717 decompose ();
718
719 if (sweep ())
720 decompose ();
721
722 if (opts.factor)
723 factor ();
724
725 if (opts.fastelim)
726 elimfast ();
727 // if (opts.condition)
728 // condition (false);
729 after.vars = active ();
730 after.clauses = stats.current.irredundant;
732 preprocessing = false;
733 PHASE ("preprocessing", stats.preprocessings,
734 "finished with %" PRId64 " variables and %" PRId64 " clauses",
735 after.vars, after.clauses);
737 report ('P');
738}
739
742 for (int i = 0; i < lim.preprocessing; i++)
743 if (!preprocess_round (i))
744 break;
745 if (unsat)
746 return 20;
747 return 0;
748}
749
750/*------------------------------------------------------------------------*/
751
753 LOG ("satisfying formula by saved phases");
756 CADICAL_assert (propagated == trail.size ());
757 force_saved_phase = true;
758 if (external_prop) {
760 LOG ("external notifications are turned off during preprocessing.");
761 private_steps = true;
762 }
763 int res = 0;
764 while (!res) {
765 if (satisfied ()) {
766 LOG ("formula indeed satisfied by saved phases");
767 res = 10;
768 } else if (decide ()) {
769 LOG ("inconsistent assumptions with redundant clauses and phases");
770 res = 20;
771 } else if (!propagate ()) {
772 LOG ("saved phases do not satisfy redundant clauses");
773 CADICAL_assert (level > 0);
774 backtrack ();
775 conflict = 0; // ignore conflict
776 CADICAL_assert (!res);
777 break;
778 }
779 }
781 force_saved_phase = false;
782 if (external_prop) {
783 private_steps = false;
784 LOG ("external notifications are turned back on.");
785 if (!level)
786 notify_assignments (); // In case fixed assignments were found.
787 else {
789 }
790 }
791 return res;
792}
793
794/*------------------------------------------------------------------------*/
795
797 LOG ("producing failed assumptions");
799 CADICAL_assert (!assumptions.empty ());
800 while (!unsat) {
803 if (decide ())
804 break;
805 while (!unsat && !propagate ())
806 analyze ();
807 }
809 if (unsat)
810 LOG ("formula is actually unsatisfiable unconditionally");
811 else
812 LOG ("assumptions indeed failing");
813}
814
815/*------------------------------------------------------------------------*/
816
818
819 CADICAL_assert (round > 0);
820
821 if (unsat)
822 return false;
823 if (!max_var)
824 return false;
825
828 localsearching = true;
829
830 // Determine propagation limit quadratically scaled with rounds.
831 //
832 int64_t limit = opts.walkmineff;
833 limit *= round;
834 if (LONG_MAX / round > limit)
835 limit *= round;
836 else
837 limit = LONG_MAX;
838
839 int res = walk_round (limit, true);
840
842 localsearching = false;
844
845 report ('L');
846
847 return res;
848}
849
851
852 if (unsat)
853 return 0;
854 if (!max_var)
855 return 0;
856 if (!opts.walk)
857 return 0;
858 if (constraint.size ())
859 return 0;
860
861 int res = 0;
862
863 for (int i = 1; !res && i <= lim.localsearch; i++)
864 res = local_search_round (i);
865
866 if (res == 10) {
867 LOG ("local search determined formula to be satisfiable");
868 CADICAL_assert (!stats.walk.minimum);
870 } else if (res == 20) {
871 LOG ("local search determined assumptions to be inconsistent");
872 CADICAL_assert (!assumptions.empty ());
874 }
875
876 return res;
877}
878
879/*------------------------------------------------------------------------*/
880
881// if preprocess_only is false and opts.ilb is true we do not preprocess
882// such that we do not have to backtrack to level 0.
883//
884int Internal::solve (bool preprocess_only) {
885 CADICAL_assert (clause.empty ());
886 START (solve);
887 if (proof)
888 proof->solve_query ();
889 if (opts.ilb) {
890 if (opts.ilbassumptions)
892 stats.ilbtriggers++;
893 stats.ilbsuccess += (level > 0);
894 stats.levelsreused += level;
895 if (level) {
896 CADICAL_assert (control.size () > 1);
897 stats.literalsreused += num_assigned - control[1].trail;
898 }
899 if (external->propagator)
901 }
902 if (preprocess_only)
903 LOG ("internal solving in preprocessing only mode");
904 else
905 LOG ("internal solving in full mode");
907 int res = already_solved ();
908 if (!res && preprocess_only && level)
909 backtrack ();
910 if (!res)
911 res = restore_clauses ();
912 if (!res || (res == 10 && external_prop)) {
914 if (!preprocess_only)
916 }
917 if (!preprocess_only) {
918 if (!res && !level)
919 res = local_search ();
920 }
921 if (!res && !level)
922 res = preprocess ();
923 if (!preprocess_only) {
924 if (!res && !level)
925 res = local_search ();
926 if (!res && !level)
927 res = lucky_phases ();
928 if (!res || (res == 10 && external_prop)) {
929 if (res == 10 && external_prop && level)
930 backtrack ();
932 }
933 }
934 finalize (res);
935 reset_solving ();
936 report_solving (res);
937 STOP (solve);
938 return res;
939}
940
942 int res = 0;
943 if (unsat || unsat_constraint) {
944 LOG ("already inconsistent");
945 res = 20;
946 } else {
947 if (level && !opts.ilb)
948 backtrack ();
949 if (!level && !propagate ()) {
950 LOG ("root level propagation produces conflict");
952 res = 20;
953 }
954 if (max_var == 0 && res == 0)
955 res = 10;
956 }
957 return res;
958}
960 if (res == 10)
961 report ('1');
962 else if (res == 20)
963 report ('0');
964 else
965 report ('?');
966}
967
969 if (termination_forced) {
970
971 // TODO this leads potentially to a data race if the external
972 // user is calling 'terminate' twice within one 'solve' call.
973 // A proper solution would be to guard / protect setting the
974 // 'termination_forced' flag and only allow it during solving and
975 // ignore it otherwise thus also the second time it is called during a
976 // 'solve' call. We could move resetting it also the start of
977 // 'solve'.
978 //
979 termination_forced = false;
980
981 LOG ("reset forced termination");
982 }
983}
984
986 int res = 0;
987 if (opts.restoreall <= 1 && external->tainted.empty ()) {
988 LOG ("no tainted literals and nothing to restore");
989 report ('*');
990 } else {
991 report ('+');
992 // remove_garbage_binaries ();
993 external->restore_clauses ();
994 internal->report ('r');
995 if (!unsat && !level && !propagate ()) {
996 LOG ("root level propagation after restore produces conflict");
998 res = 20;
999 }
1000 }
1001 return res;
1002}
1003
1005 CADICAL_assert (clause.empty ());
1006 START (lookahead);
1008 lookingahead = true;
1009 if (external_prop) {
1010 if (level) {
1011 // Combining lookahead with external propagator is limited
1012 // Note that lookahead_probing (); would also force backtrack anyway
1013 backtrack ();
1014 }
1015 LOG ("external notifications are turned off during preprocessing.");
1016 private_steps = true;
1017 }
1018 int tmp = already_solved ();
1019 if (!tmp)
1020 tmp = restore_clauses ();
1021 int res = 0;
1022 if (!tmp)
1023 res = lookahead_probing ();
1024 if (res == INT_MIN)
1025 res = 0;
1026 reset_solving ();
1027 report_solving (tmp);
1029 lookingahead = false;
1030 STOP (lookahead);
1031 if (external_prop) {
1032 private_steps = false;
1033 LOG ("external notifications are turned back on.");
1034 notify_assignments (); // In case fixed assignments were found.
1035 }
1036 return res;
1037}
1038
1039/*------------------------------------------------------------------------*/
1040
1041void Internal::finalize (int res) {
1042 if (!proof)
1043 return;
1044 LOG ("finalizing");
1045 // finalize external units
1046 if (frat) {
1047 for (const auto &evar : external->vars) {
1048 CADICAL_assert (evar > 0);
1049 const auto eidx = 2 * evar;
1050 int sign = 1;
1051 int64_t id = external->ext_units[eidx];
1052 if (!id) {
1053 sign = -1;
1054 id = external->ext_units[eidx + 1];
1055 }
1056 if (id) {
1057 proof->finalize_external_unit (id, evar * sign);
1058 }
1059 }
1060 // finalize internal units
1061 for (const auto &lit : lits) {
1062 const auto elit = externalize (lit);
1063 if (elit) {
1064 const unsigned eidx = (elit < 0) + 2u * (unsigned) abs (elit);
1065 const int64_t id = external->ext_units[eidx];
1066 if (id) {
1067 CADICAL_assert (unit_clauses (vlit (lit)) == id);
1068 continue;
1069 }
1070 }
1071 const int64_t id = unit_clauses (vlit (lit));
1072 if (!id)
1073 continue;
1074 proof->finalize_unit (id, lit);
1075 }
1076 // See the discussion in 'propagate' on why garbage binary clauses stick
1077 // around.
1078 for (const auto &c : clauses)
1079 if (!c->garbage || (c->size == 2 && !c->flushed))
1080 proof->finalize_clause (c);
1081
1082 // finalize conflict and proof
1083 if (conflict_id) {
1084 proof->finalize_clause (conflict_id, {});
1085 }
1086 }
1087 proof->report_status (res, conflict_id);
1088 if (res == 10)
1089 external->conclude_sat ();
1090 else if (res == 20)
1091 conclude_unsat ();
1092 else if (!res)
1093 external->conclude_unknown ();
1094}
1095
1096/*------------------------------------------------------------------------*/
1097
1099 stats.print (this);
1100 for (auto &st : stat_tracers)
1101 st->print_stats ();
1102}
1103
1104/*------------------------------------------------------------------------*/
1105
1106// Only useful for debugging purposes.
1107
1109 for (const auto &lit : *c)
1110 printf ("%d ", lit);
1111 printf ("0\n");
1112}
1113
1115 int64_t m = assumptions.size ();
1116 for (auto idx : vars)
1117 if (fixed (idx))
1118 m++;
1119 for (const auto &c : clauses)
1120 if (!c->garbage)
1121 m++;
1122 printf ("p cnf %d %" PRId64 "\n", max_var, m);
1123 for (auto idx : vars) {
1124 const int tmp = fixed (idx);
1125 if (tmp)
1126 printf ("%d 0\n", tmp < 0 ? -idx : idx);
1127 }
1128 for (const auto &c : clauses)
1129 if (!c->garbage)
1130 dump (c);
1131 for (const auto &lit : assumptions)
1132 printf ("%d 0\n", lit);
1133 fflush (stdout);
1134}
1135
1136/*------------------------------------------------------------------------*/
1137
1139 if (constraint.empty () && !unsat_constraint)
1140 return true;
1141
1142 vector<int> eclause;
1143 if (unsat)
1144 return it.clause (eclause);
1145
1146 LOG (constraint, "traversing constraint");
1147 bool satisfied = false;
1148 for (auto ilit : constraint) {
1149 const int tmp = fixed (ilit);
1150 if (tmp > 0) {
1151 satisfied = true;
1152 break;
1153 }
1154 if (tmp < 0)
1155 continue;
1156 const int elit = externalize (ilit);
1157 eclause.push_back (elit);
1158 }
1159 if (!satisfied && !it.clause (eclause))
1160 return false;
1161
1162 return true;
1163}
1164/*------------------------------------------------------------------------*/
1165
1167 vector<int> eclause;
1168 if (unsat)
1169 return it.clause (eclause);
1170 for (const auto &c : clauses) {
1171 if (c->garbage)
1172 continue;
1173 if (c->redundant)
1174 continue;
1175 bool satisfied = false;
1176 for (const auto &ilit : *c) {
1177 const int tmp = fixed (ilit);
1178 if (tmp > 0) {
1179 satisfied = true;
1180 break;
1181 }
1182 if (tmp < 0)
1183 continue;
1184 const int elit = externalize (ilit);
1185 eclause.push_back (elit);
1186 }
1187 if (!satisfied && !it.clause (eclause))
1188 return false;
1189 eclause.clear ();
1190 }
1191 return true;
1192}
1193
1194} // namespace CaDiCaL
1195
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define CADICAL_QUIET
Definition global.h:8
#define LOG(...)
virtual bool clause(const std::vector< int > &)=0
#define propagate_wrapper
Definition internal.hpp:739
#define analyze_wrapper
Definition internal.hpp:740
#define PHASE(...)
Definition message.hpp:52
int sign(int lit)
Definition util.hpp:22
#define true
Definition place_base.h:28
#define false
Definition place_base.h:29
#define STOP(P)
Definition profile.hpp:158
#define START_OUTER_WALK()
Definition profile.hpp:259
#define STOP_OUTER_WALK()
Definition profile.hpp:270
#define START(P)
Definition profile.hpp:150
int lit
Definition satVec.h:130
size_t bytes() const
Definition clause.hpp:157
External * external
Definition internal.hpp:312
vector< int > ptab
Definition internal.hpp:238
vector< unsigned > relevanttab
Definition internal.hpp:225
void inprobe(bool update_limits=true)
vector< StatTracer * > stat_tracers
Definition internal.hpp:299
double scale(double v) const
bool ext_clause_forgettable
Definition internal.hpp:249
vector< int64_t > gtab
Definition internal.hpp:235
vector< int64_t > unit_clauses_idx
Definition internal.hpp:209
bool searching_lucky_phases
Definition internal.hpp:189
cadical_kitten * citten
Definition internal.hpp:277
vector< int > constraint
Definition internal.hpp:262
void init_scores(int old_max_var, int new_max_var)
void report(char type, int verbose_level=0)
void implied(std::vector< int > &entrailed)
int local_search_round(int round)
vector< int > trail
Definition internal.hpp:259
int fixed(int lit)
bool terminated_asynchronously(int factor=1)
const Sange lits
Definition internal.hpp:325
vector< Tracer * > tracers
Definition internal.hpp:296
void add_new_original_clause(int64_t)
int externalize(int lit)
Clause * dummy_binary
Definition internal.hpp:244
int64_t saved_decisions
Definition internal.hpp:205
vector< Var > vtab
Definition internal.hpp:231
void init_queue(int old_max_var, int new_max_var)
void condition(bool update_limits=true)
void finish_added_clause_with_id(int64_t id, bool restore=false)
void elim(bool update_limits=true)
signed char val(int lit) const
bool limit(const char *name, int)
bool traverse_constraint(ClauseIterator &)
void add_original_lit(int lit)
size_t no_conflict_until
Definition internal.hpp:258
Clause * newest_clause
Definition internal.hpp:246
vector< int > assumptions
Definition internal.hpp:261
void backtrack(int target_level=0)
void reserve_ids(int number)
void enlarge_vals(size_t new_vsize)
unsigned vlit(int lit) const
Definition internal.hpp:408
Reluctant reluctant
Definition internal.hpp:198
vector< Clause * > clauses
Definition internal.hpp:283
signed char * vals
Definition internal.hpp:221
vector< signed char > marks
Definition internal.hpp:222
void init_vars(int new_max_var)
vector< int64_t > btab
Definition internal.hpp:234
int solve(bool preprocess_only=false)
int try_to_satisfy_formula_by_saved_phases()
const Range vars
Definition internal.hpp:324
bool preprocess_round(int round)
vector< int > original
Definition internal.hpp:265
Clause * external_reason
Definition internal.hpp:245
vector< Level > control
Definition internal.hpp:282
int64_t & unit_clauses(int uidx)
Definition internal.hpp:443
vector< double > stab
Definition internal.hpp:230
vector< int > parents
Definition internal.hpp:232
Internal * internal
Definition internal.hpp:311
ScoreSchedule scores
Definition internal.hpp:229
int active() const
Definition internal.hpp:362
Clause * probe_reason
Definition internal.hpp:252
void enlarge(int new_max_var)
vector< FileTracer * > file_tracers
Definition internal.hpp:298
void delete_clause(Clause *)
bool traverse_clauses(ClauseIterator &)
volatile bool termination_forced
Definition internal.hpp:320
vector< Watches > wtab
Definition internal.hpp:241
int walk_round(int64_t limit, bool prev)
vector< int > clause
Definition internal.hpp:260
vector< Flags > ftab
Definition internal.hpp:233
char * memcpy()
char * memset()