ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_assume.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4#include "options.hpp"
5
7
8namespace CaDiCaL {
9
10// Failed literal handling as pioneered by MiniSAT. This first function
11// adds an assumption literal onto the assumption stack.
12
14 if (level && !opts.ilbassumptions)
15 backtrack ();
16 else if (val (lit) < 0)
17 backtrack (max (0, var (lit).level - 1));
18 Flags &f = flags (lit);
19 const unsigned char bit = bign (lit);
20 if (f.assumed & bit) {
21 LOG ("ignoring already assumed %d", lit);
22 return;
23 }
24 LOG ("assume %d", lit);
25 f.assumed |= bit;
26 assumptions.push_back (lit);
27 freeze (lit);
28}
29
30// for LRAT we actually need to implement recursive DFS
31// for non-lrat use BFS. TODO: maybe derecursify to avoid stack overflow
32//
35 Flags &f = flags (lit);
36 if (f.seen)
37 return;
38 f.seen = true;
39 analyzed.push_back (lit);
40 Var &v = var (lit);
41 CADICAL_assert (val (lit) < 0);
42 if (v.reason == external_reason) {
44 CADICAL_assert (v.reason || !v.level);
45 }
47 if (!v.level) {
48 int64_t id = unit_id (-lit);
49 lrat_chain.push_back (id);
50 return;
51 }
52 if (v.reason) {
54 LOG (v.reason, "analyze reason");
55 for (const auto &other : *v.reason) {
57 }
58 lrat_chain.push_back (v.reason->id);
59 return;
60 }
62 LOG ("failed assumption %d", -lit);
63 clause.push_back (lit);
64}
65
67 CADICAL_assert (reason);
68 CADICAL_assert (lrat_chain.empty ());
71 for (const auto &other : *reason)
72 if (other != lit)
74 lrat_chain.push_back (reason->id);
75}
76
77// Find all failing assumptions starting from the one on the assumption
78// stack with the lowest decision level. This goes back to MiniSAT and is
79// called 'analyze_final' there.
80
82
83 START (analyze);
84
85 LOG ("analyzing failing assumptions");
86
87 CADICAL_assert (analyzed.empty ());
88 CADICAL_assert (clause.empty ());
89 CADICAL_assert (lrat_chain.empty ());
92
93 if (!unsat_constraint) {
94 // Search for failing assumptions in the (internal) assumption stack.
95
96 // There are in essence three cases: (1) An assumption is falsified on
97 // the root-level and then 'failed_unit' is set to that assumption, (2)
98 // two clashing assumptions are assumed and then 'failed_clashing' is
99 // set to the second assumed one, or otherwise (3) there is a failing
100 // assumption 'first_failed' with minimum (non-zero) decision level
101 // 'failed_level'.
102
103 int failed_unit = 0;
104 int failed_clashing = 0;
105 int first_failed = 0;
106 int failed_level = INT_MAX;
107 int efailed = 0;
108
109 for (auto &elit : external->assumptions) {
110 int lit = external->e2i[abs (elit)];
111 if (elit < 0)
112 lit = -lit;
113 if (val (lit) >= 0)
114 continue;
115 const Var &v = var (lit);
116 if (!v.level) {
117 failed_unit = lit;
118 efailed = elit;
119 break;
120 }
121 if (failed_clashing)
122 continue;
123 if (v.reason == external_reason) {
124 Var &ev = var (lit);
126 if (!ev.reason) {
127 ev.level = 0;
128 failed_unit = lit;
129 efailed = elit;
130 break;
131 }
132 ev.level = 0;
133 // Recalculate assignment level
134 for (const auto &other : *ev.reason) {
135 if (other == -lit)
136 continue;
137 CADICAL_assert (val (other));
138 int tmp = var (other).level;
139 if (tmp > ev.level)
140 ev.level = tmp;
141 }
142 if (!ev.level) {
143 failed_unit = lit;
144 efailed = elit;
145 break;
146 }
147 }
149 if (!v.reason) {
150 failed_clashing = lit;
151 efailed = elit;
152 } else if (!first_failed || v.level < failed_level) {
153 first_failed = lit;
154 efailed = elit;
155 failed_level = v.level;
156 }
157 }
158
159 CADICAL_assert (clause.empty ());
160
161 // Get the 'failed' assumption from one of the three cases.
162 int failed;
163 if (failed_unit)
164 failed = failed_unit;
165 else if (failed_clashing)
166 failed = failed_clashing;
167 else
168 failed = first_failed;
170 CADICAL_assert (efailed);
171
172 // In any case mark literal 'failed' as failed assumption.
173 {
174 Flags &f = flags (failed);
175 const unsigned bit = bign (failed);
176 CADICAL_assert (!(f.failed & bit));
177 f.failed |= bit;
178 }
179
180 // First case (1).
181 if (failed_unit) {
182 CADICAL_assert (failed == failed_unit);
183 LOG ("root-level falsified assumption %d", failed);
184 if (proof) {
185 if (lrat) {
186 unsigned eidx = (efailed > 0) + 2u * (unsigned) abs (efailed);
187 CADICAL_assert ((size_t) eidx < external->ext_units.size ());
188 const int64_t id = external->ext_units[eidx];
189 if (id) {
190 lrat_chain.push_back (id);
191 } else {
192 int64_t id = unit_id (-failed_unit);
193 lrat_chain.push_back (id);
194 }
195 }
196 proof->add_assumption_clause (++clause_id, -efailed, lrat_chain);
197 conclusion.push_back (clause_id);
198 lrat_chain.clear ();
199 }
200 goto DONE;
201 }
202
203 // Second case (2).
204 if (failed_clashing) {
205 CADICAL_assert (failed == failed_clashing);
206 LOG ("clashing assumptions %d and %d", failed, -failed);
207 Flags &f = flags (-failed);
208 const unsigned bit = bign (-failed);
209 CADICAL_assert (!(f.failed & bit));
210 f.failed |= bit;
211 if (proof) {
213 proof->add_assumption_clause (++clause_id, clash, lrat_chain);
214 conclusion.push_back (clause_id);
215 }
216 goto DONE;
217 }
218
219 // Fall through to third case (3).
220 LOG ("starting with assumption %d falsified on minimum decision level "
221 "%d",
222 first_failed, failed_level);
223
224 CADICAL_assert (first_failed);
225 CADICAL_assert (failed_level > 0);
226
227 // The 'analyzed' stack serves as working stack for a BFS through the
228 // implication graph until decisions, which are all assumptions, or
229 // units are reached. This is simpler than corresponding code in
230 // 'analyze'.
231 {
232 LOG ("failed assumption %d", first_failed);
233 Flags &f = flags (first_failed);
234 CADICAL_assert (!f.seen);
235 f.seen = true;
236 CADICAL_assert (f.failed & bign (first_failed));
237 analyzed.push_back (-first_failed);
238 clause.push_back (-first_failed);
239 }
240 } else {
241 // unsat_constraint
242 // The assumptions necessary to fail each literal in the constraint are
243 // collected.
244 for (auto lit : constraint) {
245 lit *= -1;
246 CADICAL_assert (lit != INT_MIN);
247 flags (lit).seen = true;
248 analyzed.push_back (lit);
249 }
250 }
251
252 {
253 // used for unsat_constraint lrat
254 vector<vector<int64_t>> constraint_chains;
255 vector<vector<int>> constraint_clauses;
256 vector<int> sum_constraints;
257 vector<int> econstraints;
258 for (auto &elit : external->constraint) {
259 int lit = external->e2i[abs (elit)];
260 if (elit < 0)
261 lit = -lit;
262 if (!lit)
263 continue;
264 Flags &f = flags (lit);
265 if (f.seen)
266 continue;
267 if (std::find (econstraints.begin (), econstraints.end (), elit) !=
268 econstraints.end ())
269 continue;
270 econstraints.push_back (elit);
271 }
272
273 // no LRAT do bfs as it was before
274 if (!lrat) {
275 size_t next = 0;
276 while (next < analyzed.size ()) {
277 const int lit = analyzed[next++];
278 CADICAL_assert (val (lit) > 0);
279 Var &v = var (lit);
280 if (!v.level)
281 continue;
282 if (v.reason == external_reason) {
284 if (!v.reason) {
285 v.level = 0;
286 continue;
287 }
288 }
290 if (v.reason) {
292 LOG (v.reason, "analyze reason");
293 for (const auto &other : *v.reason) {
294 Flags &f = flags (other);
295 if (f.seen)
296 continue;
297 f.seen = true;
298 CADICAL_assert (val (other) < 0);
299 analyzed.push_back (-other);
300 }
301 } else {
303 LOG ("failed assumption %d", lit);
304 clause.push_back (-lit);
305 Flags &f = flags (lit);
306 const unsigned bit = bign (lit);
307 CADICAL_assert (!(f.failed & bit));
308 f.failed |= bit;
309 }
310 }
312 } else if (!unsat_constraint) { // LRAT for case (3)
313 CADICAL_assert (clause.size () == 1);
314 const int lit = clause[0];
315 Var &v = var (lit);
317 if (v.reason == external_reason) { // does this even happen?
319 }
321 if (v.reason)
323 else {
324 int64_t id = unit_id (lit);
325 lrat_chain.push_back (id);
326 }
327 for (auto &lit : clause) {
328 Flags &f = flags (lit);
329 const unsigned bit = bign (-lit);
330 if (!(f.failed & bit))
331 f.failed |= bit;
332 }
334 } else { // LRAT for unsat_constraint
335 CADICAL_assert (clause.empty ());
337 for (auto lit : constraint) {
338 // make sure nothing gets marked failed twice
339 // also might shortcut the case where
340 // lrat_chain is empty because clause is tautological
341 CADICAL_assert (lit != INT_MIN);
343 vector<int64_t> empty;
344 vector<int> empty2;
345 constraint_chains.push_back (empty);
346 constraint_clauses.push_back (empty2);
347 for (auto ign : clause) {
348 constraint_clauses.back ().push_back (ign);
349 Flags &f = flags (ign);
350 const unsigned bit = bign (-ign);
351 if (!(f.failed & bit)) {
352 sum_constraints.push_back (ign);
353 CADICAL_assert (!(f.failed & bit));
354 f.failed |= bit;
355 }
356 }
357 clause.clear ();
359 for (auto p : lrat_chain) {
360 constraint_chains.back ().push_back (p);
361 }
362 lrat_chain.clear ();
363 }
364 for (auto &lit : sum_constraints)
365 clause.push_back (lit);
366 }
368
369 // Doing clause minimization here does not do anything because
370 // the clause already contains only one literal of each level
371 // and minimization can never reduce the number of levels
372
373 VERBOSE (1, "found %zd failed assumptions %.0f%%", clause.size (),
374 percent (clause.size (), assumptions.size ()));
375
376 // We do not actually need to learn this clause, since the conflict is
377 // forced already by some other clauses. There is also no bumping
378 // of variables nor clauses necessary. But we still want to check
379 // correctness of the claim that the determined subset of failing
380 // assumptions are a high-level core or equivalently their negations
381 // form a unit-implied clause.
382 //
383 if (!unsat_constraint) {
384 external->check_learned_clause ();
385 if (proof) {
386 vector<int> eclause;
387 for (auto &lit : clause)
388 eclause.push_back (externalize (lit));
389 proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
390 conclusion.push_back (clause_id);
391 }
392 } else {
393 CADICAL_assert (!lrat || (constraint.size () == constraint_clauses.size () &&
394 constraint.size () == constraint_chains.size ()));
395 for (auto p = constraint.rbegin (); p != constraint.rend (); p++) {
396 const auto &lit = *p;
397 if (lrat) {
398 clause.clear ();
399 for (auto &ign : constraint_clauses.back ())
400 clause.push_back (ign);
401 constraint_clauses.pop_back ();
402 }
403 clause.push_back (-lit);
404 external->check_learned_clause ();
405 if (proof) {
406 if (lrat) {
407 for (auto p : constraint_chains.back ()) {
408 lrat_chain.push_back (p);
409 }
410 constraint_chains.pop_back ();
411 LOG (lrat_chain, "assume proof chain with constraints");
412 }
413 vector<int> eclause;
414 for (auto &lit : clause)
415 eclause.push_back (externalize (lit));
416 proof->add_assumption_clause (++clause_id, eclause, lrat_chain);
417 conclusion.push_back (clause_id);
418 lrat_chain.clear ();
419 }
420 clause.pop_back ();
421 }
422 if (proof) {
423 for (auto &elit : econstraints) {
424 if (lrat) {
425 unsigned eidx = (elit > 0) + 2u * (unsigned) abs (elit);
426 CADICAL_assert ((size_t) eidx < external->ext_units.size ());
427 const int64_t id = external->ext_units[eidx];
428 if (id) {
429 lrat_chain.push_back (id);
430 } else {
431 int lit = external->e2i[abs (elit)];
432 if (elit < 0)
433 lit = -lit;
434 int64_t id = unit_id (-lit);
435 lrat_chain.push_back (id);
436 }
437 }
438 proof->add_assumption_clause (++clause_id, -elit, lrat_chain);
439 conclusion.push_back (clause_id);
440 lrat_chain.clear ();
441 }
442 }
443 }
444 lrat_chain.clear ();
445 clause.clear ();
446 }
447
448DONE:
449
450 STOP (analyze);
451}
452
454 if (!marked_failed) {
455 if (!conflict_id)
456 failing ();
457 marked_failed = true;
458 }
460 Flags &f = flags (lit);
461 const unsigned bit = bign (lit);
462 return (f.failed & bit) != 0;
463}
464
466 if (!proof || concluded)
467 return;
468 concluded = true;
469 if (!marked_failed) {
470 CADICAL_assert (conclusion.empty ());
471 if (!conflict_id)
472 failing ();
473 marked_failed = true;
474 }
475 ConclusionType con;
476 if (conflict_id)
477 con = CONFLICT;
478 else if (unsat_constraint)
479 con = CONSTRAINT;
480 else
481 con = ASSUMPTIONS;
482 proof->conclude_unsat (con, conclusion);
483}
484
486 if (proof)
487 proof->reset_assumptions ();
488 if (concluded) {
489 LOG ("reset concluded");
490 concluded = false;
491 }
492 if (conflict_id) {
493 CADICAL_assert (conclusion.size () == 1);
494 return;
495 }
496 conclusion.clear ();
497}
498
499// Add the start of each incremental phase (leaving the state
500// 'UNSATISFIABLE' actually) we reset all assumptions.
501
503 for (const auto &lit : assumptions) {
504 Flags &f = flags (lit);
505 const unsigned char bit = bign (lit);
506 f.assumed &= ~bit;
507 f.failed &= ~bit;
508 melt (lit);
509 }
510 LOG ("cleared %zd assumptions", assumptions.size ());
511 assumptions.clear ();
512 marked_failed = true;
513}
514
517
518 // Decision level could be 'INT_MAX' and thus 'level + 1' could overflow.
519 // Therefore we carefully have to use 'unsigned' for levels below.
520
521 const unsigned max_level;
522
524 : internal (s), max_level (s->level + 1u) {}
525
526 typedef uint64_t Type;
527
528 // Set assumptions first, then sorted by position on the trail
529 // unset literals are sorted by literal value.
530
531 Type operator() (const int &a) const {
532 const int val = internal->val (a);
533 const bool assigned = (val != 0);
534 const Var &v = internal->var (a);
535 uint64_t res = (assigned ? (unsigned) v.level : max_level);
536 res <<= 32;
537 res |= (assigned ? v.trail : abs (a));
538 return res;
539 }
540};
541
550
551// Sort the assumptions by the current position on the trail and backtrack
552// to the first place where the assumptions and the current trail differ.
553
555 CADICAL_assert (opts.ilbassumptions);
556 if (assumptions.empty ())
557 return;
558 MSORT (opts.radixsortlim, assumptions.begin (), assumptions.end (),
561
562 unsigned max_level = 0;
563 // assumptions are sorted by level, with unset at the end
564 for (auto lit : assumptions) {
565 if (val (lit))
566 max_level = var (lit).level;
567 else
568 break;
569 }
570
571 const unsigned size = min (level + 1u, max_level + 1);
572 CADICAL_assert ((size_t) level == control.size () - 1);
573 LOG (assumptions, "sorted assumptions");
574 int target = 0;
575 for (unsigned i = 1, j = 0; i < size;) {
576 const Level &l = control[i];
577 const int lit = l.decision;
578 const int alit = assumptions[j];
579 const int lev = i;
580 target = lev;
581 if (val (alit) > 0 &&
582 var (alit).level < lev) { // we can ignore propagated assumptions
583 LOG ("ILB skipping propagation %d", alit);
584 ++j;
585 continue;
586 }
587 if (!lit) { // skip fake decisions
588 target = lev - 1;
589 break;
590 }
591 ++i, ++j;
592 CADICAL_assert (var (lit).level == lev);
593 if (l.decision == alit) {
594 continue;
595 }
596 target = lev - 1;
597 LOG ("first different literal %d on the trail and %d from the "
598 "assumptions",
599 lit, alit);
600 break;
601 }
602 if (target < level)
603 backtrack (target);
604 LOG ("assumptions allow for reuse of trail up to level %d", level);
605 // COVER (target > 1);
606 if ((size_t) level > assumptions.size ())
607 stats.assumptionsreused += assumptions.size ();
608 else
609 stats.assumptionsreused += level;
610}
611} // namespace CaDiCaL
612
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
Cube * p
Definition exorList.c:222
@ DONE
Definition inflate.h:51
#define VERBOSE(...)
Definition message.hpp:58
unsigned bign(int lit)
Definition util.hpp:23
ConclusionType
Definition tracer.hpp:15
@ CONFLICT
Definition tracer.hpp:15
@ ASSUMPTIONS
Definition tracer.hpp:15
@ CONSTRAINT
Definition tracer.hpp:15
const char * flags()
double percent(double a, double b)
Definition util.hpp:21
#define STOP(P)
Definition profile.hpp:158
#define START(P)
Definition profile.hpp:150
#define MSORT(LIMIT, FIRST, LAST, RANK, LESS)
Definition radix.hpp:173
int lit
Definition satVec.h:130
unsigned char failed
Definition flags.hpp:43
unsigned char assumed
Definition flags.hpp:42
External * external
Definition internal.hpp:312
vector< int > analyzed
Definition internal.hpp:267
Var & var(int lit)
Definition internal.hpp:452
void assume_analyze_literal(int lit)
vector< int64_t > lrat_chain
Definition internal.hpp:210
Clause * wrapped_learn_external_reason_clause(int lit)
void assume_analyze_reason(int lit, Clause *reason)
vector< int > constraint
Definition internal.hpp:262
int externalize(int lit)
Clause * learn_external_reason_clause(int lit, int falsified_elit=0, bool no_backtrack=false)
vector< int64_t > conclusion
Definition internal.hpp:207
signed char val(int lit) const
int64_t unit_id(int lit) const
Definition internal.hpp:434
vector< int > assumptions
Definition internal.hpp:261
void backtrack(int target_level=0)
bool assumed(int lit)
Clause * external_reason
Definition internal.hpp:245
vector< Level > control
Definition internal.hpp:282
void melt(int lit)
void freeze(int lit)
vector< int > clause
Definition internal.hpp:260
int level
Definition var.hpp:19
int trail
Definition var.hpp:20
Clause * reason
Definition var.hpp:21
bool operator()(const int &a, const int &b) const
unsigned size
Definition vector.h:35