1 /* Boolector: Satisfiability Modulo Theories (SMT) solver.
2 *
3 * Copyright (C) 2007-2021 by the authors listed in the AUTHORS file.
4 *
5 * This file is part of Boolector.
6 * See COPYING for more information on using this software.
7 */
8
9 #include "btorsat.h"
10
11 #include <assert.h>
12 #include <ctype.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15
16 #include "btorabort.h"
17 #include "btorconfig.h"
18 #include "btorcore.h"
19 #include "sat/btorcadical.h"
20 #include "sat/btorcms.h"
21 #include "sat/btorlgl.h"
22 #include "sat/btorminisat.h"
23 #include "sat/btorpicosat.h"
24 #include "utils/btorutil.h"
25
26 /*------------------------------------------------------------------------*/
27
28 #if !defined(BTOR_USE_LINGELING) && !defined(BTOR_USE_PICOSAT) \
29 && !defined(BTOR_USE_MINISAT) && !defined(BTOR_USE_CADICAL) \
30 && !defined(BTOR_USE_CMS)
31 #error "no SAT solver configured"
32 #endif
33
34 static bool enable_dimacs_printer (BtorSATMgr *smgr);
35
36 /*------------------------------------------------------------------------*/
37 /* wrapper functions for SAT solver API */
38 /*------------------------------------------------------------------------*/
39
40 static inline void
add(BtorSATMgr * smgr,int32_t lit)41 add (BtorSATMgr *smgr, int32_t lit)
42 {
43 assert (smgr->api.add);
44 smgr->api.add (smgr, lit);
45 }
46
47 static inline void
assume(BtorSATMgr * smgr,int32_t lit)48 assume (BtorSATMgr *smgr, int32_t lit)
49 {
50 BTOR_ABORT (!smgr->api.assume,
51 "SAT solver %s does not support 'assume' API call",
52 smgr->name);
53 smgr->api.assume (smgr, lit);
54 }
55
56 static inline void *
clone(Btor * btor,BtorSATMgr * smgr)57 clone (Btor *btor, BtorSATMgr *smgr)
58 {
59 BTOR_ABORT (!smgr->api.clone,
60 "SAT solver %s does not support 'clone' API call",
61 smgr->name);
62 return smgr->api.clone (btor, smgr);
63 }
64
65 static inline int32_t
deref(BtorSATMgr * smgr,int32_t lit)66 deref (BtorSATMgr *smgr, int32_t lit)
67 {
68 assert (smgr->api.deref);
69 return smgr->api.deref (smgr, lit);
70 }
71
72 static inline void
enable_verbosity(BtorSATMgr * smgr,int32_t level)73 enable_verbosity (BtorSATMgr *smgr, int32_t level)
74 {
75 if (smgr->api.enable_verbosity) smgr->api.enable_verbosity (smgr, level);
76 }
77
78 static inline int32_t
failed(BtorSATMgr * smgr,int32_t lit)79 failed (BtorSATMgr *smgr, int32_t lit)
80 {
81 BTOR_ABORT (!smgr->api.failed,
82 "SAT solver %s does not support 'failed' API call",
83 smgr->name);
84 return smgr->api.failed (smgr, lit);
85 }
86
87 static inline int32_t
fixed(BtorSATMgr * smgr,int32_t lit)88 fixed (BtorSATMgr *smgr, int32_t lit)
89 {
90 if (smgr->api.fixed) return smgr->api.fixed (smgr, lit);
91 return 0;
92 }
93
94 static inline int32_t
inc_max_var(BtorSATMgr * smgr)95 inc_max_var (BtorSATMgr *smgr)
96 {
97 if (smgr->api.inc_max_var) return smgr->api.inc_max_var (smgr);
98 return smgr->maxvar + 1;
99 }
100
101 static inline void *
init(BtorSATMgr * smgr)102 init (BtorSATMgr *smgr)
103 {
104 assert (smgr->api.init);
105 return smgr->api.init (smgr);
106 }
107
108 static inline void
melt(BtorSATMgr * smgr,int32_t lit)109 melt (BtorSATMgr *smgr, int32_t lit)
110 {
111 if (smgr->api.melt) smgr->api.melt (smgr, lit);
112 // TODO: else case warning?
113 }
114
115 static inline int32_t
repr(BtorSATMgr * smgr,int32_t lit)116 repr (BtorSATMgr *smgr, int32_t lit)
117 {
118 if (smgr->api.repr) return smgr->api.repr (smgr, lit);
119 return lit;
120 }
121
122 static inline void
reset(BtorSATMgr * smgr)123 reset (BtorSATMgr *smgr)
124 {
125 assert (smgr->api.reset);
126 smgr->api.reset (smgr);
127 }
128
129 static inline int32_t
sat(BtorSATMgr * smgr,int32_t limit)130 sat (BtorSATMgr *smgr, int32_t limit)
131 {
132 assert (smgr->api.sat);
133 return smgr->api.sat (smgr, limit);
134 }
135
136 static inline void
set_output(BtorSATMgr * smgr,FILE * output)137 set_output (BtorSATMgr *smgr, FILE *output)
138 {
139 if (smgr->api.set_output) smgr->api.set_output (smgr, output);
140 }
141
142 static inline void
set_prefix(BtorSATMgr * smgr,const char * prefix)143 set_prefix (BtorSATMgr *smgr, const char *prefix)
144 {
145 if (smgr->api.set_prefix) smgr->api.set_prefix (smgr, prefix);
146 }
147
148 static inline void
setterm(BtorSATMgr * smgr)149 setterm (BtorSATMgr *smgr)
150 {
151 if (smgr->api.setterm) smgr->api.setterm (smgr);
152 }
153
154 static inline void
stats(BtorSATMgr * smgr)155 stats (BtorSATMgr *smgr)
156 {
157 if (smgr->api.stats) smgr->api.stats (smgr);
158 }
159
160 /*------------------------------------------------------------------------*/
161
162 BtorSATMgr *
btor_sat_mgr_new(Btor * btor)163 btor_sat_mgr_new (Btor *btor)
164 {
165 assert (btor);
166
167 BtorSATMgr *smgr;
168
169 BTOR_CNEW (btor->mm, smgr);
170 smgr->btor = btor;
171 smgr->output = stdout;
172 return smgr;
173 }
174
175 bool
btor_sat_mgr_has_clone_support(const BtorSATMgr * smgr)176 btor_sat_mgr_has_clone_support (const BtorSATMgr *smgr)
177 {
178 if (!smgr) return true;
179 return smgr->api.clone != 0;
180 }
181
182 bool
btor_sat_mgr_has_incremental_support(const BtorSATMgr * smgr)183 btor_sat_mgr_has_incremental_support (const BtorSATMgr *smgr)
184 {
185 if (!smgr) return false;
186 return smgr->api.assume != 0 && smgr->api.failed != 0;
187 }
188
189 void
btor_sat_mgr_set_term(BtorSATMgr * smgr,int32_t (* fun)(void *),void * state)190 btor_sat_mgr_set_term (BtorSATMgr *smgr, int32_t (*fun) (void *), void *state)
191 {
192 assert (smgr);
193 smgr->term.fun = fun;
194 smgr->term.state = state;
195 }
196
197 // FIXME log output handling, in particular: sat manager name output
198 // (see lingeling_sat) should be unique, which is not the case for
199 // clones
200 BtorSATMgr *
btor_sat_mgr_clone(Btor * btor,BtorSATMgr * smgr)201 btor_sat_mgr_clone (Btor *btor, BtorSATMgr *smgr)
202 {
203 assert (btor);
204 assert (smgr);
205
206 BtorSATMgr *res;
207 BtorMemMgr *mm;
208
209 BTOR_ABORT (!btor_sat_mgr_has_clone_support (smgr),
210 "SAT solver does not support cloning");
211
212 mm = btor->mm;
213 BTOR_NEW (mm, res);
214 res->solver = clone (btor, smgr);
215 res->btor = btor;
216 assert (mm->sat_allocated == smgr->btor->mm->sat_allocated);
217 res->name = smgr->name;
218 memcpy (&res->inc_required,
219 &smgr->inc_required,
220 (char *) smgr + sizeof (*smgr) - (char *) &smgr->inc_required);
221 BTOR_CLR (&res->term);
222 return res;
223 }
224
225 bool
btor_sat_is_initialized(BtorSATMgr * smgr)226 btor_sat_is_initialized (BtorSATMgr *smgr)
227 {
228 assert (smgr);
229 return smgr->initialized;
230 }
231
232 int32_t
btor_sat_mgr_next_cnf_id(BtorSATMgr * smgr)233 btor_sat_mgr_next_cnf_id (BtorSATMgr *smgr)
234 {
235 int32_t result;
236 assert (smgr);
237 assert (smgr->initialized);
238 result = inc_max_var (smgr);
239 if (abs (result) > smgr->maxvar) smgr->maxvar = abs (result);
240 BTOR_ABORT (result <= 0, "CNF id overflow");
241 if (btor_opt_get (smgr->btor, BTOR_OPT_VERBOSITY) > 2 && !(result % 100000))
242 BTOR_MSG (smgr->btor->msg, 2, "reached CNF id %d", result);
243 return result;
244 }
245
246 void
btor_sat_mgr_release_cnf_id(BtorSATMgr * smgr,int32_t lit)247 btor_sat_mgr_release_cnf_id (BtorSATMgr *smgr, int32_t lit)
248 {
249 assert (smgr);
250 if (!smgr->initialized) return;
251 assert (abs (lit) <= smgr->maxvar);
252 if (abs (lit) == smgr->true_lit) return;
253 melt (smgr, lit);
254 }
255
256 void
btor_sat_mgr_delete(BtorSATMgr * smgr)257 btor_sat_mgr_delete (BtorSATMgr *smgr)
258 {
259 assert (smgr != NULL);
260 /* if SAT is still initialized, then
261 * reset_sat has not been called
262 */
263 if (smgr->initialized) btor_sat_reset (smgr);
264 BTOR_DELETE (smgr->btor->mm, smgr);
265 }
266
267 /*------------------------------------------------------------------------*/
268
269 void
btor_sat_set_output(BtorSATMgr * smgr,FILE * output)270 btor_sat_set_output (BtorSATMgr *smgr, FILE *output)
271 {
272 char *prefix, *q;
273 const char *p;
274
275 assert (smgr != NULL);
276 assert (smgr->initialized);
277 assert (output != NULL);
278 (void) smgr;
279 set_output (smgr, output);
280 smgr->output = output;
281
282 prefix = btor_mem_malloc (smgr->btor->mm, strlen (smgr->name) + 4);
283 sprintf (prefix, "[%s] ", smgr->name);
284 q = prefix + 1;
285 for (p = smgr->name; *p; p++) *q++ = tolower ((int32_t) *p);
286 set_prefix (smgr, prefix);
287 btor_mem_free (smgr->btor->mm, prefix, strlen (smgr->name) + 4);
288 }
289
290 void
btor_sat_enable_solver(BtorSATMgr * smgr)291 btor_sat_enable_solver (BtorSATMgr *smgr)
292 {
293 assert (smgr);
294
295 uint32_t opt;
296
297 opt = btor_opt_get (smgr->btor, BTOR_OPT_SAT_ENGINE);
298 switch (opt)
299 {
300 #ifdef BTOR_USE_LINGELING
301 case BTOR_SAT_ENGINE_LINGELING: btor_sat_enable_lingeling (smgr); break;
302 #endif
303 #ifdef BTOR_USE_PICOSAT
304 case BTOR_SAT_ENGINE_PICOSAT: btor_sat_enable_picosat (smgr); break;
305 #endif
306 #ifdef BTOR_USE_MINISAT
307 case BTOR_SAT_ENGINE_MINISAT: btor_sat_enable_minisat (smgr); break;
308 #endif
309 #ifdef BTOR_USE_CADICAL
310 case BTOR_SAT_ENGINE_CADICAL: btor_sat_enable_cadical (smgr); break;
311 #endif
312 #ifdef BTOR_USE_CMS
313 case BTOR_SAT_ENGINE_CMS: btor_sat_enable_cms (smgr); break;
314 #endif
315 default: BTOR_ABORT (1, "no sat solver configured");
316 }
317
318 BTOR_MSG (smgr->btor->msg,
319 1,
320 "%s allows %snon-incremental mode",
321 smgr->name,
322 smgr->api.assume ? "both incremental and " : "");
323
324 if (btor_opt_get (smgr->btor, BTOR_OPT_PRINT_DIMACS))
325 {
326 enable_dimacs_printer (smgr);
327 }
328 }
329
330 static void
init_flags(BtorSATMgr * smgr)331 init_flags (BtorSATMgr *smgr)
332 {
333 assert (smgr);
334 smgr->initialized = true;
335 smgr->inc_required = true;
336 smgr->sat_time = 0;
337 }
338
339 void
btor_sat_init(BtorSATMgr * smgr)340 btor_sat_init (BtorSATMgr *smgr)
341 {
342 assert (smgr != NULL);
343 assert (!smgr->initialized);
344 BTOR_MSG (smgr->btor->msg, 1, "initialized %s", smgr->name);
345
346 init_flags (smgr);
347
348 smgr->solver = init (smgr);
349 enable_verbosity (smgr, btor_opt_get (smgr->btor, BTOR_OPT_VERBOSITY));
350
351 /* Set terminate callbacks if SAT solver supports it */
352 if (smgr->term.fun && smgr->api.setterm)
353 {
354 setterm (smgr);
355 }
356
357 smgr->true_lit = btor_sat_mgr_next_cnf_id (smgr);
358 btor_sat_add (smgr, smgr->true_lit);
359 btor_sat_add (smgr, 0);
360 btor_sat_set_output (smgr, stdout);
361 }
362
363 void
btor_sat_print_stats(BtorSATMgr * smgr)364 btor_sat_print_stats (BtorSATMgr *smgr)
365 {
366 if (!smgr || !smgr->initialized) return;
367 stats (smgr);
368 BTOR_MSG (smgr->btor->msg,
369 1,
370 "%d SAT calls in %.1f seconds",
371 smgr->satcalls,
372 smgr->sat_time);
373 }
374
375 void
btor_sat_add(BtorSATMgr * smgr,int32_t lit)376 btor_sat_add (BtorSATMgr *smgr, int32_t lit)
377 {
378 assert (smgr != NULL);
379 assert (smgr->initialized);
380 assert (abs (lit) <= smgr->maxvar);
381 assert (!smgr->satcalls || smgr->inc_required);
382 if (!lit) smgr->clauses++;
383 add (smgr, lit);
384 }
385
386 BtorSolverResult
btor_sat_check_sat(BtorSATMgr * smgr,int32_t limit)387 btor_sat_check_sat (BtorSATMgr *smgr, int32_t limit)
388 {
389 assert (smgr != NULL);
390 assert (smgr->initialized);
391 assert (!smgr->inc_required || btor_sat_mgr_has_incremental_support (smgr));
392
393 double start = btor_util_time_stamp ();
394 int32_t sat_res;
395 BtorSolverResult res;
396 BTOR_MSG (smgr->btor->msg,
397 2,
398 "calling SAT solver %s with limit %d",
399 smgr->name,
400 limit);
401 assert (!smgr->satcalls || smgr->inc_required);
402 smgr->satcalls++;
403 setterm (smgr);
404 sat_res = sat (smgr, limit);
405 smgr->sat_time += btor_util_time_stamp () - start;
406 switch (sat_res)
407 {
408 case 10: res = BTOR_RESULT_SAT; break;
409 case 20: res = BTOR_RESULT_UNSAT; break;
410 default: assert (sat_res == 0); res = BTOR_RESULT_UNKNOWN;
411 }
412 return res;
413 }
414
415 int32_t
btor_sat_deref(BtorSATMgr * smgr,int32_t lit)416 btor_sat_deref (BtorSATMgr *smgr, int32_t lit)
417 {
418 (void) smgr;
419 assert (smgr != NULL);
420 assert (smgr->initialized);
421 assert (abs (lit) <= smgr->maxvar);
422 return deref (smgr, lit);
423 }
424
425 int32_t
btor_sat_repr(BtorSATMgr * smgr,int32_t lit)426 btor_sat_repr (BtorSATMgr *smgr, int32_t lit)
427 {
428 (void) smgr;
429 assert (smgr != NULL);
430 assert (smgr->initialized);
431 assert (abs (lit) <= smgr->maxvar);
432 return repr (smgr, lit);
433 }
434
435 void
btor_sat_reset(BtorSATMgr * smgr)436 btor_sat_reset (BtorSATMgr *smgr)
437 {
438 assert (smgr != NULL);
439 assert (smgr->initialized);
440 BTOR_MSG (smgr->btor->msg, 2, "resetting %s", smgr->name);
441 reset (smgr);
442 smgr->solver = 0;
443 smgr->initialized = false;
444 }
445
446 int32_t
btor_sat_fixed(BtorSATMgr * smgr,int32_t lit)447 btor_sat_fixed (BtorSATMgr *smgr, int32_t lit)
448 {
449 int32_t res;
450 assert (smgr != NULL);
451 assert (smgr->initialized);
452 assert (abs (lit) <= smgr->maxvar);
453 res = fixed (smgr, lit);
454 return res;
455 }
456
457 /*------------------------------------------------------------------------*/
458
459 void
btor_sat_assume(BtorSATMgr * smgr,int32_t lit)460 btor_sat_assume (BtorSATMgr *smgr, int32_t lit)
461 {
462 assert (smgr != NULL);
463 assert (smgr->initialized);
464 assert (abs (lit) <= smgr->maxvar);
465 assert (!smgr->satcalls || smgr->inc_required);
466 assume (smgr, lit);
467 }
468
469 int32_t
btor_sat_failed(BtorSATMgr * smgr,int32_t lit)470 btor_sat_failed (BtorSATMgr *smgr, int32_t lit)
471 {
472 (void) smgr;
473 assert (smgr != NULL);
474 assert (smgr->initialized);
475 assert (abs (lit) <= smgr->maxvar);
476 return failed (smgr, lit);
477 }
478
479 /*------------------------------------------------------------------------*/
480 /* DIMACS printer */
481 /*------------------------------------------------------------------------*/
482
483 static void *
dimacs_printer_init(BtorSATMgr * smgr)484 dimacs_printer_init (BtorSATMgr *smgr)
485 {
486 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
487 BtorSATMgr *wrapped_smgr = printer->smgr;
488
489 BTOR_INIT_STACK (smgr->btor->mm, printer->clauses);
490 BTOR_INIT_STACK (smgr->btor->mm, printer->assumptions);
491 printer->out = stdout;
492
493 /* Note: We need to explicitly do the initialization steps for 'wrapped_smgr'
494 * here instead of calling btor_sat_init on 'wrapped_smgr'. Otherwise, not all
495 * information is recorded correctly. */
496 BTOR_MSG (smgr->btor->msg, 1, "initialized %s", wrapped_smgr->name);
497 init_flags (wrapped_smgr);
498 wrapped_smgr->solver = wrapped_smgr->api.init (wrapped_smgr);
499
500 return printer;
501 }
502
503 static void
dimacs_printer_add(BtorSATMgr * smgr,int32_t lit)504 dimacs_printer_add (BtorSATMgr *smgr, int32_t lit)
505 {
506 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
507 BTOR_PUSH_STACK (printer->clauses, lit);
508 add (printer->smgr, lit);
509 }
510
511 static void
dimacs_printer_assume(BtorSATMgr * smgr,int32_t lit)512 dimacs_printer_assume (BtorSATMgr *smgr, int32_t lit)
513 {
514 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
515 BTOR_PUSH_STACK (printer->assumptions, lit);
516 assume (printer->smgr, lit);
517 }
518
519 static int32_t
dimacs_printer_deref(BtorSATMgr * smgr,int32_t lit)520 dimacs_printer_deref (BtorSATMgr *smgr, int32_t lit)
521 {
522 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
523 return deref (printer->smgr, lit);
524 }
525
526 static int32_t
dimacs_printer_repr(BtorSATMgr * smgr,int32_t lit)527 dimacs_printer_repr (BtorSATMgr *smgr, int32_t lit)
528 {
529 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
530 return repr (printer->smgr, lit);
531 }
532
533 static void
dimacs_printer_enable_verbosity(BtorSATMgr * smgr,int32_t level)534 dimacs_printer_enable_verbosity (BtorSATMgr *smgr, int32_t level)
535 {
536 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
537 return enable_verbosity (printer->smgr, level);
538 }
539
540 static int32_t
dimacs_printer_failed(BtorSATMgr * smgr,int32_t lit)541 dimacs_printer_failed (BtorSATMgr *smgr, int32_t lit)
542 {
543 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
544 return failed (printer->smgr, lit);
545 }
546
547 static int32_t
dimacs_printer_fixed(BtorSATMgr * smgr,int32_t lit)548 dimacs_printer_fixed (BtorSATMgr *smgr, int32_t lit)
549 {
550 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
551 return fixed (printer->smgr, lit);
552 }
553
554 static void
dimacs_printer_reset(BtorSATMgr * smgr)555 dimacs_printer_reset (BtorSATMgr *smgr)
556 {
557 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
558 BtorSATMgr *wrapped_smgr = printer->smgr;
559
560 reset (wrapped_smgr);
561
562 BTOR_DELETE (smgr->btor->mm, wrapped_smgr);
563 BTOR_RELEASE_STACK (printer->clauses);
564 BTOR_RELEASE_STACK (printer->assumptions);
565 BTOR_DELETE (smgr->btor->mm, printer);
566 smgr->solver = 0;
567 }
568
569 static void
print_dimacs(BtorSATMgr * smgr)570 print_dimacs (BtorSATMgr *smgr)
571 {
572 int32_t lit;
573 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
574
575 /* Print CNF in DIMACS format. */
576 fprintf (printer->out, "c CNF dump %u start\n", smgr->satcalls);
577 fprintf (printer->out, "c Boolector version %s\n", BTOR_GIT_ID);
578 fprintf (printer->out, "p cnf %u %u\n", smgr->maxvar, smgr->clauses);
579
580 /* Print clauses */
581 for (size_t i = 0; i < BTOR_COUNT_STACK (printer->clauses); i++)
582 {
583 lit = BTOR_PEEK_STACK (printer->clauses, i);
584 if (lit)
585 printf ("%d ", lit);
586 else
587 printf ("%d\n", lit);
588 }
589
590 /* Print assumptions */
591 if (!BTOR_EMPTY_STACK (printer->assumptions))
592 {
593 fprintf (printer->out, "c assumptions\n");
594 for (size_t i = 0; i < BTOR_COUNT_STACK (printer->assumptions); i++)
595 {
596 lit = BTOR_PEEK_STACK (printer->assumptions, i);
597 fprintf (printer->out, "%d\n", lit);
598 }
599 }
600 fprintf (printer->out, "c CNF dump %u end\n", smgr->satcalls);
601 }
602
603 static int32_t
dimacs_printer_sat(BtorSATMgr * smgr,int32_t limit)604 dimacs_printer_sat (BtorSATMgr *smgr, int32_t limit)
605 {
606 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
607 BtorSATMgr *wrapped_smgr = printer->smgr;
608
609 print_dimacs (smgr);
610
611 wrapped_smgr->inc_required = smgr->inc_required;
612 wrapped_smgr->satcalls = smgr->satcalls;
613
614 /* If incremental is disabled, we only print the CNF and return unknown. */
615 return smgr->inc_required ? sat (wrapped_smgr, limit) : 0;
616 }
617
618 static void
dimacs_printer_set_output(BtorSATMgr * smgr,FILE * output)619 dimacs_printer_set_output (BtorSATMgr *smgr, FILE *output)
620 {
621 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
622 printer->out = output;
623 set_output (printer->smgr, output);
624 }
625
626 static void
dimacs_printer_set_prefix(BtorSATMgr * smgr,const char * prefix)627 dimacs_printer_set_prefix (BtorSATMgr *smgr, const char *prefix)
628 {
629 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
630 set_prefix (printer->smgr, prefix);
631 }
632
633 static void
dimacs_printer_stats(BtorSATMgr * smgr)634 dimacs_printer_stats (BtorSATMgr *smgr)
635 {
636 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
637 stats (printer->smgr);
638 }
639
640 static void
clone_int_stack(BtorMemMgr * mm,BtorIntStack * clone,BtorIntStack * stack)641 clone_int_stack (BtorMemMgr *mm, BtorIntStack *clone, BtorIntStack *stack)
642 {
643 size_t size = BTOR_SIZE_STACK (*stack);
644 size_t cnt = BTOR_COUNT_STACK (*stack);
645
646 BTOR_INIT_STACK (mm, *clone);
647 if (size)
648 {
649 BTOR_CNEWN (mm, clone->start, size);
650 clone->end = clone->start + size;
651 clone->top = clone->start + cnt;
652 memcpy (clone->start, stack->start, cnt * sizeof (int32_t));
653 }
654 }
655
656 static void *
dimacs_printer_clone(Btor * btor,BtorSATMgr * smgr)657 dimacs_printer_clone (Btor *btor, BtorSATMgr *smgr)
658 {
659 BtorCnfPrinter *printer, *printer_clone;
660 BtorMemMgr *mm;
661
662 mm = btor->mm;
663 printer = (BtorCnfPrinter *) smgr->solver;
664
665 BTOR_CNEW (mm, printer_clone);
666 clone_int_stack (mm, &printer_clone->assumptions, &printer->assumptions);
667 clone_int_stack (mm, &printer_clone->clauses, &printer->clauses);
668 printer_clone->out = printer->out;
669 printer_clone->smgr = btor_sat_mgr_clone (btor, printer->smgr);
670
671 return printer_clone;
672 }
673
674 static void
dimacs_printer_setterm(BtorSATMgr * smgr)675 dimacs_printer_setterm (BtorSATMgr *smgr)
676 {
677 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
678 setterm (printer->smgr);
679 }
680
681 static int32_t
dimacs_printer_inc_max_var(BtorSATMgr * smgr)682 dimacs_printer_inc_max_var (BtorSATMgr *smgr)
683 {
684 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
685 BtorSATMgr *wrapped_smgr = printer->smgr;
686 wrapped_smgr->inc_required = smgr->inc_required;
687 wrapped_smgr->maxvar = smgr->maxvar;
688 return inc_max_var (wrapped_smgr);
689 }
690
691 static void
dimacs_printer_melt(BtorSATMgr * smgr,int32_t lit)692 dimacs_printer_melt (BtorSATMgr *smgr, int32_t lit)
693 {
694 BtorCnfPrinter *printer = (BtorCnfPrinter *) smgr->solver;
695 BtorSATMgr *wrapped_smgr = printer->smgr;
696 wrapped_smgr->inc_required = smgr->inc_required;
697 melt (wrapped_smgr, lit);
698 }
699
700 /*------------------------------------------------------------------------*/
701
702 /* The DIMACS printer is a SAT manager that wraps the currently configured SAT
703 * mangager. It records the CNF sent to the SAT solver and forwards all API
704 * calls to the wrapped SAT manager. The DIMACS printer assumes a SAT solver
705 * was already enabled. */
706 static bool
enable_dimacs_printer(BtorSATMgr * smgr)707 enable_dimacs_printer (BtorSATMgr *smgr)
708 {
709 assert (smgr);
710 assert (smgr->name);
711
712 BtorCnfPrinter *printer;
713
714 /* Initialize printer and copy current SAT manager. */
715 BTOR_CNEW (smgr->btor->mm, printer);
716 BTOR_CNEW (smgr->btor->mm, printer->smgr);
717 memcpy (printer->smgr, smgr, sizeof (BtorSATMgr));
718
719 /* Clear API */
720 memset (&smgr->api, 0, sizeof (smgr->api));
721
722 smgr->solver = printer;
723 smgr->name = "DIMACS Printer";
724 smgr->api.add = dimacs_printer_add;
725 smgr->api.deref = dimacs_printer_deref;
726 smgr->api.enable_verbosity = dimacs_printer_enable_verbosity;
727 smgr->api.fixed = dimacs_printer_fixed;
728 smgr->api.inc_max_var = dimacs_printer_inc_max_var;
729 smgr->api.init = dimacs_printer_init;
730 smgr->api.melt = dimacs_printer_melt;
731 smgr->api.repr = dimacs_printer_repr;
732 smgr->api.reset = dimacs_printer_reset;
733 smgr->api.sat = dimacs_printer_sat;
734 smgr->api.set_output = dimacs_printer_set_output;
735 smgr->api.set_prefix = dimacs_printer_set_prefix;
736 smgr->api.stats = dimacs_printer_stats;
737 smgr->api.setterm = dimacs_printer_setterm;
738
739 /* These function are used in btor_sat_mgr_has_* testers and should only be
740 * set if the underlying SAT solver also has support for it. */
741 smgr->api.assume = printer->smgr->api.assume ? dimacs_printer_assume : 0;
742 smgr->api.failed = printer->smgr->api.failed ? dimacs_printer_failed : 0;
743 smgr->api.clone = printer->smgr->api.clone ? dimacs_printer_clone : 0;
744
745 return true;
746 }
747