ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
proof.c
Go to the documentation of this file.
1#include "global.h"
2
3#ifndef KISSAT_NPROOFS
4
5#include "allocate.h"
6#include "error.h"
7#include "file.h"
8#include "inline.h"
9
10#undef KISSAT_NDEBUG
11
12#ifndef KISSAT_NDEBUG
13#include <string.h>
14#endif
15
16#define size_buffer (1u << 20)
17
18struct write_buffer {
19 unsigned char chars[size_buffer];
20 size_t pos;
21};
22
23typedef struct write_buffer write_buffer;
24
25struct proof {
26 write_buffer buffer;
28 bool binary;
29 file *file;
30 ints line;
31 uint64_t added;
32 uint64_t deleted;
33 uint64_t lines;
34 uint64_t literals;
35#ifndef KISSAT_NDEBUG
36 bool empty;
37 char *units;
38 size_t size_units;
39#endif
40#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
41 unsigneds imported;
42#endif
43};
44
45#undef LOGPREFIX
46#define LOGPREFIX "PROOF"
47
48#define LOGIMPORTED3(...) \
49 LOGLITS3 (SIZE_STACK (proof->imported), BEGIN_STACK (proof->imported), \
50 __VA_ARGS__)
51
52#define LOGLINE3(...) \
53 LOGINTS3 (SIZE_STACK (proof->line), BEGIN_STACK (proof->line), \
54 __VA_ARGS__)
55
56void kissat_init_proof (kissat *solver, file *file, bool binary) {
58 KISSAT_assert (!solver->proof);
59 proof *proof = kissat_calloc (solver, 1, sizeof (struct proof));
60 proof->binary = binary;
61 proof->file = file;
62 proof->solver = solver;
63 solver->proof = proof;
64 LOG ("starting to trace %s proof", binary ? "binary" : "non-binary");
65}
66
67static void flush_buffer (proof *proof) {
68 size_t bytes = proof->buffer.pos;
69 if (!bytes)
70 return;
71 size_t written = kissat_write (proof->file, proof->buffer.chars, bytes);
72 if (bytes != written)
73 kissat_fatal ("flushing %zu bytes in proof write-buffer failed", bytes);
74 proof->buffer.pos = 0;
75}
76
77void kissat_release_proof (kissat *solver) {
78 proof *proof = solver->proof;
79 KISSAT_assert (proof);
80 LOG ("stopping to trace proof");
81 flush_buffer (proof);
82 kissat_flush (proof->file);
83 RELEASE_STACK (proof->line);
84#ifndef KISSAT_NDEBUG
85 kissat_free (solver, proof->units, proof->size_units);
86#endif
87#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
88 RELEASE_STACK (proof->imported);
89#endif
90 kissat_free (solver, proof, sizeof (struct proof));
91 solver->proof = 0;
92}
93
94#ifndef KISSAT_QUIET
95
96#include <inttypes.h>
97
98#define PERCENT_LINES(NAME) kissat_percent (proof->NAME, proof->lines)
99
100void kissat_print_proof_statistics (kissat *solver, bool verbose) {
101 proof *proof = solver->proof;
102 PRINT_STAT ("proof_added", proof->added, PERCENT_LINES (added), "%",
103 "per line");
104 PRINT_STAT ("proof_bytes", proof->file->bytes,
105 proof->file->bytes / (double) (1 << 20), "MB", "");
106 PRINT_STAT ("proof_deleted", proof->deleted, PERCENT_LINES (deleted), "%",
107 "per line");
108 if (verbose)
109 PRINT_STAT ("proof_lines", proof->lines, 100, "%", "");
110 if (verbose)
111 PRINT_STAT ("proof_literals", proof->literals,
112 kissat_average (proof->literals, proof->lines), "",
113 "per line");
114}
115
116#endif
117
118// clang-format off
119
120static inline void write_char (proof *, unsigned char)
122
123static inline void import_external_proof_literal (kissat *, proof *, int)
125
126static inline void
127import_internal_proof_literal (kissat *, proof *, unsigned)
129
130// clang-format on
131
132static inline void write_char (proof *proof, unsigned char ch) {
133 write_buffer *buffer = &proof->buffer;
134 if (buffer->pos == size_buffer)
135 flush_buffer (proof);
136 buffer->chars[buffer->pos++] = ch;
137}
138
139static inline void import_internal_proof_literal (kissat *solver,
140 proof *proof,
141 unsigned ilit) {
142 int elit = kissat_export_literal (solver, ilit);
143 KISSAT_assert (elit);
144 PUSH_STACK (proof->line, elit);
145 proof->literals++;
146#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
147 PUSH_STACK (proof->imported, ilit);
148#endif
149}
150
151static inline void import_external_proof_literal (kissat *solver,
152 proof *proof, int elit) {
153 KISSAT_assert (elit);
154 PUSH_STACK (proof->line, elit);
155 proof->literals++;
156#ifndef KISSAT_NDEBUG
157 KISSAT_assert (EMPTY_STACK (proof->imported));
158#endif
159}
160
161static void import_internal_proof_binary (kissat *solver, proof *proof,
162 unsigned a, unsigned b) {
163 KISSAT_assert (EMPTY_STACK (proof->line));
164 import_internal_proof_literal (solver, proof, a);
165 import_internal_proof_literal (solver, proof, b);
166}
167
168static void import_internal_proof_literals (kissat *solver, proof *proof,
169 size_t size,
170 const unsigned *ilits) {
171 KISSAT_assert (EMPTY_STACK (proof->line));
172 KISSAT_assert (size <= UINT_MAX);
173 for (size_t i = 0; i < size; i++)
174 import_internal_proof_literal (solver, proof, ilits[i]);
175}
176
177static void import_external_proof_literals (kissat *solver, proof *proof,
178 size_t size, const int *elits) {
179 KISSAT_assert (EMPTY_STACK (proof->line));
180 KISSAT_assert (size <= UINT_MAX);
181 for (size_t i = 0; i < size; i++)
182 import_external_proof_literal (solver, proof, elits[i]);
183}
184
185static void import_proof_clause (kissat *solver, proof *proof,
186 const clause *c) {
187 import_internal_proof_literals (solver, proof, c->size, c->lits);
188}
189
190static void print_binary_proof_line (proof *proof) {
191 KISSAT_assert (proof->binary);
192 for (all_stack (int, elit, proof->line)) {
193 unsigned x = 2u * ABS (elit) + (elit < 0);
194 unsigned char ch;
195 while (x & ~0x7f) {
196 ch = (x & 0x7f) | 0x80;
197 write_char (proof, ch);
198 x >>= 7;
199 }
200 write_char (proof, x);
201 }
202 write_char (proof, 0);
203}
204
205static void print_non_binary_proof_line (proof *proof) {
206 KISSAT_assert (!proof->binary);
207 char buffer[16];
208 char *end_of_buffer = buffer + sizeof buffer;
209 *--end_of_buffer = 0;
210 for (all_stack (int, elit, proof->line)) {
211 char *p = end_of_buffer;
212 KISSAT_assert (!*p);
213 KISSAT_assert (elit);
214 KISSAT_assert (elit != INT_MIN);
215 unsigned eidx;
216 if (elit < 0) {
217 write_char (proof, '-');
218 eidx = -elit;
219 } else
220 eidx = elit;
221 for (unsigned tmp = eidx; tmp; tmp /= 10)
222 *--p = '0' + (tmp % 10);
223 while (p != end_of_buffer)
224 write_char (proof, *p++);
225 write_char (proof, ' ');
226 }
227 write_char (proof, '0');
228 write_char (proof, '\n');
229}
230
231static void print_proof_line (proof *proof) {
232 proof->lines++;
233 if (proof->binary)
234 print_binary_proof_line (proof);
235 else
236 print_non_binary_proof_line (proof);
237 CLEAR_STACK (proof->line);
238#if !defined(KISSAT_NDEBUG) || defined(LOGGING)
239 CLEAR_STACK (proof->imported);
240#endif
241#ifndef KISSAT_NOPTIONS
242 kissat *solver = proof->solver;
243#endif
244 if (GET_OPTION (flushproof)) {
245 flush_buffer (proof);
246 kissat_flush (proof->file);
247 }
248}
249
250#ifndef KISSAT_NDEBUG
251
252static unsigned external_to_proof_literal (int elit) {
253 KISSAT_assert (elit);
254 KISSAT_assert (elit != INT_MIN);
255 return 2u * (abs (elit) - 1) + (elit < 0);
256}
257
258static void resize_proof_units (proof *proof, unsigned plit) {
259 kissat *solver = proof->solver;
260 const size_t old_size = proof->size_units;
261 size_t new_size = old_size ? old_size : 2;
262 while (new_size <= plit)
263 new_size *= 2;
264 char *new_units = kissat_calloc (solver, new_size, 1);
265 if (old_size)
266 memcpy (new_units, proof->units, old_size);
267 kissat_dealloc (solver, proof->units, old_size, 1);
268 proof->units = new_units;
269 proof->size_units = new_size;
270}
271
272static void check_repeated_proof_lines (proof *proof) {
273 size_t size = SIZE_STACK (proof->line);
274 if (!size) {
275 KISSAT_assert (!proof->empty);
276 proof->empty = true;
277 } else if (size == 1) {
278 const int eunit = PEEK_STACK (proof->line, 0);
279 const unsigned punit = external_to_proof_literal (eunit);
280 KISSAT_assert (punit != INVALID_LIT);
281 if (!proof->size_units || proof->size_units <= punit)
282 resize_proof_units (proof, punit);
283 proof->units[punit] = 1;
284 }
285}
286
287#endif
288
289static void print_added_proof_line (proof *proof) {
290 proof->added++;
291#ifdef LOGGING
292 struct kissat *solver = proof->solver;
293 KISSAT_assert (SIZE_STACK (proof->imported) == SIZE_STACK (proof->line));
294 LOGIMPORTED3 ("added proof line");
295 LOGLINE3 ("added proof line");
296#endif
297#ifndef KISSAT_NDEBUG
298 check_repeated_proof_lines (proof);
299#endif
300 if (proof->binary)
301 write_char (proof, 'a');
302 print_proof_line (proof);
303}
304
305static void print_delete_proof_line (proof *proof) {
306 proof->deleted++;
307#ifdef LOGGING
308 struct kissat *solver = proof->solver;
309 if (SIZE_STACK (proof->imported) == SIZE_STACK (proof->line))
310 LOGIMPORTED3 ("deleted internal proof line");
311 LOGLINE3 ("deleted external proof line");
312#endif
313 write_char (proof, 'd');
314 if (!proof->binary)
315 write_char (proof, ' ');
316 print_proof_line (proof);
317}
318
319void kissat_add_binary_to_proof (kissat *solver, unsigned a, unsigned b) {
320 proof *proof = solver->proof;
321 KISSAT_assert (proof);
322 import_internal_proof_binary (solver, proof, a, b);
323 print_added_proof_line (proof);
324}
325
326void kissat_add_clause_to_proof (kissat *solver, const clause *c) {
327 proof *proof = solver->proof;
328 KISSAT_assert (proof);
329 import_proof_clause (solver, proof, c);
330 print_added_proof_line (proof);
331}
332
333void kissat_add_empty_to_proof (kissat *solver) {
334 proof *proof = solver->proof;
335 KISSAT_assert (proof);
336 KISSAT_assert (EMPTY_STACK (proof->line));
337 print_added_proof_line (proof);
338}
339
340void kissat_add_lits_to_proof (kissat *solver, size_t size,
341 const unsigned *ilits) {
342 proof *proof = solver->proof;
343 KISSAT_assert (proof);
344 import_internal_proof_literals (solver, proof, size, ilits);
345 print_added_proof_line (proof);
346}
347
348void kissat_add_unit_to_proof (kissat *solver, unsigned ilit) {
349 proof *proof = solver->proof;
350 KISSAT_assert (proof);
351 KISSAT_assert (EMPTY_STACK (proof->line));
352 import_internal_proof_literal (solver, proof, ilit);
353 print_added_proof_line (proof);
354}
355
356void kissat_shrink_clause_in_proof (kissat *solver, const clause *c,
357 unsigned remove, unsigned keep) {
358 proof *proof = solver->proof;
359 const value *const values = solver->values;
360 KISSAT_assert (EMPTY_STACK (proof->line));
361 const unsigned *ilits = c->lits;
362 const unsigned size = c->size;
363 for (unsigned i = 0; i != size; i++) {
364 const unsigned ilit = ilits[i];
365 if (ilit == remove)
366 continue;
367 if (ilit != keep && values[ilit] < 0 && !LEVEL (ilit))
368 continue;
369 import_internal_proof_literal (solver, proof, ilit);
370 }
371 print_added_proof_line (proof);
372 import_proof_clause (solver, proof, c);
373 print_delete_proof_line (proof);
374}
375
376void kissat_delete_binary_from_proof (kissat *solver, unsigned a,
377 unsigned b) {
378 proof *proof = solver->proof;
379 KISSAT_assert (proof);
380 import_internal_proof_binary (solver, proof, a, b);
381 print_delete_proof_line (proof);
382}
383
384void kissat_delete_clause_from_proof (kissat *solver, const clause *c) {
385 proof *proof = solver->proof;
386 KISSAT_assert (proof);
387 import_proof_clause (solver, proof, c);
388 print_delete_proof_line (proof);
389}
390
391void kissat_delete_external_from_proof (kissat *solver, size_t size,
392 const int *elits) {
393 proof *proof = solver->proof;
394 KISSAT_assert (proof);
395 LOGINTS3 (size, elits, "explicitly deleted");
396 import_external_proof_literals (solver, proof, size, elits);
397 print_delete_proof_line (proof);
398}
399
400void kissat_delete_internal_from_proof (kissat *solver, size_t size,
401 const unsigned *ilits) {
402 proof *proof = solver->proof;
403 KISSAT_assert (proof);
404 import_internal_proof_literals (solver, proof, size, ilits);
405 print_delete_proof_line (proof);
406}
407
408#else
410#endif
void * kissat_calloc(kissat *solver, size_t n, size_t size)
Definition allocate.c:97
void kissat_free(kissat *solver, void *ptr, size_t bytes)
Definition allocate.c:61
void kissat_dealloc(kissat *solver, void *ptr, size_t n, size_t size)
Definition allocate.c:114
#define LEVEL(LIT)
Definition assign.h:34
#define ATTRIBUTE_ALWAYS_INLINE
Definition attribute.h:15
#define all_stack(T, E, S)
Definition stack.h:94
#define SIZE_STACK(S)
Definition stack.h:19
#define EMPTY_STACK(S)
Definition stack.h:18
#define RELEASE_STACK(S)
Definition stack.h:71
#define CLEAR_STACK(S)
Definition stack.h:50
#define PUSH_STACK(S, E)
Definition stack.h:39
#define PEEK_STACK(S, N)
Definition stack.h:29
#define INVALID_LIT
#define LOG(...)
ABC_NAMESPACE_IMPL_START typedef signed char value
void kissat_fatal(const char *fmt,...)
Definition error.c:58
bool pos
Definition globals.c:30
Cube * p
Definition exorList.c:222
struct file file
Definition file.h:21
#define KISSAT_assert(ignore)
Definition global.h:13
typedefABC_NAMESPACE_HEADER_START struct kissat kissat
Definition kissat.h:7
#define solver
Definition kitten.c:211
#define LOGINTS3(...)
Definition logging.h:397
unsigned long long size
Definition giaNewBdd.h:39
#define GET_OPTION(N)
Definition options.h:295
int kissat_proof_dummy_to_avoid_warning
Definition proof.c:409
unsigned lits[3]
Definition clause.h:39
unsigned size
Definition clause.h:37
Definition file.h:23
unsigned size
Definition internal.h:107
value * values
Definition internal.h:122
char * memcpy()
#define ABS(a)
Definition util_old.h:250