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