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 * CONTEXT OPERATIONS
21 */
22
23 #ifndef __CONTEXT_H
24 #define __CONTEXT_H
25
26 #include "api/search_parameters.h"
27 #include "context/context_utils.h"
28
29
30 /********************************
31 * INITIALIZATION AND CONTROL *
32 *******************************/
33
34 /*
35 * Initialize ctx for the given logic, mode, and architecture
36 * - terms = term table for this context
37 * - qflag = false means quantifier-free variant
38 * - qflag = true means quantifiers allowed
39 * If arch is one of the ARCH_AUTO_... variants, then mode must be ONECHECK
40 */
41 extern void init_context(context_t *ctx, term_table_t *terms, smt_logic_t logic,
42 context_mode_t mode, context_arch_t arch, bool qflag);
43
44
45 /*
46 * Deletion
47 */
48 extern void delete_context(context_t *ctx);
49
50
51 /*
52 * Reset: remove all assertions
53 */
54 extern void reset_context(context_t *ctx);
55
56
57 /*
58 * Set the trace:
59 * - the current tracer must be NULL.
60 * - the tracer is also attached to the context's smt_core
61 * (so all solvers can use it to print stuff).
62 */
63 extern void context_set_trace(context_t *ctx, tracer_t *trace);
64
65
66 /*
67 * Push and pop
68 * - should not be used if the push_pop option is disabled
69 */
70 extern void context_push(context_t *ctx);
71 extern void context_pop(context_t *ctx);
72
73
74
75 /*************
76 * OPTIONS *
77 ************/
78
79
80 /*
81 * Functions for testing/setting optional features are defined
82 * in context_utils.h and are available in any module that
83 * imports context.h. We define a few more here that are
84 * related to the arithmetic solver.
85 */
86
87 /*
88 * Options for the simplex solver. If the context already contains
89 * a simplex solver, then these options are set in this solver.
90 * Otherwise,, they will be set at the time the simplex solver is
91 * constructed and added to the simplex solver.
92 */
93 extern void enable_splx_eager_lemmas(context_t *ctx);
94 extern void disable_splx_eager_lemmas(context_t *ctx);
95 extern void enable_splx_periodic_icheck(context_t *ctx);
96 extern void disable_splx_periodic_icheck(context_t *ctx);
97 extern void enable_splx_eqprop(context_t *ctx);
98 extern void disable_splx_eqprop(context_t *ctx);
99
100
101 /*
102 * Check which variant of the arithmetic solver is present
103 */
104 extern bool context_has_idl_solver(context_t *ctx);
105 extern bool context_has_rdl_solver(context_t *ctx);
106 extern bool context_has_simplex_solver(context_t *ctx);
107
108
109
110 /****************************
111 * ASSERTIONS AND CHECK *
112 ***************************/
113
114 /*
115 * Assert a boolean formula f.
116 *
117 * The context status must be IDLE.
118 *
119 * Return code:
120 * - TRIVIALLY_UNSAT means that an inconsistency is detected
121 * (in that case the context status is set to UNSAT)
122 * - CTX_NO_ERROR means no internalization error and status not
123 * determined
124 * - otherwise, the code is negative. The assertion could
125 * not be processed.
126 */
127 extern int32_t assert_formula(context_t *ctx, term_t f);
128
129
130 /*
131 * Assert all formulas f[0] ... f[n-1]
132 * same return code as above.
133 */
134 extern int32_t assert_formulas(context_t *ctx, uint32_t n, const term_t *f);
135
136
137 /*
138 * Convert boolean term t to a literal l in context ctx
139 * - return a negative code if there's an error
140 * - return a literal (l >= 0) otherwise.
141 */
142 extern int32_t context_internalize(context_t *ctx, term_t t);
143
144
145 /*
146 * Build an assumption for Boolean term t:
147 * - this converts t to a literal l in context ctx
148 * then create an indicator variable x in the core
149 * and add the clause (x => l) in the core.
150 * - return a negative code if t can't be internalized
151 * - return the literal x otherwise (where x>=0).
152 */
153 extern int32_t context_add_assumption(context_t *ctx, term_t t);
154
155
156 /*
157 * Add the blocking clause to ctx
158 * - ctx->status must be either SAT or UNKNOWN
159 * - this collects all decision literals in the current truth assignment
160 * (say l_1, ..., l_k) then clears the current assignment and adds the
161 * clause ((not l_1) \/ ... \/ (not l_k)).
162 *
163 * Return code:
164 * - TRIVIALLY_UNSAT: means that the blocking clause is empty (i.e., k = 0)
165 * (in that case, the context status is set to UNSAT)
166 * - CTX_NO_ERROR: means that the blocking clause is not empty (i.e., k > 0)
167 * (In this case, the context status is set to IDLE)
168 */
169 extern int32_t assert_blocking_clause(context_t *ctx);
170
171
172 /*
173 * Check whether the context is consistent
174 * - parameters = search and heuristic parameters to use
175 * - if parameters is NULL, the default values are used
176 *
177 * return status: either STATUS_UNSAT, STATUS_SAT, STATUS_UNKNOWN,
178 * STATUS_INTERRUPTED (these codes are defined in smt_core.h)
179 */
180 extern smt_status_t check_context(context_t *ctx, const param_t *parameters);
181
182
183 /*
184 * Check under assumptions
185 * - parameters = search and heuristic parameters to use
186 * - if parameter is NULL, default values are used
187 * - a = array of n literals = n assumptions
188 * - each a[i] must be defined in ctx->core
189 *
190 * return status: either STATUS_UNSAT, STATUS_SAT, STATUS_UNKNOWN,
191 * STATUS_INTERRUPTED
192 *
193 * If status is STATUS_UNSAT then the assumptions are inconsistent
194 */
195 extern smt_status_t check_context_with_assumptions(context_t *ctx, const param_t *parameters, uint32_t n, const literal_t *a);
196
197
198 /*
199 * Build a model: the context's status must be STATUS_SAT or STATUS_UNKNOWN
200 * - model must be initialized (and empty)
201 * - the model maps a value to every uninterpreted terms present in ctx's
202 * internalization tables
203 * - if model->has_alias is true, the term substitution defined by ctx->intern_tbl
204 * is copied into the model
205 */
206 extern void context_build_model(model_t *model, context_t *ctx);
207
208
209 /*
210 * Build an unsat core: the context's status must be STATUS_UNSAT
211 * - the unsat core is returned in vector *v
212 * - if there are no assumption, the core is empty
213 * - otherwise, the core is constructed from the bad_assumption
214 * and copied in v
215 */
216 extern void context_build_unsat_core(context_t *ctx, ivector_t *v);
217
218
219 /*
220 * Interrupt the search
221 * - this can be called after check_context from a signal handler
222 * - this interrupts the current search
223 * - if clean_interrupt is enabled, calling context_cleanup will
224 * restore the solver to a good state, equivalent to the state
225 * before the call to check_context
226 * - otherwise, the solver is in a bad state from which new assertions
227 * can't be processed. Cleanup is possible via pop (if push/pop is supported)
228 * or reset.
229 */
230 extern void context_stop_search(context_t *ctx);
231
232
233 /*
234 * Cleanup after check is interrupted
235 * - must not be called if the clean_interrupt option is disabled
236 * - restore the context to a good state (status = IDLE)
237 */
238 extern void context_cleanup(context_t *ctx);
239
240
241 /*
242 * Clear boolean assignment and return to the IDLE state.
243 * - this can be called after check returns UNKNOWN or SEARCHING
244 * provided the context's mode isn't ONECHECK
245 * - after this call, additional formulas can be asserted and
246 * another call to check_context is allowed. Model construction
247 * is no longer possible until the next call to check_context.
248 */
249 extern void context_clear(context_t *ctx);
250
251
252 /*
253 * Cleanup after the search returned UNSAT
254 * - if there are assumptions, they are removed
255 * - if the clean_interrupt option is enabled, the state
256 * is restored to what it was at the start of search
257 * - otherwise, this does nothing.
258 *
259 * On exit, the context's status can be either STATUS_IDLE
260 * (if assumptions were removed) or STATUS_UNSAT otherwise.
261 *
262 * NOTE: Call this before context_pop(ctx) if the context status
263 * is unsat.
264 */
265 extern void context_clear_unsat(context_t *ctx);
266
267
268 /*
269 * Precheck: force generation of clauses and other stuff that's
270 * constructed lazily by the solvers. For example, this
271 * can be used to convert all the constraints asserted in the
272 * bitvector to clauses so that we can export the result to DIMACS.
273 *
274 * If ctx status is IDLE:
275 * - the function calls 'start_search' and does one round of propagation.
276 * - if this results in UNSAT, the function returns UNSAT
277 * - otherwise the function returns UNKNOWN and restore the status to
278 * IDLE
279 *
280 * If ctx status is not IDLE, the function returns it and does nothing
281 * else.
282 */
283 extern smt_status_t precheck_context(context_t *ctx);
284
285
286 /*
287 * Solve using another SAT solver
288 * - sat_solver = name of the external SAT solver to use
289 * sat_solver can be either "y2sat" or "cadical"
290 * - verbosity = verbosity level
291 *
292 * This may be used only for BV or pure SAT problems
293 *
294 * If ctx status is IDLE:
295 * - perform one round of propagation to convert the problem to CNF
296 * - call an external SAT solver on the CNF problem
297 *
298 * If ctx status is not IDLE, the function returns it and does nothing
299 * else.
300 */
301 extern smt_status_t check_with_delegate(context_t *ctx, const char *sat_solver, uint32_t verbosity);
302
303
304 /*
305 * Bit-blast then export to DIMACS
306 * - filename = name of the output file
307 * - status = status of the context after bit-blasting
308 *
309 * If ctx status is IDLE
310 * - perform one round of propagation to conver the problem to CNF
311 * - export the CNF to DIMACS
312 *
313 * If ctx status is not IDLE,
314 * - store the stauts in *status and do nothing else
315 *
316 * Return code:
317 * 1 if the DIMACS file was created
318 * 0 if the problem was solved by the propagation round
319 * -1 if there was an error in creating or writing to the file.
320 */
321 extern int32_t bitblast_then_export_to_dimacs(context_t *ctx, const char *filename, smt_status_t *status);
322
323 /*
324 * Simplify then export to DIMACS
325 * - filename = name of the output file
326 * - status = status of the context after CNF conversion + preprocessing
327 *
328 * If ctx status is IDLE
329 * - perform one round of propagation to convert the problem to CNF
330 * - export the CNF to y2sat for extra preprocessing then export that to DIMACS
331 *
332 * If ctx status is not IDLE, the function stores it in *status
333 * If y2sat preprocessing solves the formula, return the status also in *status
334 *
335 * Return code:
336 * 1 if the DIMACS file was created
337 * 0 if the problems was solved by preprocessing (or if ctx status is not IDLE)
338 * -1 if there was an error creating or writing to the file.
339 */
340 extern int32_t process_then_export_to_dimacs(context_t *ctx, const char *filename, smt_status_t *status);
341
342
343
344 /*
345 * FOR TESTING/DEBUGGING
346 */
347
348 /*
349 * Preprocess formula f or array of formulas f[0 ... n-1]
350 * - this does flattening + build substitutions
351 * - return code: as in assert_formulas
352 * - the result is stored in the internal vectors
353 * ctx->top_interns
354 * ctx->top_eqs
355 * ctx->top_atoms
356 * ctx->top_formulas
357 * + ctx->intern stores substitutions
358 */
359 extern int32_t context_process_formula(context_t *ctx, term_t f);
360 extern int32_t context_process_formulas(context_t *ctx, uint32_t n, term_t *f);
361
362
363
364 /*
365 * Read the status: returns one of
366 * STATUS_IDLE (before check_context)
367 * STATUS_SEARCHING (during check_context)
368 * STATUS_UNKNOWN
369 * STATUS_SAT
370 * STATUS_UNSAT
371 * STATUS_INTERRUPTED
372 */
context_status(context_t * ctx)373 static inline smt_status_t context_status(context_t *ctx) {
374 if (ctx->arch == CTX_ARCH_MCSAT) {
375 return mcsat_status(ctx->mcsat);
376 } else {
377 return smt_status(ctx->core);
378 }
379 }
380
381
382 /*
383 * Read the base_level (= number of calls to push)
384 */
context_base_level(context_t * ctx)385 static inline uint32_t context_base_level(context_t *ctx) {
386 return ctx->base_level;
387 }
388
389
390 /*
391 * Value of a Boolean term in ctx
392 * - t must be a Boolean term
393 *
394 * The result can be
395 * - VAL_TRUE if t is true
396 * - VAL_FALSE if t is false
397 * - VAL_UNDEF_FALSE or VAL_UNDEF_TRUE otherwise (value is not known)
398 */
399 extern bval_t context_bool_term_value(context_t *ctx, term_t t);
400
401
402 /*
403 * GARBAGE-COLLECTION SUPPORT
404 */
405
406 /*
407 * Mark all terms present in ctx (to make sure they survive the
408 * next call to term_table_gc).
409 */
410 extern void context_gc_mark(context_t *ctx);
411
412
413 #endif /* __CONTEXT_H */
414