ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
cadical_lidruptracer.cpp
Go to the documentation of this file.
1#include "global.h"
2
3#include "internal.hpp"
4
6
7namespace CaDiCaL {
8
9/*------------------------------------------------------------------------*/
10
12 : internal (i), file (f), binary (b), num_clauses (0), size_clauses (0),
13 clauses (0), last_hash (0), last_id (0), last_clause (0)
14#ifndef CADICAL_QUIET
15 ,
16 added (0), deleted (0)
17#endif
18{
19 (void) internal;
20
21 // Initialize random number table for hash function.
22 //
23 Random random (42);
24 for (unsigned n = 0; n < num_nonces; n++) {
25 uint64_t nonce = random.next ();
26 if (!(nonce & 1))
27 nonce++;
28 CADICAL_assert (nonce), CADICAL_assert (nonce & 1);
29 nonces[n] = nonce;
30 }
31#ifndef CADICAL_NDEBUG
32 binary = b;
33#else
34 (void) b;
35#endif
36 piping = file->piping ();
37}
38
40 internal = i;
41 file->connect_internal (internal);
42 LOG ("LIDRUP TRACER connected to internal");
43}
44
46 LOG ("LIDRUP TRACER delete");
47 delete file;
48 for (size_t i = 0; i < size_clauses; i++)
49 for (LidrupClause *c = clauses[i], *next; c; c = next)
50 next = c->next, delete_clause (c);
51 delete[] clauses;
52}
53
54/*------------------------------------------------------------------------*/
55
56void LidrupTracer::enlarge_clauses () {
57 CADICAL_assert (num_clauses == size_clauses);
58 const uint64_t new_size_clauses = size_clauses ? 2 * size_clauses : 1;
59 LOG ("LIDRUP Tracer enlarging clauses of tracer from %" PRIu64
60 " to %" PRIu64,
61 (uint64_t) size_clauses, (uint64_t) new_size_clauses);
62 LidrupClause **new_clauses;
63 new_clauses = new LidrupClause *[new_size_clauses];
64 clear_n (new_clauses, new_size_clauses);
65 for (uint64_t i = 0; i < size_clauses; i++) {
66 for (LidrupClause *c = clauses[i], *next; c; c = next) {
67 next = c->next;
68 const uint64_t h = reduce_hash (c->hash, new_size_clauses);
69 c->next = new_clauses[h];
70 new_clauses[h] = c;
71 }
72 }
73 delete[] clauses;
74 clauses = new_clauses;
75 size_clauses = new_size_clauses;
76}
77
78LidrupClause *LidrupTracer::new_clause () {
79 LidrupClause *res = new LidrupClause;
80 res->next = 0;
81 res->hash = last_hash;
82 res->id = last_id;
83 for (const auto &id : imported_chain) {
84 res->chain.push_back (id);
85 }
86 for (const auto &lit : imported_clause) {
87 res->literals.push_back (lit);
88 }
89 last_clause = res;
90 num_clauses++;
91 return res;
92}
93
94void LidrupTracer::delete_clause (LidrupClause *c) {
96 num_clauses--;
97 delete c;
98}
99
100uint64_t LidrupTracer::reduce_hash (uint64_t hash, uint64_t size) {
101 CADICAL_assert (size > 0);
102 unsigned shift = 32;
103 uint64_t res = hash;
104 while ((((uint64_t) 1) << shift) > size) {
105 res ^= res >> shift;
106 shift >>= 1;
107 }
108 res &= size - 1;
109 CADICAL_assert (res < size);
110 return res;
111}
112
113uint64_t LidrupTracer::compute_hash (const int64_t id) {
114 CADICAL_assert (id > 0);
115 unsigned j = id % num_nonces;
116 uint64_t tmp = nonces[j] * (uint64_t) id;
117 return last_hash = tmp;
118}
119
120bool LidrupTracer::find_and_delete (const int64_t id) {
121 if (!num_clauses)
122 return false;
123 LidrupClause **res = 0, *c;
124 const uint64_t hash = compute_hash (id);
125 const uint64_t h = reduce_hash (hash, size_clauses);
126 for (res = clauses + h; (c = *res); res = &c->next) {
127 if (c->hash == hash && c->id == id) {
128 break;
129 }
130 if (!c->next)
131 return false;
132 }
133 if (!c)
134 return false;
135 CADICAL_assert (c && res);
136 *res = c->next;
137 for (auto &lit : c->literals) {
138 imported_clause.push_back (lit);
139 }
140 for (auto &cid : c->chain) {
141 imported_chain.push_back (cid);
142 }
143 delete_clause (c);
144 return true;
145}
146
147void LidrupTracer::insert () {
148 if (num_clauses == size_clauses)
149 enlarge_clauses ();
150 const uint64_t h = reduce_hash (compute_hash (last_id), size_clauses);
151 LidrupClause *c = new_clause ();
152 c->next = clauses[h];
153 clauses[h] = c;
154}
155
156/*------------------------------------------------------------------------*/
157
158inline void LidrupTracer::flush_if_piping () {
159 if (piping)
160 file->flush ();
161}
162
163inline void LidrupTracer::put_binary_zero () {
164 CADICAL_assert (binary);
165 CADICAL_assert (file);
166 file->put ((unsigned char) 0);
167}
168
169inline void LidrupTracer::put_binary_lit (int lit) {
170 CADICAL_assert (binary);
171 CADICAL_assert (file);
172 CADICAL_assert (lit != INT_MIN);
173 unsigned x = 2 * abs (lit) + (lit < 0);
174 unsigned char ch;
175 while (x & ~0x7f) {
176 ch = (x & 0x7f) | 0x80;
177 file->put (ch);
178 x >>= 7;
179 }
180 ch = x;
181 file->put (ch);
182}
183
184inline void LidrupTracer::put_binary_id (int64_t id, bool can_be_negative) {
185 CADICAL_assert (binary);
186 CADICAL_assert (file);
187 uint64_t x = abs (id);
188 if (can_be_negative) {
189 x = 2 * x + (id < 0);
190 }
191 unsigned char ch;
192 while (x & ~0x7f) {
193 ch = (x & 0x7f) | 0x80;
194 file->put (ch);
195 x >>= 7;
196 }
197 ch = x;
198 file->put (ch);
199}
200
201/*------------------------------------------------------------------------*/
202
203void LidrupTracer::lidrup_add_restored_clause (int64_t id) {
204 if (!batch_weaken.empty () || !batch_delete.empty ())
205 lidrup_batch_weaken_restore_and_delete ();
206 batch_restore.push_back (id);
207}
208
209void LidrupTracer::lidrup_add_derived_clause (
210 int64_t id, const vector<int> &clause, const vector<int64_t> &chain) {
211 lidrup_batch_weaken_restore_and_delete ();
212 if (binary) {
213 file->put ('l');
214 put_binary_id (id);
215 } else {
216 file->put ("l ");
217 file->put (id);
218 file->put (' ');
219 }
220 for (const auto &external_lit : clause)
221 if (binary)
222 put_binary_lit (external_lit);
223 else
224 file->put (external_lit), file->put (' ');
225 if (binary)
226 put_binary_zero ();
227 else
228 file->put ("0 ");
229 for (const auto &cid : chain)
230 if (binary)
231 put_binary_id (cid);
232 else
233 file->put (cid), file->put (' ');
234 if (binary)
235 put_binary_zero ();
236 else
237 file->put ("0\n");
238}
239
240void LidrupTracer::lidrup_add_original_clause (int64_t id,
241 const vector<int> &clause) {
242 lidrup_batch_weaken_restore_and_delete ();
243 if (binary) {
244 file->put ('i');
245 put_binary_id (id);
246 } else {
247 file->put ("i ");
248 file->put (id);
249 file->put (' ');
250 }
251 for (const auto &external_lit : clause)
252 if (binary)
253 put_binary_lit (external_lit);
254 else
255 file->put (external_lit), file->put (' ');
256 if (binary)
257 put_binary_zero ();
258 else
259 file->put ("0\n");
260}
261
262void LidrupTracer::lidrup_batch_weaken_restore_and_delete () {
263 CADICAL_assert (batch_weaken.empty () || batch_delete.empty ());
264 if (!batch_weaken.empty ()) {
265 if (binary) {
266 file->put ('w');
267 } else {
268 file->put ("w ");
269 }
270 for (const auto &id : batch_weaken) {
271 if (binary)
272 put_binary_id (id);
273 else
274 file->put (id), file->put (' ');
275 }
276 batch_weaken.clear ();
277 if (binary)
278 put_binary_zero ();
279 else
280 file->put ("0\n");
281#ifndef CADICAL_QUIET
282 batched++;
283#endif
284 }
285 if (!batch_delete.empty ()) {
286 if (binary) {
287 file->put ('d');
288 } else {
289 file->put ("d ");
290 }
291 for (const auto &id : batch_delete) {
292 if (binary)
293 put_binary_id (id);
294 else
295 file->put (id), file->put (' ');
296 }
297 batch_delete.clear ();
298 if (binary)
299 put_binary_zero ();
300 else
301 file->put ("0\n");
302#ifndef CADICAL_QUIET
303 batched++;
304#endif
305 }
306 if (!batch_restore.empty ()) {
307 if (binary) {
308 file->put ('r');
309 } else {
310 file->put ("r ");
311 }
312 for (const auto &id : batch_restore) {
313 if (binary)
314 put_binary_id (id);
315 else
316 file->put (id), file->put (' ');
317 }
318 batch_restore.clear ();
319 if (binary)
320 put_binary_zero ();
321 else
322 file->put ("0\n");
323#ifndef CADICAL_QUIET
324 batched++;
325#endif
326 }
327}
328
329void LidrupTracer::lidrup_conclude_and_delete (
330 const vector<int64_t> &conclusion) {
331 lidrup_batch_weaken_restore_and_delete ();
332 int64_t size = conclusion.size ();
333 if (size > 1) {
334 if (binary) {
335 file->put ('U');
336 put_binary_id (size);
337 } else {
338 file->put ("U ");
339 file->put (size), file->put ("\n");
340 }
341 }
342 for (auto &id : conclusion) {
343 if (binary)
344 file->put ('u');
345 else
346 file->put ("u ");
347 if (!find_and_delete (id)) {
348 CADICAL_assert (imported_clause.empty ());
349 CADICAL_assert (conclusion.size () == 1);
350 if (binary) {
351 put_binary_zero ();
352 put_binary_id (id);
353 put_binary_zero ();
354 } else {
355 file->put ("0 ");
356 file->put (id);
357 file->put (" 0\n");
358 }
359 } else {
360 for (const auto &external_lit : imported_clause) {
361 // flip sign...
362 const auto not_elit = -external_lit;
363 if (binary)
364 put_binary_lit (not_elit);
365 else
366 file->put (not_elit), file->put (' ');
367 }
368 if (binary)
369 put_binary_zero ();
370 else
371 file->put ("0 ");
372 for (const auto &cid : imported_chain) {
373 if (binary)
374 put_binary_id (cid);
375 else
376 file->put (cid), file->put (' ');
377 }
378 if (binary)
379 put_binary_zero ();
380 else
381 file->put ("0\n");
382 imported_clause.clear ();
383 imported_chain.clear ();
384 }
385 }
386 flush_if_piping ();
387}
388
389void LidrupTracer::lidrup_report_status (int status) {
390 lidrup_batch_weaken_restore_and_delete ();
391 if (binary)
392 file->put ('s');
393 else
394 file->put ("s ");
395 if (status == SATISFIABLE)
396 file->put ("SATISFIABLE");
397 else if (status == UNSATISFIABLE)
398 file->put ("UNSATISFIABLE");
399 else
400 file->put ("UNKNOWN");
401 if (!binary)
402 file->put ("\n");
403 flush_if_piping ();
404}
405
406void LidrupTracer::lidrup_conclude_sat (const vector<int> &model) {
407 lidrup_batch_weaken_restore_and_delete ();
408 if (binary)
409 file->put ('m');
410 else
411 file->put ("m ");
412 for (auto &lit : model) {
413 if (binary)
414 put_binary_lit (lit);
415 else
416 file->put (lit), file->put (' ');
417 }
418 if (binary)
419 put_binary_zero ();
420 else
421 file->put ("0\n");
422 flush_if_piping ();
423}
424
425void LidrupTracer::lidrup_conclude_unknown (const vector<int> &trail) {
426 lidrup_batch_weaken_restore_and_delete ();
427 if (binary)
428 file->put ('e');
429 else
430 file->put ("e ");
431 for (auto &lit : trail) {
432 if (binary)
433 put_binary_lit (lit);
434 else
435 file->put (lit), file->put (' ');
436 }
437 if (binary)
438 put_binary_zero ();
439 else
440 file->put ("0\n");
441 flush_if_piping ();
442}
443
444void LidrupTracer::lidrup_solve_query () {
445 lidrup_batch_weaken_restore_and_delete ();
446 if (binary)
447 file->put ('q');
448 else
449 file->put ("q ");
450 for (auto &lit : assumptions) {
451 if (binary)
452 put_binary_lit (lit);
453 else
454 file->put (lit), file->put (' ');
455 }
456 if (binary)
457 put_binary_zero ();
458 else
459 file->put ("0\n");
460 flush_if_piping ();
461}
462
463/*------------------------------------------------------------------------*/
464
465void LidrupTracer::add_derived_clause (int64_t id, bool,
466 const vector<int> &clause,
467 const vector<int64_t> &chain) {
468 if (file->closed ())
469 return;
470 CADICAL_assert (imported_clause.empty ());
471 LOG (clause, "LIDRUP TRACER tracing addition of derived clause");
472 lidrup_add_derived_clause (id, clause, chain);
473#ifndef CADICAL_QUIET
474 added++;
475#endif
476}
477
479 const vector<int> &clause,
480 const vector<int64_t> &chain) {
481 if (file->closed ())
482 return;
483 CADICAL_assert (imported_clause.empty ());
484 LOG (clause,
485 "LIDRUP TRACER tracing addition of assumption clause[%" PRId64 "]",
486 id);
487 for (auto &lit : clause)
488 imported_clause.push_back (lit);
489 for (auto &cid : chain)
490 imported_chain.push_back (cid);
491 last_id = id;
492 insert ();
493 imported_clause.clear ();
494 imported_chain.clear ();
495}
496
497void LidrupTracer::delete_clause (int64_t id, bool, const vector<int> &) {
498 if (file->closed ())
499 return;
500 CADICAL_assert (imported_clause.empty ());
501 LOG ("LIDRUP TRACER tracing deletion of clause[%" PRId64 "]", id);
502 if (find_and_delete (id)) {
503 CADICAL_assert (imported_clause.empty ());
504 if (!batch_delete.empty () || !batch_restore.empty ())
505 lidrup_batch_weaken_restore_and_delete ();
506 batch_weaken.push_back (id);
507#ifndef CADICAL_QUIET
508 weakened++;
509#endif
510 } else {
511 if (!batch_weaken.empty () || !batch_restore.empty ())
512 lidrup_batch_weaken_restore_and_delete ();
513 batch_delete.push_back (id);
514#ifndef CADICAL_QUIET
515 deleted++;
516#endif
517 }
518}
519
520void LidrupTracer::weaken_minus (int64_t id, const vector<int> &) {
521 if (file->closed ())
522 return;
523 CADICAL_assert (imported_clause.empty ());
524 LOG ("LIDRUP TRACER tracing weaken minus of clause[%" PRId64 "]", id);
525 last_id = id;
526 insert ();
527}
528
530 const vector<int64_t> &conclusion) {
531 if (file->closed ())
532 return;
533 CADICAL_assert (imported_clause.empty ());
534 LOG (conclusion, "LIDRUP TRACER tracing conclusion of clause(s)");
535 lidrup_conclude_and_delete (conclusion);
536}
537
539 const vector<int> &clause,
540 bool restored) {
541 if (file->closed ())
542 return;
543 if (!restored) {
544 LOG (clause, "LIDRUP TRACER tracing addition of original clause");
545#ifndef CADICAL_QUIET
546 original++;
547#endif
548 return lidrup_add_original_clause (id, clause);
549 }
550 CADICAL_assert (restored);
551 if (find_and_delete (id)) {
552 LOG (clause,
553 "LIDRUP TRACER the clause was not yet weakened, so no restore");
554 return;
555 }
556 LOG (clause, "LIDRUP TRACER tracing addition of restored clause");
557 lidrup_add_restored_clause (id);
558#ifndef CADICAL_QUIET
559 restore++;
560#endif
561}
562
563void LidrupTracer::report_status (int status, int64_t) {
564 if (file->closed ())
565 return;
566 LOG ("LIDRUP TRACER tracing report of status %d", status);
567 lidrup_report_status (status);
568}
569
571 if (file->closed ())
572 return;
573 LOG (model, "LIDRUP TRACER tracing conclusion of model");
574 lidrup_conclude_sat (model);
575}
576
578 if (file->closed ())
579 return;
580 LOG (entrailed, "LIDRUP TRACER tracing conclusion of UNK");
581 lidrup_conclude_unknown (entrailed);
582}
583
585 if (file->closed ())
586 return;
587 LOG (assumptions, "LIDRUP TRACER tracing solve query with assumptions");
588 lidrup_solve_query ();
589#ifndef CADICAL_QUIET
590 solved++;
591#endif
592}
593
595 LOG ("LIDRUP TRACER tracing addition of assumption %d", lit);
596 assumptions.push_back (lit);
597}
598
600 LOG (assumptions, "LIDRUP TRACER tracing reset of assumptions");
601 assumptions.clear ();
602}
603
604/*------------------------------------------------------------------------*/
605
606bool LidrupTracer::closed () { return file->closed (); }
607
608#ifndef CADICAL_QUIET
609
610void LidrupTracer::print_statistics () {
611 // TODO complete this.
612 uint64_t bytes = file->bytes ();
613 uint64_t total = added + deleted + weakened + restore + original;
614 MSG ("LIDRUP %" PRId64 " original clauses %.2f%%", original,
615 percent (original, total));
616 MSG ("LIDRUP %" PRId64 " learned clauses %.2f%%", added,
617 percent (added, total));
618 MSG ("LIDRUP %" PRId64 " deleted clauses %.2f%%", deleted,
619 percent (deleted, total));
620 MSG ("LIDRUP %" PRId64 " weakened clauses %.2f%%", weakened,
621 percent (weakened, total));
622 MSG ("LIDRUP %" PRId64 " restored clauses %.2f%%", restore,
623 percent (restore, total));
624 MSG ("LIDRUP %" PRId64 " batches of deletions, weaken and restores %.2f",
625 batched, relative (batched, deleted + restore + weakened));
626 MSG ("LIDRUP %" PRId64 " queries %.2f", solved, relative (solved, total));
627 MSG ("LIDRUP %" PRId64 " bytes (%.2f MB)", bytes,
628 bytes / (double) (1 << 20));
629}
630
631#endif
632
633void LidrupTracer::close (bool print) {
635 file->close ();
636#ifndef CADICAL_QUIET
637 if (print) {
638 MSG ("LIDRUP proof file '%s' closed", file->name ());
639 print_statistics ();
640 }
641#else
642 (void) print;
643#endif
644}
645
646void LidrupTracer::flush (bool print) {
648 lidrup_batch_weaken_restore_and_delete ();
649 file->flush ();
650#ifndef CADICAL_QUIET
651 if (print) {
652 MSG ("LIDRUP proof file '%s' flushed", file->name ());
653 print_statistics ();
654 }
655#else
656 (void) print;
657#endif
658}
659
660} // namespace CaDiCaL
661
#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(...)
void conclude_sat(const vector< int > &) override
void conclude_unsat(ConclusionType, const vector< int64_t > &) override
void conclude_unknown(const vector< int > &) override
void add_derived_clause(int64_t, bool, const vector< int > &, const vector< int64_t > &) override
void connect_internal(Internal *i) override
LidrupTracer(Internal *, File *file, bool)
void report_status(int, int64_t) override
void add_assumption(int) override
void add_original_clause(int64_t, bool, const vector< int > &, bool=false) override
void add_assumption_clause(int64_t, const vector< int > &, const vector< int64_t > &) override
void weaken_minus(int64_t, const vector< int > &) override
#define MSG(...)
Definition message.hpp:49
double relative(double a, double b)
Definition util.hpp:20
ConclusionType
Definition tracer.hpp:15
@ UNSATISFIABLE
Definition cadical.hpp:30
@ SATISFIABLE
Definition cadical.hpp:29
void clear_n(T *base, size_t n)
Definition util.hpp:149
double percent(double a, double b)
Definition util.hpp:21
unsigned long long size
Definition giaNewBdd.h:39
struct clause_t clause
STRUCTURE DEFINITIONS ///.
Definition satClause.h:48
int lit
Definition satVec.h:130
Definition file.h:23
uint64_t bytes
Definition file.h:29
unsigned size
Definition vector.h:35
long random()