ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_external.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4#include <cstdint>
5
7
8namespace CaDiCaL {
9
11 : internal (i), max_var (0), vsize (0), extended (false),
13 propagator (0), solution (0), vars (max_var) {
15 CADICAL_assert (!internal->external);
16 internal->external = this;
17}
18
20 if (solution)
21 delete[] solution;
22}
23
24void External::enlarge (int new_max_var) {
25
27
28 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) new_max_var;
29 while (new_vsize <= (size_t) new_max_var)
30 new_vsize *= 2;
31 LOG ("enlarge external size from %zd to new size %zd", vsize, new_vsize);
32 vsize = new_vsize;
33}
34
35void External::init (int new_max_var, bool extension) {
37 if (new_max_var <= max_var)
38 return;
39 int new_vars = new_max_var - max_var;
40 int old_internal_max_var = internal->max_var;
41 int new_internal_max_var = old_internal_max_var + new_vars;
42 internal->init_vars (new_internal_max_var);
43 if ((size_t) new_max_var >= vsize)
44 enlarge (new_max_var);
45 LOG ("initialized %d external variables", new_vars);
46 if (!max_var) {
47 CADICAL_assert (e2i.empty ());
48 e2i.push_back (0);
49 ext_units.push_back (0);
50 ext_units.push_back (0);
51 ext_flags.push_back (0);
52 ervars.push_back (0);
53 CADICAL_assert (internal->i2e.empty ());
54 internal->i2e.push_back (0);
55 } else {
56 CADICAL_assert (e2i.size () == (size_t) max_var + 1);
57 CADICAL_assert (internal->i2e.size () == (size_t) old_internal_max_var + 1);
58 }
59 unsigned iidx = old_internal_max_var + 1, eidx;
60 for (eidx = max_var + 1u; eidx <= (unsigned) new_max_var;
61 eidx++, iidx++) {
62 LOG ("mapping external %u to internal %u", eidx, iidx);
63 CADICAL_assert (e2i.size () == eidx);
64 e2i.push_back (iidx);
65 ext_units.push_back (0);
66 ext_units.push_back (0);
67 ext_flags.push_back (0);
68 ervars.push_back (0);
69 internal->i2e.push_back (eidx);
70 CADICAL_assert (internal->i2e[iidx] == (int) eidx);
71 CADICAL_assert (e2i[eidx] == (int) iidx);
72 }
73 if (extension)
74 internal->stats.variables_extension += new_vars;
75 else
76 internal->stats.variables_original += new_vars;
77 if (new_max_var >= (int64_t) is_observed.size ())
78 is_observed.resize (1 + (size_t) new_max_var, false);
79 if (internal->opts.checkfrozen)
80 if (new_max_var >= (int64_t) moltentab.size ())
81 moltentab.resize (1 + (size_t) new_max_var, false);
82 CADICAL_assert (iidx == (size_t) new_internal_max_var + 1);
83 CADICAL_assert (eidx == (size_t) new_max_var + 1);
84 CADICAL_assert (ext_units.size () == (size_t) new_max_var * 2 + 2);
85 max_var = new_max_var;
86}
87
88/*------------------------------------------------------------------------*/
89
91 assumptions.clear ();
92 internal->reset_assumptions ();
93}
94
96 concluded = false;
97 internal->reset_concluded ();
98}
99
101 constraint.clear ();
102 internal->reset_constraint ();
103}
104
106 if (!extended)
107 return;
108 LOG ("reset extended");
109 extended = false;
110}
111
112void External::reset_limits () { internal->reset_limits (); }
113
114/*------------------------------------------------------------------------*/
115
116// when extension is true, elit should be a fresh variable and
117// we can set a flag that it is an extension variable.
118// This is then used in the API contracts, that extension variables are
119// never part of the input
120int External::internalize (int elit, bool extension) {
121 int ilit;
122 if (elit) {
123 CADICAL_assert (elit != INT_MIN);
124 const int eidx = abs (elit);
125 if (extension && eidx <= max_var)
126 FATAL ("can not add a definition for an already used variable %d",
127 eidx);
128 if (eidx > max_var) {
129 init (eidx, extension);
130 }
131 if (extension) {
132 CADICAL_assert (ervars.size () > (size_t) eidx);
133 ervars[eidx] = true;
134 }
135 ilit = e2i[eidx];
136 if (elit < 0)
137 ilit = -ilit;
138 if (!ilit) {
139 CADICAL_assert (internal->max_var < INT_MAX);
140 ilit = internal->max_var + 1u;
141 internal->init_vars (ilit);
142 e2i[eidx] = ilit;
143 LOG ("mapping external %d to internal %d", eidx, ilit);
144 e2i[eidx] = ilit;
145 internal->i2e.push_back (eidx);
146 CADICAL_assert (internal->i2e[ilit] == eidx);
147 CADICAL_assert (e2i[eidx] == ilit);
148 if (elit < 0)
149 ilit = -ilit;
150 }
151 if (internal->opts.checkfrozen) {
152 CADICAL_assert (eidx < (int64_t) moltentab.size ());
153 if (moltentab[eidx])
154 FATAL ("can not reuse molten literal %d", eidx);
155 }
156 Flags &f = internal->flags (ilit);
157 if (f.status == Flags::UNUSED)
158 internal->mark_active (ilit);
159 else if (f.status != Flags::ACTIVE && f.status != Flags::FIXED)
160 internal->reactivate (ilit);
161 if (!marked (tainted, elit) && marked (witness, -elit)) {
162 CADICAL_assert (!internal->opts.checkfrozen);
163 LOG ("marking tainted %d", elit);
164 mark (tainted, elit);
165 }
166 } else
167 ilit = 0;
168 return ilit;
169}
170
171void External::add (int elit) {
172 CADICAL_assert (elit != INT_MIN);
174
175 bool forgettable = false;
176
177 if (internal->opts.check &&
178 (internal->opts.checkwitness || internal->opts.checkfailed)) {
179
180 forgettable =
181 internal->from_propagator && internal->ext_clause_forgettable;
182
183 // Forgettable clauses (coming from the external propagator) are not
184 // saved into the external 'original' stack. They are stored separately
185 // in external 'forgettable_original', from where they are deleted when
186 // the corresponding clause is deleted (actually deleted, not just
187 // marked as garbage).
188 if (!forgettable)
189 original.push_back (elit);
190 }
191
192 const int ilit = internalize (elit);
193 CADICAL_assert (!elit == !ilit);
194
195 // The external literals of the new clause must be saved for later
196 // when the proof is printed during add_original_lit (0)
197 if (elit && (internal->proof || forgettable)) {
198 eclause.push_back (elit);
199 if (internal->lrat) {
200 // actually find unit of -elit (flips elit < 0)
201 unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
202 CADICAL_assert ((size_t) eidx < ext_units.size ());
203 const int64_t id = ext_units[eidx];
204 bool added = ext_flags[abs (elit)];
205 if (id && !added) {
206 ext_flags[abs (elit)] = true;
207 internal->lrat_chain.push_back (id);
208 }
209 }
210 }
211
212 if (!elit && internal->proof && internal->lrat) {
213 for (const auto &elit : eclause) {
214 ext_flags[abs (elit)] = false;
215 }
216 }
217
218 if (elit)
219 LOG ("adding external %d as internal %d", elit, ilit);
220 internal->add_original_lit (ilit);
221
222 // Clean-up saved external literals once proof line is printed
223 if (!elit && (internal->proof || forgettable))
224 eclause.clear ();
225}
226
227void External::assume (int elit) {
228 CADICAL_assert (elit);
230 if (internal->proof)
231 internal->proof->add_assumption (elit);
232 assumptions.push_back (elit);
233 const int ilit = internalize (elit);
234 CADICAL_assert (ilit);
235 LOG ("assuming external %d as internal %d", elit, ilit);
236 internal->assume (ilit);
237}
238
239bool External::flip (int elit) {
240 CADICAL_assert (elit);
241 CADICAL_assert (elit != INT_MIN);
243
244 int eidx = abs (elit);
245 if (eidx > max_var)
246 return false;
247 if (marked (witness, elit))
248 return false;
249 int ilit = e2i[eidx];
250 if (!ilit)
251 return false;
252 bool res = internal->flip (ilit);
253 if (res && extended)
255 return res;
256}
257
258bool External::flippable (int elit) {
259 CADICAL_assert (elit);
260 CADICAL_assert (elit != INT_MIN);
262
263 int eidx = abs (elit);
264 if (eidx > max_var)
265 return false;
266 if (marked (witness, elit))
267 return false;
268 int ilit = e2i[eidx];
269 if (!ilit)
270 return false;
271 return internal->flippable (ilit);
272}
273
274bool External::failed (int elit) {
275 CADICAL_assert (elit);
276 CADICAL_assert (elit != INT_MIN);
277 int eidx = abs (elit);
278 if (eidx > max_var)
279 return 0;
280 int ilit = e2i[eidx];
281 if (!ilit)
282 return 0;
283 if (elit < 0)
284 ilit = -ilit;
285 return internal->failed (ilit);
286}
287
288void External::constrain (int elit) {
289 if (constraint.size () && !constraint.back ()) {
290 LOG (constraint, "replacing previous constraint");
292 }
293 CADICAL_assert (elit != INT_MIN);
295 const int ilit = internalize (elit);
296 CADICAL_assert (!elit == !ilit);
297 if (elit)
298 LOG ("adding external %d as internal %d to constraint", elit, ilit);
299 else if (!elit && internal->proof) {
300 internal->proof->add_constraint (constraint);
301 }
302 constraint.push_back (elit);
303 internal->constrain (ilit);
304}
305
307 return internal->failed_constraint ();
308}
309
310void External::phase (int elit) {
311 CADICAL_assert (elit);
312 CADICAL_assert (elit != INT_MIN);
313 const int ilit = internalize (elit);
314 internal->phase (ilit);
315}
316
317void External::unphase (int elit) {
318 CADICAL_assert (elit);
319 CADICAL_assert (elit != INT_MIN);
320 int eidx = abs (elit);
321 if (eidx > max_var) {
322 UNUSED:
323 LOG ("resetting forced phase of unused external %d ignored", elit);
324 return;
325 }
326 int ilit = e2i[eidx];
327 if (!ilit)
328 goto UNUSED;
329 if (elit < 0)
330 ilit = -ilit;
331 internal->unphase (ilit);
332}
333
334/*------------------------------------------------------------------------*/
335
336// External propagation related functions
337//
338// Note that when an already assigned variable is added as observed, the
339// solver will backtrack to undo this assignment.
340//
342 if (!propagator) {
343 LOG ("No connected propagator that could observe the variable, "
344 "observed flag is not set.");
345 return;
346 }
347
348 CADICAL_assert (elit);
349 CADICAL_assert (elit != INT_MIN);
350 reset_extended (); // tainting!
351
352 int eidx = abs (elit);
353 if (eidx <= max_var &&
354 (marked (witness, elit) || marked (witness, -elit))) {
355 LOG ("Error, only clean variables are allowed to become observed.");
356 CADICAL_assert (false);
357
358 // TODO: here needs to come the taint and restore of the newly
359 // observed variable. Restore_clauses must be called before continue.
360 // LOG ("marking tainted %d", elit);
361 // mark (tainted, elit);
362 // mark (tainted, -elit);
363 // restore_clauses ...
364 }
365
366 if (eidx >= (int64_t) is_observed.size ())
367 is_observed.resize (1 + (size_t) eidx, false);
368
369 if (is_observed[eidx])
370 return;
371
372 LOG ("marking %d as externally watched", eidx);
373
374 // Will do the necessary internalization
375 freeze (elit);
376 is_observed[eidx] = true;
377
378 int ilit = internalize (elit);
379 // internal add-observed-var backtracks to a lower decision level to
380 // unassign the variable in case it was already assigned previously (but
381 // not on the current level)
382 internal->add_observed_var (ilit);
383
384 if (propagator->is_lazy)
385 return;
386
387 // In case this variable was already assigned (e.g. via unit clause) and
388 // got compacted to map to another (not observed) variable, it can not be
389 // unnasigned so it must be notified explicitly now. (-> Can lead to
390 // repeated fixed assignment notifications, in case it was unobserved and
391 // observed again. But a repeated notification is less error-prone than
392 // never notifying an assignment.)
393 const int tmp = fixed (elit);
394 if (!tmp)
395 return;
396 int unit = tmp < 0 ? -elit : elit;
397
398 LOG ("notify propagator about fixed assignment upon observe for %d",
399 unit);
400
401 // internal add-observed-var had to backtrack to root-level already
402 CADICAL_assert (!internal->level);
403
404 std::vector<int> assigned = {unit};
405 propagator->notify_assignment (assigned);
406}
407
409 if (!propagator) {
410 LOG ("No connected propagator that could have watched the variable");
411 return;
412 }
413 int eidx = abs (elit);
414
415 if (eidx > max_var)
416 return;
417
418 if (is_observed[eidx]) {
419 // Follow opposite order of add_observed_var, first remove internal
420 // is_observed
421 int ilit = e2i[eidx]; // internalize (elit);
422 internal->remove_observed_var (ilit);
423
424 is_observed[eidx] = false;
425 melt (elit);
426 LOG ("unmarking %d as externally watched", eidx);
427 }
428}
429
431 // Shouldn't be called if there is no connected propagator
434
435 internal->notified = 0;
436 LOG ("reset notified counter to 0");
437
438 if (!is_observed.size ())
439 return;
440
441 CADICAL_assert (!max_var || (size_t) max_var + 1 == is_observed.size ());
442
443 for (auto elit : vars) {
444 int eidx = abs (elit);
445 CADICAL_assert (eidx <= max_var);
446 if (is_observed[eidx]) {
447 int ilit = internalize (elit);
448 internal->remove_observed_var (ilit);
449 LOG ("unmarking %d as externally watched", eidx);
450 is_observed[eidx] = false;
451 melt (elit);
452 }
453 }
454}
455
456bool External::observed (int elit) {
457 CADICAL_assert (elit);
458 CADICAL_assert (elit != INT_MIN);
459 int eidx = abs (elit);
460 if (eidx > max_var)
461 return false;
462 if (eidx >= (int) is_observed.size ())
463 return false;
464
465 return is_observed[eidx];
466}
467
468bool External::is_witness (int elit) {
469 CADICAL_assert (elit);
470 CADICAL_assert (elit != INT_MIN);
471 int eidx = abs (elit);
472 if (eidx > max_var)
473 return false;
474 return (marked (witness, elit) || marked (witness, -elit));
475}
476
477bool External::is_decision (int elit) {
478 CADICAL_assert (elit);
479 CADICAL_assert (elit != INT_MIN);
480 int eidx = abs (elit);
481 if (eidx > max_var)
482 return false;
483
484 int ilit = internalize (elit);
485 return internal->is_decision (ilit);
486}
487
488void External::force_backtrack (size_t new_level) {
489 if (!propagator) {
490 LOG ("No connected propagator that could force backtracking");
491 return;
492 }
493 LOG ("force backtrack to level %zd", new_level);
494 internal->force_backtrack (new_level);
495}
496
497/*------------------------------------------------------------------------*/
498
500 int res = internal->propagate_assumptions ();
501 if (res == 10 && !extended)
502 extend (); // Call solution reconstruction
503 check_solve_result (res);
504 reset_limits ();
505 return res;
506}
507
508void External::implied (std::vector<int> &trailed) {
509 std::vector<int> ilit_implicants;
510 internal->implied (ilit_implicants);
511
512 // Those implied literals must be filtered out that are witnesses
513 // on the reconstruction stack -> no inplace externalize is possible.
514 // (Internal does not see these marks, so no earlier filter is
515 // possible.)
516
517 trailed.clear();
518
519 for (const auto &ilit : ilit_implicants) {
520 CADICAL_assert (ilit);
521 const int elit = internal->externalize (ilit);
522 const int eidx = abs (elit);
523 const bool is_extension_var = ervars[eidx];
524 if (!marked (tainted, elit) && !is_extension_var) {
525 trailed.push_back (elit);
526 }
527 }
528}
529
531 if (!internal->proof || concluded)
532 return;
533 concluded = true;
534
535 vector<int> trail;
536 implied (trail);
537 internal->proof->conclude_unknown (trail);
538}
539
540/*------------------------------------------------------------------------*/
541
542// Internal checker if 'solve' claims the formula to be satisfiable.
543
545 LOG ("checking satisfiable");
546 if (!extended)
547 extend ();
548 if (internal->opts.checkwitness)
550 if (internal->opts.checkassumptions && !assumptions.empty ())
552 if (internal->opts.checkconstraint && !constraint.empty ())
554}
555
556// Internal checker if 'solve' claims formula to be unsatisfiable.
557
559 LOG ("checking unsatisfiable");
560 if (!internal->opts.checkfailed)
561 return;
562 if (!assumptions.empty () || !constraint.empty ())
563 check_failing ();
564}
565
566// Check result of 'solve' to be correct.
567
569 if (!internal->opts.check)
570 return;
571 if (res == 10)
573 if (res == 20)
575}
576
577// Prepare checking that completely molten literals are not used as argument
578// of 'add' or 'assume', which is invalid under freezing semantics. This
579// case would be caught by our 'restore' implementation so is only needed
580// for checking the deprecated 'freeze' semantics.
581
583 if (!internal->opts.checkfrozen)
584 return;
585 CADICAL_assert ((size_t) max_var + 1 == moltentab.size ());
586#ifdef LOGGING
587 int registered = 0, molten = 0;
588#endif
589 for (auto lit : vars) {
590 if (moltentab[lit]) {
591 LOG ("skipping already molten literal %d", lit);
592#ifdef LOGGING
593 molten++;
594#endif
595 } else if (frozen (lit))
596 LOG ("skipping currently frozen literal %d", lit);
597 else {
598 LOG ("new molten literal %d", lit);
599 moltentab[lit] = true;
600#ifdef LOGGING
601 registered++;
602 molten++;
603#endif
604 }
605 }
606 LOG ("registered %d new molten literals", registered);
607 LOG ("reached in total %d molten literals", molten);
608}
609
610int External::solve (bool preprocess_only) {
613 int res = internal->solve (preprocess_only);
614 check_solve_result (res);
615 reset_limits ();
616 return res;
617}
618
619void External::terminate () { internal->terminate (); }
620
624 int ilit = internal->lookahead ();
625 const int elit =
626 (ilit && ilit != INT_MIN) ? internal->externalize (ilit) : 0;
627 LOG ("lookahead internal %d external %d", ilit, elit);
628 return elit;
629}
630
632 int min_depth = 0) {
635 reset_limits ();
636 auto cubes = internal->generate_cubes (depth, min_depth);
637 auto externalize = [this] (int ilit) {
638 const int elit = ilit ? internal->externalize (ilit) : 0;
639 MSG ("lookahead internal %d external %d", ilit, elit);
640 return elit;
641 };
642 auto externalize_map = [this, externalize] (std::vector<int> cube) {
643 (void) this;
644 MSG ("Cube : ");
645 std::for_each (begin (cube), end (cube), externalize);
646 };
647 std::for_each (begin (cubes.cubes), end (cubes.cubes), externalize_map);
648
649 return cubes;
650}
651
652/*------------------------------------------------------------------------*/
653
654void External::freeze (int elit) {
656 int ilit = internalize (elit);
657 unsigned eidx = vidx (elit);
658 if (eidx >= frozentab.size ())
659 frozentab.resize (eidx + 1, 0);
660 unsigned &ref = frozentab[eidx];
661 if (ref < UINT_MAX) {
662 ref++;
663 LOG ("external variable %d frozen once and now frozen %u times", eidx,
664 ref);
665 } else
666 LOG ("external variable %d frozen but remains frozen forever", eidx);
667 internal->freeze (ilit);
668}
669
670void External::melt (int elit) {
672 int ilit = internalize (elit);
673 unsigned eidx = vidx (elit);
674 CADICAL_assert (eidx < frozentab.size ());
675 unsigned &ref = frozentab[eidx];
676 CADICAL_assert (ref > 0);
677 if (ref < UINT_MAX) {
678 if (!--ref) {
679 if (observed (elit)) {
680 ref++;
681 LOG ("external variable %d is observed, can not be completely "
682 "molten",
683 eidx);
684 } else
685 LOG ("external variable %d melted once and now completely melted",
686 eidx);
687 } else
688 LOG ("external variable %d melted once but remains frozen %u times",
689 eidx, ref);
690 } else
691 LOG ("external variable %d melted but remains frozen forever", eidx);
692 internal->melt (ilit);
693}
694
695/*------------------------------------------------------------------------*/
696
697void External::check_assignment (int (External::*a) (int) const) {
698
699 // First check all assigned and consistent.
700 //
701 for (auto idx : vars) {
702 if (!(this->*a) (idx))
703 FATAL ("unassigned variable: %d", idx);
704 int value_idx = (this->*a) (idx);
705 int value_neg_idx = (this->*a) (-idx);
706 if (value_idx == idx)
707 CADICAL_assert (value_neg_idx == idx);
708 else {
709 CADICAL_assert (value_idx == -idx);
710 CADICAL_assert (value_neg_idx == -idx);
711 }
712 if (value_idx != value_neg_idx)
713 FATAL ("inconsistently assigned literals %d and %d", idx, -idx);
714 }
715
716 // Then check that all (saved) original clauses are satisfied.
717 //
718 bool satisfied = false;
719 const auto end = original.end ();
720 auto start = original.begin (), i = start;
721#ifndef CADICAL_QUIET
722 int64_t count = 0;
723#endif
724 for (; i != end; i++) {
725 int lit = *i;
726 if (!lit) {
727 if (!satisfied) {
729 fputs ("unsatisfied clause:\n", stderr);
730 for (auto j = start; j != i; j++)
731 fprintf (stderr, "%d ", *j);
732 fputc ('0', stderr);
734 }
735 satisfied = false;
736 start = i + 1;
737#ifndef CADICAL_QUIET
738 count++;
739#endif
740 } else if (!satisfied && (this->*a) (lit) == lit)
741 satisfied = true;
742 }
743
744 bool presence_flag;
745 // Check those forgettable external clauses that are still present, but
746 // only if the external propagator is still connected (otherwise solution
747 // reconstruction is allowed to touch the previously observed variables so
748 // there is no guarantee that the final model will satisfy these clauses.)
749 for (const auto &forgettables : forgettable_original) {
750 if (!propagator)
751 break;
752 presence_flag = true;
753 satisfied = false;
754#ifndef CADICAL_QUIET
755 count++;
756#endif
757 std::vector<int> literals;
758 for (const auto lit : forgettables.second) {
759 if (presence_flag) {
760 // First integer is a Boolean flag, not a literal
761 if (!lit) {
762 // Deleted clauses can be ignored, they count as satisfied
763 satisfied = true;
764 break;
765 }
766 presence_flag = false;
767 continue;
768 }
769
770 if ((this->*a) (lit) == lit) {
771 satisfied = true;
772 break;
773 }
774 }
775
776 if (!satisfied) {
778 fputs ("unsatisfied external forgettable clause:\n", stderr);
779 for (size_t j = 1; j < forgettables.second.size (); j++)
780 fprintf (stderr, "%d ", forgettables.second[j]);
781 fputc ('0', stderr);
783 }
784 }
785#ifndef CADICAL_QUIET
786 VERBOSE (1, "satisfying assignment checked on %" PRId64 " clauses",
787 count);
788#endif
789}
790
791/*------------------------------------------------------------------------*/
792
794 for (const auto &lit : assumptions) {
795 // Not 'signed char' !!!!
796 const int tmp = ival (lit);
797 if (tmp != lit)
798 FATAL ("assumption %d falsified", lit);
799 if (!tmp)
800 FATAL ("assumption %d unassigned", lit);
801 }
802 VERBOSE (1, "checked that %zd assumptions are satisfied",
803 assumptions.size ());
804}
805
807 for (const auto lit : constraint) {
808 if (ival (lit) == lit) {
809 VERBOSE (1, "checked that constraint is satisfied");
810 return;
811 }
812 }
813 FATAL ("constraint not satisfied");
814}
815
817 Solver *checker = new Solver ();
818 DeferDeletePtr<Solver> delete_checker (checker);
819 checker->prefix ("checker ");
820#ifdef LOGGING
821 if (internal->opts.log)
822 checker->set ("log", true);
823#endif
824
825 for (const auto lit : assumptions) {
826 if (!failed (lit))
827 continue;
828 LOG ("checking failed literal %d in core", lit);
829 checker->add (lit);
830 checker->add (0);
831 }
832 if (failed_constraint ()) {
833 LOG (constraint, "checking failed constraint");
834 for (const auto lit : constraint)
835 checker->add (lit);
836 } else if (constraint.size ())
837 LOG (constraint, "constraint satisfied and ignored");
838
839 // Add original clauses as last step, failing () and failed_constraint ()
840 // might add more external clauses (due to lazy explanation)
841 for (const auto lit : original)
842 checker->add (lit);
843
844 // Add every forgettable external clauses
845 for (const auto &forgettables : forgettable_original) {
846 bool presence_flag = true;
847 for (const auto lit : forgettables.second) {
848 if (presence_flag) {
849 // First integer is a Boolean flag, not a literal, ignore it here
850 presence_flag = false;
851 continue;
852 }
853 checker->add (lit);
854 }
855 checker->add (0);
856 }
857
858 int res = checker->solve ();
859 if (res != 20)
860 FATAL ("failed assumptions do not form a core");
861 delete_checker.free ();
862 VERBOSE (1, "checked that %zd failing assumptions form a core",
863 assumptions.size ());
864}
865
866/*------------------------------------------------------------------------*/
867
868// Traversal of unit clauses is implemented here.
869
870// In principle we want to traverse the clauses of the simplified formula
871// only, particularly eliminated variables should be completely removed.
872// This poses the question what to do with unit clauses. Should they be
873// considered part of the simplified formula or of the witness to construct
874// solutions for the original formula? Ideally they should be considered
875// to be part of the witness only, i.e., as they have been simplified away.
876
877// Therefore we distinguish frozen and non-frozen units during clause
878// traversal. Frozen units are treated as unit clauses while non-frozen
879// units are treated as if they were already eliminated and put on the
880// extension stack as witness clauses.
881
882// Furthermore, eliminating units during 'compact' could be interpreted as
883// variable elimination, i.e., just add the resolvents (remove falsified
884// literals), then drop the clauses with the unit, and push the unit on the
885// extension stack. This is of course only OK if the user did not freeze
886// that variable (even implicitly during assumptions).
887
888// Thanks go to Fahiem Bacchus for asking why there is a necessity to
889// distinguish these two cases (frozen and non-frozen units). The answer is
890// that it is not strictly necessary, and this distinction could be avoided
891// by always treating units as remaining unit clauses, thus only using the
892// first of the two following functions and dropping the 'if (!frozen (idx))
893// continue;' check in it. This has however the down-side that those units
894// are still in the simplified formula and only as units. I would not
895// consider such a formula as really being 'simplified'. On the other hand
896// if the user explicitly freezes a literal, then it should continue to be
897// in the simplified formula during traversal. So also only using the
898// second function is not ideal.
899
900// There is however a catch where this solution breaks down (in the sense of
901// producing less optimal results - that is keeping units in the formula
902// which better would be witness clauses). The problem is with compact
903// preprocessing which removes eliminated but also fixed internal variables.
904// One internal unit (fixed) variable is kept and all the other external
905// literals which became unit are mapped to that internal literal (negated
906// or positively). Compact is called non-deterministically from the point
907// of the user and thus there is no control on when this happens. If
908// compact happens those external units are mapped to a single internal
909// literal now and then all share the same 'frozen' counter. So if the
910// user freezes one of them all in essence get frozen, which in turn then
911// makes a difference in terms of traversing such a unit as unit clause or
912// as unit witness.
913
915 if (internal->unsat)
916 return true;
917
919
920 for (auto idx : vars) {
921 if (!frozen (idx))
922 continue;
923 const int tmp = fixed (idx);
924 if (!tmp)
925 continue;
926 int unit = tmp < 0 ? -idx : idx;
927 clause.push_back (unit);
928 if (!it.clause (clause))
929 return false;
930 clause.clear ();
931 }
932
933 return true;
934}
935
937 WitnessIterator &it) {
938 if (internal->unsat)
939 return true;
940
941 vector<int> clause_and_witness;
942 for (auto idx : vars) {
943 if (frozen (idx))
944 continue;
945 const int tmp = fixed (idx);
946 if (!tmp)
947 continue;
948 int unit = tmp < 0 ? -idx : idx;
949 const int ilit = e2i[idx] * (tmp < 0 ? -1 : 1);
950 // heurstically add + max_var to the id to avoid reusing ids
951 const int64_t id = internal->lrat ? internal->unit_id (ilit) : 1;
952 CADICAL_assert (id);
953 clause_and_witness.push_back (unit);
954 if (!it.witness (clause_and_witness, clause_and_witness, id + max_var))
955 return false;
956 clause_and_witness.clear ();
957 }
958
959 return true;
960}
961
962/*------------------------------------------------------------------------*/
963
964void External::copy_flags (External &other) const {
965 const vector<Flags> &this_ftab = internal->ftab;
966 vector<Flags> &other_ftab = other.internal->ftab;
967 const unsigned limit = min (max_var, other.max_var);
968 for (unsigned eidx = 1; eidx <= limit; eidx++) {
969 const int this_ilit = e2i[eidx];
970 if (!this_ilit)
971 continue;
972 const int other_ilit = other.e2i[eidx];
973 if (!other_ilit)
974 continue;
975 if (!internal->active (this_ilit))
976 continue;
977 if (!other.internal->active (other_ilit))
978 continue;
979 CADICAL_assert (this_ilit != INT_MIN);
980 CADICAL_assert (other_ilit != INT_MIN);
981 const Flags &this_flags = this_ftab[abs (this_ilit)];
982 Flags &other_flags = other_ftab[abs (other_ilit)];
983 this_flags.copy (other_flags);
984 }
985}
986
987/*------------------------------------------------------------------------*/
988
991 if (learner->learning (0)) {
992 LOG ("exporting learned empty clause");
993 learner->learn (0);
994 } else
995 LOG ("not exporting learned empty clause");
996}
997
1000 if (learner->learning (1)) {
1001 LOG ("exporting learned unit clause");
1002 const int elit = internal->externalize (ilit);
1003 CADICAL_assert (elit);
1004 learner->learn (elit);
1005 learner->learn (0);
1006 } else
1007 LOG ("not exporting learned unit clause");
1008}
1009
1012 size_t size = clause.size ();
1013 CADICAL_assert (size <= (unsigned) INT_MAX);
1014 if (learner->learning ((int) size)) {
1015 LOG ("exporting learned clause of size %zu", size);
1016 for (auto ilit : clause) {
1017 const int elit = internal->externalize (ilit);
1018 CADICAL_assert (elit);
1019 learner->learn (elit);
1020 }
1021 learner->learn (0);
1022 } else
1023 LOG ("not exporting learned clause of size %zu", size);
1024}
1025
1026} // namespace CaDiCaL
1027
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
virtual bool clause(const std::vector< int > &)=0
void add(int lit)
void prefix(const char *verbose_message_prefix)
bool set(const char *name, int val)
virtual bool witness(const std::vector< int > &clause, const std::vector< int > &witness, int64_t id=0)=0
#define MSG(...)
Definition message.hpp:49
#define FATAL
Definition message.hpp:64
#define VERBOSE(...)
Definition message.hpp:58
void fatal_message_start()
void fatal_message_end()
#define false
Definition place_base.h:29
int lit
Definition satVec.h:130
bool traverse_all_non_frozen_units_as_witnesses(WitnessIterator &)
void constrain(int elit)
vector< bool > ext_flags
Definition external.hpp:74
void enlarge(int new_max_var)
bool is_witness(int elit)
CaDiCaL::CubesWithStatus generate_cubes(int, int)
const Range vars
Definition external.hpp:149
vector< bool > tainted
Definition external.hpp:88
vector< bool > is_observed
Definition external.hpp:115
bool marked(const vector< bool > &map, int elit) const
Definition external.hpp:216
bool is_decision(int elit)
signed char * solution
Definition external.hpp:135
int ival(int elit) const
Definition external.hpp:325
void export_learned_unit_clause(int ilit)
bool frozen(int elit)
Definition external.hpp:257
vector< bool > moltentab
Definition external.hpp:145
vector< bool > witness
Definition external.hpp:87
Terminator * terminator
Definition external.hpp:97
void implied(std::vector< int > &entrailed)
vector< int64_t > ext_units
Definition external.hpp:73
void check_assignment(int(External::*assignment)(int) const)
vector< int > extension
Definition external.hpp:85
Learner * learner
Definition external.hpp:101
vector< int > original
Definition external.hpp:137
unordered_map< uint64_t, vector< int > > forgettable_original
Definition external.hpp:121
vector< int > constraint
Definition external.hpp:70
bool flippable(int elit)
void remove_observed_var(int elit)
void add_observed_var(int elit)
void copy_flags(External &other) const
bool traverse_all_frozen_units_as_clauses(ClauseIterator &)
vector< unsigned > frozentab
Definition external.hpp:92
Internal * internal
Definition external.hpp:61
vector< int > eclause
Definition external.hpp:75
bool observed(int elit)
int solve(bool preprocess_only)
vector< int > e2i
Definition external.hpp:67
FixedAssignmentListener * fixed_listener
Definition external.hpp:109
void export_learned_large_clause(const vector< int > &)
void force_backtrack(size_t new_level)
void init(int new_max_var, bool extension=false)
int vidx(int elit) const
Definition external.hpp:155
vector< bool > ervars
Definition external.hpp:90
ExternalPropagator * propagator
Definition external.hpp:113
int fixed(int elit) const
void check_solve_result(int res)
vector< int > assumptions
Definition external.hpp:69
int internalize(int, bool extension=false)
void copy(Flags &dst) const
Definition flags.hpp:79
unsigned char status
Definition flags.hpp:56
bool active(int lit)
Definition internal.hpp:360
vector< Flags > ftab
Definition internal.hpp:233
unsigned size
Definition clause.h:37
Definition exor.h:123
signed char mark
Definition value.h:8