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