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