1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * PRINT SMT-CORE STRUCTURE
21  */
22 
23 #include <inttypes.h>
24 
25 #include "solvers/cdcl/smt_core_printer.h"
26 
27 
28 static const char * const bval2string[] = {
29   "undef", "undef", "false", "true", "<invalid bval>",
30 };
31 
32 static const char * const status2string[] = {
33   "idle", "searching", "unknown", "sat", "unsat", "interrupted",
34   "<invalid status>",
35 };
36 
37 
38 /*
39  * Boolean value
40  */
print_bval(FILE * f,bval_t b)41 void print_bval(FILE *f, bval_t b) {
42   // cast to (int) prevents compilation warnings with clang
43   // because it uses (unsigned) for the bval_t enum.
44   if ((int) b < 0 || b > VAL_TRUE) {
45     b = VAL_TRUE + 1;
46   }
47   fputs(bval2string[b], f);
48 }
49 
50 /*
51  * Status
52  */
print_status(FILE * f,smt_status_t s)53 void print_status(FILE *f, smt_status_t s) {
54   if (s > STATUS_INTERRUPTED) {
55     s = STATUS_INTERRUPTED + 1;
56   }
57   fputs(status2string[s], f);
58 }
59 
60 /*
61  * Boolean variable
62  */
print_bvar(FILE * f,bvar_t x)63 void print_bvar(FILE *f, bvar_t x) {
64   if (x < 0) {
65     if (x == null_bvar) {
66       fputs("null_bvar", f);
67     } else {
68       fprintf(f, "BVAR%"PRId32, x);
69     }
70   } else if (x == const_bvar) {
71     fputs("true", f);
72   } else {
73     fprintf(f, "p!%"PRId32, x);
74   }
75 }
76 
77 /*
78  * Literal
79  */
print_literal(FILE * f,literal_t l)80 void print_literal(FILE *f, literal_t l) {
81   if (l < 0) {
82     if (l == null_literal) {
83       //      fputs("null_literal", f);
84       fputs("nil", f);
85     } else {
86       fprintf(f, "LIT%"PRId32, l);
87     }
88   } else if (l == true_literal) {
89     fputs("tt", f);
90   } else if (l == false_literal) {
91     fputs("ff", f);
92   } else {
93     if (is_neg(l)) fputc('~', f);
94     fprintf(f, "p!%"PRId32, var_of(l));
95   }
96 }
97 
98 
99 /*
100  * Clause
101  */
print_clause(FILE * f,clause_t * cl)102 void print_clause(FILE *f, clause_t *cl) {
103   uint32_t i;
104   literal_t l;
105 
106 
107   /*
108    * Some problem clauses may be hidden (because one of their
109    * literal is true. For such clauses, the first two literals
110    * are negated.
111    */
112   if (cl->cl[0] < 0 || cl->cl[1] < 0) {
113 
114     fputc('[', f);
115     print_literal(f, - cl->cl[0]);
116     fputc(' ', f);
117     print_literal(f, - cl->cl[1]);
118     i = 2;
119     l = cl->cl[i];
120     while (l >= 0) {
121       fputc(' ', f);
122       print_literal(f, l);
123       i ++;
124       l = cl->cl[i];
125     }
126     fputc(']', f);
127 
128   } else {
129     fputc('{', f);
130     print_literal(f, cl->cl[0]);
131     i = 1;
132     l = cl->cl[i];
133     while (l >= 0) {
134       fputc(' ', f);
135       print_literal(f, l);
136       i ++;
137       l = cl->cl[i];
138     }
139     fputc('}', f);
140   }
141 }
142 
143 
144 
145 /*
146  * Print unit clauses = all the literals in core->stack[0 .. core->nb_units-1]
147  */
print_unit_clause(FILE * f,literal_t l)148 void print_unit_clause(FILE *f, literal_t l) {
149   fputc('{', f);
150   print_literal(f, l);
151   fputc('}', f);
152 }
153 
print_unit_clauses(FILE * f,smt_core_t * core)154 void print_unit_clauses(FILE *f, smt_core_t *core) {
155   prop_stack_t *stack;
156   uint32_t i, n;
157 
158   n = core->nb_unit_clauses;
159   stack = &core->stack;
160   for (i=0; i<n; i++) {
161     print_unit_clause(f, stack->lit[i]);
162     fputc('\n', f);
163   }
164 }
165 
166 
167 /*
168  * Print array a, formatted as a clause
169  */
print_litarray(FILE * f,uint32_t n,literal_t * a)170 void print_litarray(FILE *f, uint32_t n, literal_t *a) {
171   uint32_t i;
172 
173   fputc('{', f);
174   if (n > 0) {
175     print_literal(f, a[0]);
176     for (i=1; i<n; i++) {
177       fputc(' ', f);
178       print_literal(f, a[i]);
179     }
180   }
181   fputc('}', f);
182 }
183 
184 
185 #if 0
186 /*
187  * Variant of print_clause: sort the literals first
188  */
189 void print_clause_sorted(FILE *f, clause_t *cl) {
190   ivector_t v;
191   uint32_t i;
192   literal_t l;
193 
194   init_ivector(&v, 10);
195 
196   if (cl->cl[0] < 0 || cl->cl[1] < 0) {
197     ivector_push(&v, - cl->cl[0]);
198     ivector_push(&v, - cl->cl[1]);
199   } else {
200     ivector_push(&v, cl->cl[0]);
201     ivector_push(&v, cl->cl[1]);
202   }
203   i = 2;
204   l = cl->cl[i];
205   while (l >= 0) {
206     ivector_push(&v, l);
207     i ++;
208     l = cl->cl[i];
209   }
210   int_array_sort(v.data, v.size);
211   print_litarray(f, v.size, v.data);
212 
213   delete_ivector(&v);
214 }
215 #endif
216 
217 
218 /*
219  * Print binary and problem clauses
220  */
print_binary_clause(FILE * f,literal_t l1,literal_t l2)221 void print_binary_clause(FILE *f, literal_t l1, literal_t l2) {
222   fputc('{', f);
223   print_literal(f, l1);
224   fputc(' ', f);
225   print_literal(f, l2);
226   fputc('}', f);
227 }
228 
print_binary_clauses(FILE * f,smt_core_t * core)229 void print_binary_clauses(FILE *f, smt_core_t *core) {
230   int32_t n;
231   literal_t l1, l2;
232   literal_t *bin;
233 
234   n = core->nlits;
235   for (l1=0; l1<n; l1++) {
236     bin = core->bin[l1];
237     if (bin != NULL) {
238       for (;;) {
239         l2 = *bin++;
240         if (l2 < 0) break;
241         if (l1 <= l2) {
242           print_binary_clause(f, l1, l2);
243           fputc('\n', f);
244         }
245       }
246     }
247   }
248 }
249 
print_clause_vector(FILE * f,clause_t ** vector)250 static void print_clause_vector(FILE *f, clause_t **vector) {
251   uint32_t i, n;
252 
253   if (vector != NULL) {
254     n = get_cv_size(vector);
255     for (i=0; i<n; i++) {
256       print_clause(f, vector[i]);
257       fputc('\n', f);
258     }
259   }
260 }
261 
print_problem_clauses(FILE * f,smt_core_t * core)262 void print_problem_clauses(FILE *f, smt_core_t *core) {
263   print_clause_vector(f, core->problem_clauses);
264 }
265 
print_learned_clauses(FILE * f,smt_core_t * core)266 void print_learned_clauses(FILE *f, smt_core_t *core) {
267   print_clause_vector(f, core->learned_clauses);
268 }
269 
print_clauses(FILE * f,smt_core_t * core)270 void print_clauses(FILE *f, smt_core_t *core) {
271   print_unit_clauses(f, core);
272   print_binary_clauses(f, core);
273   print_problem_clauses(f, core);
274   fputc('\n', f);
275 }
276 
print_all_clauses(FILE * f,smt_core_t * core)277 void print_all_clauses(FILE *f, smt_core_t *core) {
278   print_binary_clauses(f, core);
279   fputc('\n', f);
280   print_problem_clauses(f, core);
281   fputc('\n', f);
282   print_learned_clauses(f, core);
283   fputc('\n', f);
284 }
285 
286 /*
287  * Find the length of a lemma a:
288  * - a must be terminated by null_literal (or any negative end marker)
289  */
lemma_length(literal_t * a)290 static uint32_t lemma_length(literal_t *a) {
291   uint32_t n;
292 
293   n = 0;
294   while (*a >= 0) {
295     a ++;
296     n ++;
297   }
298   return n;
299 }
300 
301 
302 /*
303  * Print all lemmas
304  */
print_lemmas(FILE * f,smt_core_t * core)305 void print_lemmas(FILE *f, smt_core_t *core) {
306   lemma_block_t *tmp;
307   literal_t *lemma;
308   uint32_t i, j, n;
309 
310   for (i=0; i<core->lemmas.free_block; i++) {
311     tmp = core->lemmas.block[i];
312     lemma = tmp->data;
313     j = 0;
314     while (j < tmp->ptr) {
315       n = lemma_length(lemma);
316       print_litarray(f, n, lemma);
317       fputc('\n', f);
318       n ++;
319       j += n;
320       lemma += n;
321     }
322   }
323 }
324 
325 
326 /*
327  * Print assignment
328  */
print_boolean_assignment(FILE * f,smt_core_t * core)329 void print_boolean_assignment(FILE *f, smt_core_t *core) {
330   prop_stack_t *stack;
331   uint32_t i, n;
332   literal_t l;
333 
334   stack = &core->stack;
335   n = stack->top;
336   for (i=0; i<n; i++) {
337     l = stack->lit[i];
338     fputc(' ', f);
339     if (is_pos(l)) fputc(' ', f);
340     print_literal(f, l);
341     fprintf(f, " level = %"PRIu32"\n", core->level[var_of(l)]);
342   }
343 }
344 
345 /*
346  * Print conflict data
347  */
print_conflict(FILE * f,smt_core_t * core)348 void print_conflict(FILE *f, smt_core_t *core) {
349   literal_t l;
350   uint32_t i;
351 
352   if (core->inconsistent) {
353     i = 0;
354     l = core->conflict[i];
355     if (l < 0) {
356       fputs("Conflict: empty clause\n", f);
357     } else {
358       fputs("Conflict:", f);
359       while (l >= 0) {
360         fputc(' ', f);
361         print_literal(f, l);
362         i ++;
363         l = core->conflict[i];
364       }
365       fputc('\n', f);
366     }
367 
368   } else {
369     fputs("No conflict\n", f);
370   }
371 }
372 
373 
374 /*
375  * Size of a clause vector (deal with the case v == NULL)
376  */
cv_size(clause_t ** v)377 static inline uint32_t cv_size(clause_t **v) {
378   return v == NULL ? 0 : get_cv_size(v);
379 }
380 
381 /*
382  * Print current state of core
383  * (This needs to be exported for now, because it's used in the tests)
384  */
print_smt_core(FILE * f,smt_core_t * core)385 void print_smt_core(FILE *f, smt_core_t *core) {
386   fprintf(f, "SMT Core %p\n", core);
387   fprintf(f, "  %"PRIu32" variables\n", core->nvars);
388   fprintf(f, "  %"PRIu32" unit clauses\n", core->nb_unit_clauses);
389   fprintf(f, "  %"PRIu32" binary clauses\n", core->nb_bin_clauses);
390   fprintf(f, "  %"PRIu32" problem clauses\n", cv_size(core->problem_clauses));
391   fprintf(f, "  %"PRIu32" learned clauses\n", cv_size(core->learned_clauses));
392   fprintf(f, "status = %s\n", status2string[core->status]);
393   fprintf(f, "base_level = %"PRIu32"\n", core->base_level);
394   fprintf(f, "decision_level = %"PRIu32"\n", core->decision_level);
395   print_conflict(f, core);
396   fprintf(f, "Assignment:\n");
397   print_boolean_assignment(f, core);
398   fprintf(f, "Clauses:\n");
399   print_unit_clauses(f, core);
400   print_binary_clauses(f, core);
401   print_problem_clauses(f, core);
402   print_learned_clauses(f, core);
403   fputc('\n', f);
404   fflush(f);
405 }
406 
407 
408 
409 
410