ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_proof.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9using namespace std;
10
11/*------------------------------------------------------------------------*/
12
13// Enable proof logging and checking by allocating a 'Proof' object.
14
16 if (!proof) {
17 LOG ("connecting proof to internal solver");
18 proof = new Proof (this);
19 }
20}
21
23 size_t new_vsize = vsize ? 2 * vsize : 1 + (size_t) max_var;
24 unit_clauses_idx.resize (2 * new_vsize, 0);
25}
26
28 if (lrat)
29 return;
31 lrat = true;
32}
33
34void Internal::connect_proof_tracer (Tracer *tracer, bool antecedents,
35 bool finalize_clauses) {
37 if (antecedents)
38 force_lrat ();
39 if (finalize_clauses)
40 frat = true;
42 proof->connect (tracer);
43 tracers.push_back (tracer);
44}
45
47 bool antecedents,
48 bool finalize_clauses) {
50 if (antecedents)
51 force_lrat ();
52 if (finalize_clauses)
53 frat = true;
55 tracer->connect_internal (this);
56 proof->connect (tracer);
57 tracers.push_back (tracer);
58}
59
60void Internal::connect_proof_tracer (StatTracer *tracer, bool antecedents,
61 bool finalize_clauses) {
63 if (antecedents)
64 force_lrat ();
65 if (finalize_clauses)
66 frat = true;
68 tracer->connect_internal (this);
69 proof->connect (tracer);
70 stat_tracers.push_back (tracer);
71}
72
73void Internal::connect_proof_tracer (FileTracer *tracer, bool antecedents,
74 bool finalize_clauses) {
76 if (antecedents)
77 force_lrat ();
78 if (finalize_clauses)
79 frat = true;
81 tracer->connect_internal (this);
82 proof->connect (tracer);
83 file_tracers.push_back (tracer);
84}
85
87 auto it = std::find (tracers.begin (), tracers.end (), tracer);
88 if (it != tracers.end ()) {
89 tracers.erase (it);
91 proof->disconnect (tracer);
92 return true;
93 }
94 return false;
95}
96
98 auto it = std::find (stat_tracers.begin (), stat_tracers.end (), tracer);
99 if (it != stat_tracers.end ()) {
100 stat_tracers.erase (it);
102 proof->disconnect (tracer);
103 return true;
104 }
105 return false;
106}
107
109 auto it = std::find (file_tracers.begin (), file_tracers.end (), tracer);
110 if (it != file_tracers.end ()) {
111 file_tracers.erase (it);
113 proof->disconnect (tracer);
114 return true;
115 }
116 return false;
117}
118
120 tracers.erase (std::remove (tracers.begin (), tracers.end (), t),
121 tracers.end ());
122}
123
124// Enable proof tracing.
125
127 if (opts.veripb) {
128 LOG ("PROOF connecting VeriPB tracer");
129 bool antecedents = opts.veripb == 1 || opts.veripb == 2;
130 bool deletions = opts.veripb == 2 || opts.veripb == 4;
131 FileTracer *ft =
132 new VeripbTracer (this, file, opts.binary, antecedents, deletions);
133 connect_proof_tracer (ft, antecedents);
134 } else if (opts.frat) {
135 LOG ("PROOF connecting FRAT tracer");
136 bool antecedents = opts.frat == 1;
138 FileTracer *ft =
139 new FratTracer (this, file, opts.binary, opts.frat == 1);
140 connect_proof_tracer (ft, antecedents, true);
141 } else if (opts.lrat) {
142 LOG ("PROOF connecting LRAT tracer");
143 FileTracer *ft = new LratTracer (this, file, opts.binary);
144 connect_proof_tracer (ft, true);
145 } else if (opts.idrup) {
146 LOG ("PROOF connecting IDRUP tracer");
147 FileTracer *ft = new IdrupTracer (this, file, opts.binary);
148 connect_proof_tracer (ft, true);
149 } else if (opts.lidrup) {
150 LOG ("PROOF connecting LIDRUP tracer");
151 FileTracer *ft = new LidrupTracer (this, file, opts.binary);
152 connect_proof_tracer (ft, true);
153 } else {
154 LOG ("PROOF connecting DRAT tracer");
155 FileTracer *ft = new DratTracer (this, file, opts.binary);
156 connect_proof_tracer (ft, false);
157 }
158}
159
160// Enable proof checking.
161
164 if (opts.checkproof > 1) {
165 StatTracer *lratchecker = new LratChecker (this);
166 DeferDeletePtr<LratChecker> delete_lratchecker (
167 (LratChecker *) lratchecker);
168 LOG ("PROOF connecting LRAT proof checker");
169 force_lrat ();
170 frat = true;
172 proof->connect (lratchecker);
173 stat_tracers.push_back (lratchecker);
174 delete_lratchecker.release ();
175 }
176 if (opts.checkproof == 1 || opts.checkproof == 3) {
177 StatTracer *checker = new Checker (this);
178 DeferDeletePtr<Checker> delete_checker ((Checker *) checker);
179 LOG ("PROOF connecting proof checker");
180 proof->connect (checker);
181 stat_tracers.push_back (checker);
182 delete_checker.release ();
183 }
184}
185
186// We want to close a proof trace and stop checking as soon we are done.
187
188void Internal::close_trace (bool print) {
189 for (auto &tracer : file_tracers)
190 tracer->close (print);
191}
192
193// We can flush a proof trace file before actually closing it.
194
195void Internal::flush_trace (bool print) {
196 for (auto &tracer : file_tracers)
197 tracer->flush (print);
198}
199
200/*------------------------------------------------------------------------*/
201
202Proof::Proof (Internal *s) : internal (s) { LOG ("PROOF new"); }
203
204Proof::~Proof () { LOG ("PROOF delete"); }
205
206/*------------------------------------------------------------------------*/
207
208inline void Proof::add_literal (int internal_lit) {
209 const int external_lit = internal->externalize (internal_lit);
210 clause.push_back (external_lit);
211}
212
213inline void Proof::add_literals (Clause *c) {
214 for (auto const &lit : *c)
215 add_literal (lit);
216}
217
218inline void Proof::add_literals (const vector<int> &c) {
219 for (auto const &lit : c)
220 add_literal (lit);
221}
222
223/*------------------------------------------------------------------------*/
224
225void Proof::add_original_clause (int64_t id, bool r, const vector<int> &c) {
226 LOG (c, "PROOF adding original internal clause");
227 add_literals (c);
228 clause_id = id;
229 redundant = r;
230 add_original_clause ();
231}
232
233void Proof::add_external_original_clause (int64_t id, bool r,
234 const vector<int> &c,
235 bool restore) {
236 // literals of c are already external
237 CADICAL_assert (clause.empty ());
238 for (auto const &lit : c)
239 clause.push_back (lit);
240 clause_id = id;
241 redundant = r;
242 add_original_clause (restore);
243}
244
246 const vector<int> &c) {
247 // literals of c are already external
248 CADICAL_assert (clause.empty ());
249 for (auto const &lit : c)
250 clause.push_back (lit);
251 clause_id = id;
252 redundant = r;
253 delete_clause ();
254}
255
257 const vector<int64_t> &chain) {
258 LOG ("PROOF adding empty clause");
259 CADICAL_assert (clause.empty ());
260 CADICAL_assert (proof_chain.empty ());
261 for (const auto &cid : chain)
262 proof_chain.push_back (cid);
263 clause_id = id;
264 redundant = false;
265 add_derived_clause ();
266}
267
268void Proof::add_derived_unit_clause (int64_t id, int internal_unit,
269 const vector<int64_t> &chain) {
270 LOG ("PROOF adding unit clause %d", internal_unit);
271 CADICAL_assert (proof_chain.empty ());
272 CADICAL_assert (clause.empty ());
273 add_literal (internal_unit);
274 for (const auto &cid : chain)
275 proof_chain.push_back (cid);
276 clause_id = id;
277 redundant = false;
278 add_derived_clause ();
279}
280
281/*------------------------------------------------------------------------*/
282
283void Proof::add_derived_clause (Clause *c, const vector<int64_t> &chain) {
284 LOG (c, "PROOF adding to proof derived");
285 CADICAL_assert (clause.empty ());
286 CADICAL_assert (proof_chain.empty ());
287 add_literals (c);
288 for (const auto &cid : chain)
289 proof_chain.push_back (cid);
290 clause_id = c->id;
291 redundant = c->redundant;
292 add_derived_clause ();
293}
294
295void Proof::add_derived_clause (int64_t id, bool r, const vector<int> &c,
296 const vector<int64_t> &chain) {
297 LOG (c, "PROOF adding derived clause");
298 CADICAL_assert (clause.empty ());
299 CADICAL_assert (proof_chain.empty ());
300 for (const auto &lit : c)
301 add_literal (lit);
302 for (const auto &cid : chain)
303 proof_chain.push_back (cid);
304 clause_id = id;
305 redundant = r;
306 add_derived_clause ();
307}
308
309void Proof::add_assumption_clause (int64_t id, const vector<int> &c,
310 const vector<int64_t> &chain) {
311 // literals of c are already external
312 CADICAL_assert (clause.empty ());
313 CADICAL_assert (proof_chain.empty ());
314 for (const auto &lit : c)
315 clause.push_back (lit);
316 for (const auto &cid : chain)
317 proof_chain.push_back (cid);
318 clause_id = id;
319 add_assumption_clause ();
320}
321
322void Proof::add_assumption (int a) {
323 // a is already external
324 CADICAL_assert (clause.empty ());
325 CADICAL_assert (proof_chain.empty ());
326 clause.push_back (a);
327 add_assumption ();
328}
329
330void Proof::add_constraint (const vector<int> &c) {
331 // literals of c are already external
332 CADICAL_assert (clause.empty ());
333 CADICAL_assert (proof_chain.empty ());
334 for (const auto &lit : c)
335 clause.push_back (lit);
336 add_constraint ();
337}
338
339void Proof::add_assumption_clause (int64_t id, int lit,
340 const vector<int64_t> &chain) {
341 CADICAL_assert (clause.empty ());
342 CADICAL_assert (proof_chain.empty ());
343 clause.push_back (lit);
344 for (const auto &cid : chain)
345 proof_chain.push_back (cid);
346 clause_id = id;
347 add_assumption_clause ();
348}
349
350void Proof::delete_clause (Clause *c) {
351 LOG (c, "PROOF deleting from proof");
352 clause.clear (); // Can be non-empty if an allocation fails during adding.
353 add_literals (c);
354 clause_id = c->id;
355 redundant = c->redundant;
356 delete_clause (); // Increments 'statistics.deleted'.
357}
358
359void Proof::delete_clause (int64_t id, bool r, const vector<int> &c) {
360 LOG (c, "PROOF deleting from proof");
361 CADICAL_assert (clause.empty ());
362 add_literals (c);
363 clause_id = id;
364 redundant = r;
365 delete_clause (); // Increments 'statistics.deleted'.
366}
367
368void Proof::weaken_minus (Clause *c) {
369 LOG (c, "PROOF weaken minus of");
370 CADICAL_assert (clause.empty ());
371 add_literals (c);
372 clause_id = c->id;
373 weaken_minus ();
374}
375
376void Proof::weaken_minus (int64_t id, const vector<int> &c) {
377 LOG (c, "PROOF deleting from proof");
378 CADICAL_assert (clause.empty ());
379 add_literals (c);
380 clause_id = id;
381 weaken_minus ();
382}
383
385 weaken_minus (c);
386 delete_clause (c); // Increments 'statistics.deleted'.
387}
388
389void Proof::weaken_plus (int64_t id, const vector<int> &c) {
390 weaken_minus (id, c);
391 delete_clause (id, false, c); // Increments 'statistics.deleted'.
392}
393
394void Proof::delete_unit_clause (int64_t id, const int lit) {
395 LOG ("PROOF deleting unit from proof %d", lit);
396 CADICAL_assert (clause.empty ());
397 add_literal (lit);
398 clause_id = id;
399 redundant = false;
400 delete_clause ();
401}
402
403void Proof::finalize_clause (Clause *c) {
404 LOG (c, "PROOF finalizing clause");
405 CADICAL_assert (clause.empty ());
406 add_literals (c);
407 clause_id = c->id;
408 finalize_clause ();
409}
410
411void Proof::finalize_clause (int64_t id, const vector<int> &c) {
412 LOG (c, "PROOF finalizing clause");
413 CADICAL_assert (clause.empty ());
414 for (const auto &lit : c)
415 add_literal (lit);
416 clause_id = id;
417 finalize_clause ();
418}
419
420void Proof::finalize_unit (int64_t id, int lit) {
421 LOG ("PROOF finalizing clause %d", lit);
422 CADICAL_assert (clause.empty ());
423 add_literal (lit);
424 clause_id = id;
425 finalize_clause ();
426}
427
428void Proof::finalize_external_unit (int64_t id, int lit) {
429 LOG ("PROOF finalizing clause %d", lit);
430 CADICAL_assert (clause.empty ());
431 clause.push_back (lit);
432 clause_id = id;
433 finalize_clause ();
434}
435
436/*------------------------------------------------------------------------*/
437
438// During garbage collection clauses are shrunken by removing falsified
439// literals. To avoid copying the clause, we provide a specialized tracing
440// function here, which traces the required 'add' and 'remove' operations.
441
443 LOG (c, "PROOF flushing falsified literals in");
444 CADICAL_assert (clause.empty ());
445 const bool antecedents = (internal->lrat || internal->frat);
446 for (int i = 0; i < c->size; i++) {
447 int internal_lit = c->literals[i];
448 if (internal->fixed (internal_lit) < 0) {
449 if (antecedents) {
450 int64_t id = internal->unit_id (-internal_lit);
451 proof_chain.push_back (id);
452 }
453 continue;
454 }
455 add_literal (internal_lit);
456 }
457 proof_chain.push_back (c->id);
458 redundant = c->redundant;
459 int64_t id = ++internal->clause_id;
460 clause_id = id;
461 add_derived_clause ();
462 delete_clause (c);
463 c->id = id;
464}
465
466// While strengthening clauses, e.g., through self-subsuming resolutions,
467// during subsumption checking, we have a similar situation, except that we
468// have to remove exactly one literal. Again the following function allows
469// to avoid copying the clause and instead provides tracing of the required
470// 'add' and 'remove' operations.
471
472void Proof::strengthen_clause (Clause *c, int remove,
473 const vector<int64_t> &chain) {
474 LOG (c, "PROOF strengthen by removing %d in", remove);
475 CADICAL_assert (clause.empty ());
476 for (int i = 0; i < c->size; i++) {
477 int internal_lit = c->literals[i];
478 if (internal_lit == remove)
479 continue;
480 add_literal (internal_lit);
481 }
482 int64_t id = ++internal->clause_id;
483 clause_id = id;
484 redundant = c->redundant;
485 for (const auto &cid : chain)
486 proof_chain.push_back (cid);
487 add_derived_clause ();
488 delete_clause (c);
489 c->id = id;
490}
491
492void Proof::otfs_strengthen_clause (Clause *c, const std::vector<int> &old,
493 const vector<int64_t> &chain) {
494 LOG (c, "PROOF otfs strengthen");
495 CADICAL_assert (clause.empty ());
496 for (int i = 0; i < c->size; i++) {
497 int internal_lit = c->literals[i];
498 add_literal (internal_lit);
499 }
500 int64_t id = ++internal->clause_id;
501 clause_id = id;
502 redundant = c->redundant;
503 for (const auto &cid : chain)
504 proof_chain.push_back (cid);
505 add_derived_clause ();
506 delete_clause (c->id, c->redundant, old);
507 c->id = id;
508}
509
510void Proof::strengthen (int64_t id) {
511 clause_id = id;
512 strengthen ();
513}
514
515/*------------------------------------------------------------------------*/
516
517void Proof::add_original_clause (bool restore) {
518 LOG (clause, "PROOF adding original external clause");
519 CADICAL_assert (clause_id);
520
521 for (auto &tracer : tracers) {
522 tracer->add_original_clause (clause_id, false, clause, restore);
523 }
524 clause.clear ();
525 clause_id = 0;
526}
527
528void Proof::add_derived_clause () {
529 LOG (clause, "PROOF adding derived external clause (redundant: %d)",
530 redundant);
531 CADICAL_assert (clause_id);
532 for (auto &tracer : tracers) {
533 tracer->add_derived_clause (clause_id, redundant, clause, proof_chain);
534 }
535 proof_chain.clear ();
536 clause.clear ();
537 clause_id = 0;
538}
539
540void Proof::delete_clause () {
541 LOG (clause, "PROOF deleting external clause");
542 for (auto &tracer : tracers) {
543 tracer->delete_clause (clause_id, redundant, clause);
544 }
545 clause.clear ();
546 clause_id = 0;
547}
548
549void Proof::demote_clause () {
550 LOG (clause, "PROOF demoting external clause");
551 CADICAL_assert (!redundant);
552 for (auto &tracer : tracers) {
553 tracer->demote_clause (clause_id, clause);
554 }
555 clause.clear ();
556 clause_id = 0;
557}
558
559void Proof::weaken_minus () {
560 LOG (clause, "PROOF marking as clause to restore");
561 for (auto &tracer : tracers) {
562 tracer->weaken_minus (clause_id, clause);
563 }
564 clause.clear ();
565 clause_id = 0;
566}
567
568void Proof::strengthen () {
569 LOG ("PROOF strengthen clause with id %" PRId64, clause_id);
570 for (auto &tracer : tracers) {
571 tracer->strengthen (clause_id);
572 }
573 clause_id = 0;
574}
575
576void Proof::finalize_clause () {
577 for (auto &tracer : tracers) {
578 tracer->finalize_clause (clause_id, clause);
579 }
580 clause.clear ();
581 clause_id = 0;
582}
583
584void Proof::add_assumption_clause () {
585 LOG (clause, "PROOF adding assumption clause");
586 for (auto &tracer : tracers) {
587 tracer->add_assumption_clause (clause_id, clause, proof_chain);
588 }
589 proof_chain.clear ();
590 clause.clear ();
591 clause_id = 0;
592}
593
594void Proof::add_assumption () {
595 LOG (clause, "PROOF adding assumption");
596 CADICAL_assert (clause.size () == 1);
597 for (auto &tracer : tracers) {
598 tracer->add_assumption (clause.back ());
599 }
600 clause.clear ();
601}
602
603void Proof::add_constraint () {
604 LOG (clause, "PROOF adding constraint");
605 for (auto &tracer : tracers) {
606 tracer->add_constraint (clause);
607 }
608 clause.clear ();
609}
610
612 LOG ("PROOF reset assumptions");
613 for (auto &tracer : tracers) {
614 tracer->reset_assumptions ();
615 }
616}
617
618void Proof::report_status (int status, int64_t id) {
619 LOG ("PROOF reporting status %d", status);
620 for (auto &tracer : tracers) {
621 tracer->report_status (status, id);
622 }
623}
624
625void Proof::begin_proof (int64_t id) {
626 LOG (clause, "PROOF begin proof");
627 for (auto &tracer : tracers) {
628 tracer->begin_proof (id);
629 }
630}
631
633 LOG (clause, "PROOF solve query");
634 for (auto &tracer : tracers) {
635 tracer->solve_query ();
636 }
637}
638
640 const vector<int64_t> &conclusion) {
641 LOG (clause, "PROOF conclude unsat");
642 for (auto &tracer : tracers) {
643 tracer->conclude_unsat (con, conclusion);
644 }
645}
646
647void Proof::conclude_sat (const vector<int> &model) {
648 LOG (clause, "PROOF conclude sat");
649 for (auto &tracer : tracers) {
650 tracer->conclude_sat (model);
651 }
652}
653
655 LOG (clause, "PROOF conclude unknown");
656 for (auto &tracer : tracers) {
657 tracer->conclude_unknown (trail);
658 }
659}
660
661} // namespace CaDiCaL
662
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define CADICAL_assert(ignore)
Definition global.h:14
#define LOG(...)
Proof(Internal *)
void disconnect(Tracer *t)
void finalize_unit(int64_t, int)
void delete_unit_clause(int64_t id, const int lit)
void conclude_unknown(const vector< int > &trace)
void weaken_plus(int64_t, const vector< int > &)
void strengthen_clause(Clause *, int, const vector< int64_t > &)
void begin_proof(int64_t)
void delete_external_original_clause(int64_t, bool, const vector< int > &)
void finalize_external_unit(int64_t, int)
void otfs_strengthen_clause(Clause *, const vector< int > &, const vector< int64_t > &)
void add_derived_unit_clause(int64_t, int unit, const vector< int64_t > &)
void report_status(int, int64_t)
void add_derived_empty_clause(int64_t, const vector< int64_t > &)
void flush_clause(Clause *)
void conclude_sat(const vector< int > &model)
void conclude_unsat(ConclusionType, const vector< int64_t > &)
void add_external_original_clause(int64_t, bool, const vector< int > &, bool restore=false)
ConclusionType
Definition tracer.hpp:15
int lit
Definition satVec.h:130
virtual void connect_internal(Internal *)
Definition tracer.hpp:157
void flush_trace(bool stats=false)
vector< StatTracer * > stat_tracers
Definition internal.hpp:299
vector< int64_t > unit_clauses_idx
Definition internal.hpp:209
void close_trace(bool stats=false)
vector< Tracer * > tracers
Definition internal.hpp:296
bool disconnect_proof_tracer(Tracer *tracer)
int externalize(int lit)
void connect_proof_tracer(Tracer *tracer, bool antecedents, bool finalize_clauses=false)
vector< FileTracer * > file_tracers
Definition internal.hpp:298
Definition file.h:23