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 * Yices solver for SMT benchmarks
21 */
22
23 #if defined(CYGWIN) || defined(MINGW)
24 #ifndef __YICES_DLLSPEC__
25 #define __YICES_DLLSPEC__ __declspec(dllexport)
26 #endif
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdbool.h>
32 #include <signal.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <inttypes.h>
36 #include <gmp.h>
37
38 #include "api/smt_logic_codes.h"
39 #include "api/yices_globals.h"
40
41 #include "context/context.h"
42 #include "context/context_printer.h"
43
44 #include "frontend/smt1/smt_lexer.h"
45 #include "frontend/smt1/smt_parser.h"
46 #include "frontend/smt1/smt_term_stack.h"
47
48 #include "io/concrete_value_printer.h"
49 #include "io/model_printer.h"
50 #include "io/term_printer.h"
51 #include "io/type_printer.h"
52
53 #include "solvers/bv/bvsolver.h"
54 #include "solvers/bv/bvsolver_printer.h"
55 #include "solvers/cdcl/smt_core_printer.h"
56 #include "solvers/egraph/egraph_printer.h"
57 #include "solvers/floyd_warshall/idl_floyd_warshall.h"
58 #include "solvers/floyd_warshall/idl_fw_printer.h"
59 #include "solvers/floyd_warshall/rdl_floyd_warshall.h"
60 #include "solvers/floyd_warshall/rdl_fw_printer.h"
61 #include "solvers/funs/fun_solver.h"
62 #include "solvers/simplex/simplex.h"
63 #include "solvers/simplex/simplex_printer.h"
64
65 #include "utils/command_line.h"
66 #include "utils/cputime.h"
67 #include "utils/memsize.h"
68 #include "utils/timeout.h"
69
70 #include "yices.h"
71 #include "yices_exit_codes.h"
72
73
74 /*
75 * yices_rev is set up at compile time in yices_version.c
76 */
77 extern const char * const yices_rev;
78
79
80 /*
81 * GLOBAL OBJECTS
82 */
83 static lexer_t lexer;
84 static parser_t parser;
85 static tstack_t stack;
86 static smt_benchmark_t bench;
87 static context_t context;
88 static double construction_time, start_search_time, search_time;
89
90
91 /*
92 * Flag for the interrupt handler: true when the context
93 * has been initialized
94 */
95 static bool context_exists;
96
97
98 /*
99 * Trace
100 */
101 static tracer_t tracer;
102
103
104 /*
105 * Conversion of status code in the benchmark header
106 */
107 static const char * const status2string[] = {
108 "none", "unsat", "sat", "unknown",
109 };
110
111
112 /*
113 * Conversion of internalization code to an error message
114 */
115 static const char * const code2error[NUM_INTERNALIZATION_ERRORS] = {
116 "no error",
117 "internal error",
118 "type error",
119 "formula contains free variables",
120 "logic not supported",
121 "context does not support UF",
122 "context does not support scalar types",
123 "context does not support tuples",
124 "context does not support uninterpreted types",
125 "context does not support arithmetic",
126 "context does not support bitvectors",
127 "context does not support function equalities",
128 "context does not support quantifiers",
129 "context does not support lambdas",
130 "not an IDL formula",
131 "not an RDL formula",
132 "non-linear arithmetic not supported",
133 "too many variables for the arithmetic solver",
134 "too many atoms for the arithmetic solver",
135 "arithmetic solver exception",
136 "bitvector solver exception",
137 "theory not supported by MCSAT",
138 };
139
140
141
142 /*
143 * COMMAND LINE ARGUMENTS
144 */
145
146 /*
147 * Option flags other than the ones in params_t
148 */
149 static bool var_elim;
150 static bool flatten_or;
151 static bool learn_eq;
152 static bool break_sym;
153 static bool arith_elim;
154 static bool bvarith_elim;
155 static bool keep_ite;
156 static bool dump_context;
157 static bool dump_internalization;
158 static bool show_model;
159
160 /*
161 * Simplex options not in params_t
162 */
163 static bool eager_lemmas;
164
165
166 /*
167 * Which arithmetic solver to use
168 */
169 typedef enum {
170 ARITH_SOLVER_AUTOMATIC,
171 ARITH_SOLVER_FLOYD_WARSHALL,
172 ARITH_SOLVER_SIMPLEX,
173 } arith_solver_t;
174
175 static arith_solver_t arith_solver;
176
177
178 /*
179 * Timeout value in seconds (0 means no timeout)
180 */
181 static uint32_t timeout;
182
183
184 /*
185 * Filename given on the command line
186 */
187 static char *filename;
188
189 /*
190 * If this flag is true, no search parameters was given on the command line,
191 * so the default should be used.
192 */
193 static bool use_default_params;
194
195 /*
196 * Buffer to store the search parameters if the defaults are not used
197 */
198 static param_t params;
199
200
201 /*
202 * COMMAND LINE OPTIONS AND FLAGS
203 */
204 typedef enum optid {
205 show_version_opt, // print version and exit
206 print_help_opt, // print help and exit
207
208 // Internalization
209 var_elim_opt, // apply var elimination during internalization
210 flatten_opt, // flatten or and disequality terms
211 learneq_opt, // learn UF equalities
212 breaksym_opt, // break symmetries in UF
213 arith_elim_opt, // eliminate arithmetic variables
214 bvarith_elim_opt, // simplification of bitvector arithmetic expressions
215 keep_ite_opt, // keep term if-then-else in the egraph
216
217 // Debug,
218 dump_context_opt, // dump the solver state (after internalization)
219 dump_internalization_opt, // dump the mapping from terms to solver objects (after internalization)
220
221 // Model
222 show_model_opt, // print the model if SAT
223
224 // Restarts
225 fast_restart_opt, // enable fast restart in smt_core
226 c_threshold_opt, // restart parameter
227 c_factor_opt, // restart parameter
228 d_threshold_opt, // restart parameter (only relevant if fast_restart is true)
229 d_factor_opt, // restart parameter (only relevant if fast_restart is true)
230
231 // Clause database reduction
232 r_threshold_opt, // lower limit on conflict-reduction threshold
233 r_fraction_opt,
234 r_factor_opt,
235
236 // Branching heuristics
237 var_decay_opt, // decay factor for variable activities
238 randomness_opt, // percent of random decisions
239 randomseed_opt, // prng seed
240 neg_branching_opt, // branching: set decision variable false
241 pos_branching_opt, // branching: set decision variable true
242 theory_branching_opt, // let the theory solver decide
243 theory_neg_branching_opt, // theory solver + neg for non-atom
244 theory_pos_branching_opt, // theory solver + pos for non-atom
245
246 // Clause learning
247 clause_decay_opt, // decay factor for learned clause
248 cache_tclause_opt, // enable autolearn from theory solver
249 tclause_size_opt, // maximal size of clauses learned from the theory solver
250
251 // Egraph parameters
252 dyn_ack_opt, // dynamic ackermann for non-boolean
253 dyn_boolack_opt, // dynamic ackermann for boolean terms
254 max_ackermann_opt, // limit for non-boolean dynamic ackermann trick
255 max_boolackermann_opt, // limit for boolean dynamic ackermann trick
256 aux_eq_quota_opt, // max number of equalities created by ackermann
257 aux_eq_ratio_opt, // increase ratio
258 max_interface_eqs_opt, // max number or interface equalities in each final_check
259
260 // Arithmetic
261 use_floyd_warshall, // IDL or RDL solver
262 use_simplex, // Simplex solver
263 simplex_eager_lemmas, // generate simple lemmas eagerly
264 simplex_prop_enabled, // enable row-based propagation
265 simplex_prop_threshold, // max size of rows in propagation table
266 simplex_adjust_model, // enable optimized model reconciliation (egraph + simplex)
267 simplex_bland_threshold, // threshold that triggers activation of Bland's rule
268 simplex_check_period, // for integer arithmetic: period of calls to integer_check
269
270 // Array solver
271 max_update_conflicts, // max instances of the update axiom per round
272 max_extensionality, // max instances of the extensionality axiom per round
273
274 // Timeout
275 timeout_opt, // give a timeout
276 } optid_t;
277
278 #define NUM_OPTIONS (timeout_opt+1)
279
280
281 /*
282 * Option descriptors for the command-line parser
283 */
284 static option_desc_t options[NUM_OPTIONS] = {
285 { "version", 'V', FLAG_OPTION, show_version_opt },
286 { "help", 'h', FLAG_OPTION, print_help_opt },
287
288 { "var-elim", '\0', FLAG_OPTION, var_elim_opt },
289 { "flatten", '\0', FLAG_OPTION, flatten_opt },
290 { "learn-eq", '\0', FLAG_OPTION, learneq_opt },
291 { "break-symmetries", '\0', FLAG_OPTION, breaksym_opt },
292 { "arith-elim", '\0', FLAG_OPTION, arith_elim_opt },
293 { "bvarith-elim", '\0', FLAG_OPTION, bvarith_elim_opt },
294 { "keep-ite", '\0', FLAG_OPTION, keep_ite_opt },
295
296 { "dump", '\0', FLAG_OPTION, dump_context_opt },
297 { "dump-internalization", '\0', FLAG_OPTION, dump_internalization_opt },
298
299 { "show-model", '\0', FLAG_OPTION, show_model_opt },
300
301 { "fast-restarts", '\0', FLAG_OPTION, fast_restart_opt },
302 { "c-threshold", '\0', MANDATORY_INT, c_threshold_opt },
303 { "c-factor", '\0', MANDATORY_FLOAT, c_factor_opt },
304 { "d-threshold", '\0', MANDATORY_INT, d_threshold_opt },
305 { "d-factor", '\0', MANDATORY_FLOAT, d_factor_opt },
306
307 { "r-threshold", '\0', MANDATORY_INT, r_threshold_opt },
308 { "r-fraction", '\0', MANDATORY_FLOAT, r_fraction_opt },
309 { "r-factor", '\0', MANDATORY_FLOAT, r_factor_opt },
310
311 { "var-decay", '\0', MANDATORY_FLOAT, var_decay_opt },
312 { "randomness", '\0', MANDATORY_FLOAT, randomness_opt },
313 { "random-seed", '\0', MANDATORY_INT, randomseed_opt },
314 { "neg-branching", '\0', FLAG_OPTION, neg_branching_opt },
315 { "pos-branching", '\0', FLAG_OPTION, pos_branching_opt },
316 { "theory-branching", '\0', FLAG_OPTION, theory_branching_opt },
317 { "th-neg-branching", '\0', FLAG_OPTION, theory_neg_branching_opt },
318 { "th-pos-branching", '\0', FLAG_OPTION, theory_pos_branching_opt },
319
320 { "clause-decay", '\0', MANDATORY_FLOAT, clause_decay_opt },
321 { "cache-tclauses", '\0', FLAG_OPTION, cache_tclause_opt },
322 { "tclause-size", '\0', MANDATORY_INT, tclause_size_opt },
323
324 { "dyn-ack", '\0', FLAG_OPTION, dyn_ack_opt },
325 { "dyn-bool-ack", '\0', FLAG_OPTION, dyn_boolack_opt },
326 { "max-ack", '\0', MANDATORY_INT, max_ackermann_opt },
327 { "max-bool-ack", '\0', MANDATORY_INT, max_boolackermann_opt },
328 { "aux-eq-quota", '\0', MANDATORY_INT, aux_eq_quota_opt },
329 { "aux-eq-ratio", '\0', MANDATORY_FLOAT, aux_eq_ratio_opt },
330 { "max-interface-eqs", '\0', MANDATORY_INT, max_interface_eqs_opt },
331
332 { "floyd-warshall", '\0', FLAG_OPTION, use_floyd_warshall },
333 { "simplex", '\0', FLAG_OPTION, use_simplex },
334 { "eager-lemmas", '\0', FLAG_OPTION, simplex_eager_lemmas },
335 { "simplex-prop", '\0', FLAG_OPTION, simplex_prop_enabled },
336 { "prop-threshold", '\0', MANDATORY_INT, simplex_prop_threshold },
337 { "simplex-adjust-model", '\0', FLAG_OPTION, simplex_adjust_model },
338 { "bland-threshold", '\0', MANDATORY_INT, simplex_bland_threshold },
339 { "icheck-period", '\0', MANDATORY_INT, simplex_check_period },
340
341 { "max-update-conflicts", '\0', MANDATORY_INT, max_update_conflicts },
342 { "max-extensionality", '\0', MANDATORY_INT, max_extensionality },
343
344 { "timeout", 't', MANDATORY_INT, timeout_opt },
345 };
346
347
348 /*
349 * Option value = either an integer or a double
350 */
351 typedef union option_val_u {
352 int32_t i_value;
353 double d_value;
354 } option_val_t;
355
356
357 /*
358 * Flags to indicate the options given on the command line
359 * and for options with a value, what the argument was
360 */
361 static bool opt_set[NUM_OPTIONS];
362 static option_val_t opt_val[NUM_OPTIONS];
363
364
365 /*
366 * Processing of these options
367 */
print_version(void)368 static void print_version(void) {
369 printf("Yices %s\n"
370 "Copyright SRI International.\n"
371 "Linked with GMP %s\n"
372 "Copyright Free Software Foundation, Inc.\n"
373 "Build date: %s\n"
374 "Platform: %s (%s)\n",
375 yices_version, gmp_version, yices_build_date,
376 yices_build_arch, yices_build_mode);
377 fflush(stdout);
378 }
379
yices_help(char * progname)380 static void yices_help(char *progname) {
381 printf("Usage: %s [options] filename\n", progname);
382 printf("Option summary:\n"
383 " General:\n"
384 " --version, -V\n"
385 " --help, -h\n"
386 " --timeout, -t\n"
387 " Internalization:\n"
388 " --var-elim\n"
389 " --flatten\n"
390 " --learn-eq\n"
391 " --break-symmetries\n"
392 " --arith-elim\n"
393 " --keep-ite\n"
394 " Model construction\n"
395 " --show-model\n"
396 " Debugging:\n"
397 " --dump\n"
398 " --dump-internalization\n"
399 " Restart:\n"
400 " --fast-restarts\n"
401 " --c-threshold=<int>\n"
402 " --c-factor=<float>\n"
403 " --d-threshold=<int>\n"
404 " --d-factor=<float>\n"
405 " Learned-clause deletion:\n"
406 " --r-threshold=<int>\n"
407 " --r-fraction=<float>\n"
408 " --r-factor=<float>\n"
409 " Branching heuristic:\n"
410 " --var-decay=<float>\n"
411 " --randomness=<float>\n"
412 " --random-seed=<int>\n"
413 " --neg-branching\n"
414 " --pos-branching\n"
415 " --theory-branching\n"
416 " --th-neg-branching\n"
417 " --th-pos-branching\n"
418 " Clause-learning heuristic\n"
419 " --clause-decay=<float>\n"
420 " --cache-tclauses\n"
421 " --tclause-size\n"
422 " Egraph options:\n"
423 " --dyn-ack\n"
424 " --dyn-bool-ack\n"
425 " --max-ack=<int>\n"
426 " --max-bool-ack=<int>\n"
427 " --aux-eq-quota=<int>\n"
428 " --aux-eq-ratio=<float>\n"
429 " --max-interface-eqs=<int>\n"
430 " Arithmetic:\n"
431 " --floyd-warshall\n"
432 " --simplex\n"
433 " --eager-lemmas\n"
434 " --simplex-prop\n"
435 " --prop-threshold\n"
436 " --simplex-adjust-model\n"
437 " --bland-threshold\n"
438 " --icheck-period\n"
439 " Array solver options:\n"
440 " --max-update-conflicts=<int>\n"
441 " --max-extensionality=<int>\n"
442 "\n"
443 "For bug reporting and other information, please see http://yices.csl.sri.com/\n");
444 fflush(stdout);
445 }
446
447
448 /*
449 * Message for unrecognized options or other errors on the command line.
450 */
yices_usage(char * progname)451 static void yices_usage(char *progname) {
452 fprintf(stderr, "Usage: %s [options] filename\n", progname);
453 fprintf(stderr, "Try '%s --help' for more information\n", progname);
454 }
455
456
457 /*
458 * Name of options k in the options table
459 */
opt_name(optid_t k)460 static inline const char *opt_name(optid_t k) {
461 return options[k].name;
462 }
463
464 /*
465 * Name of option that select branching mode b
466 */
branching_name(branch_t b)467 static const char *branching_name(branch_t b) {
468 const char *name;
469
470 name = NULL;
471 switch (b) {
472 case BRANCHING_DEFAULT:
473 break;
474 case BRANCHING_NEGATIVE:
475 name = opt_name(neg_branching_opt);
476 break;
477 case BRANCHING_POSITIVE:
478 name = opt_name(pos_branching_opt);
479 break;
480 case BRANCHING_THEORY:
481 name = opt_name(theory_branching_opt);
482 break;
483 case BRANCHING_TH_NEG:
484 name = opt_name(theory_neg_branching_opt);
485 break;
486 case BRANCHING_TH_POS:
487 name = opt_name(theory_pos_branching_opt);
488 break;
489 }
490 return name;
491 }
492
493
494
495
496 /*
497 * Check the search parameters and store them in params
498 * - exit and print an error message if they are wrong
499 */
check_parameters(char * progname)500 static void check_parameters(char *progname) {
501 int32_t v;
502 double x;
503
504 use_default_params = true;
505 init_params_to_defaults(¶ms);
506
507 // generic flags
508 var_elim = opt_set[var_elim_opt];
509 flatten_or = opt_set[flatten_opt];
510 learn_eq = opt_set[learneq_opt];
511 break_sym = opt_set[breaksym_opt];
512 arith_elim = opt_set[arith_elim_opt];
513 bvarith_elim = opt_set[bvarith_elim_opt];
514 keep_ite = opt_set[keep_ite_opt];
515 dump_context = opt_set[dump_context_opt];
516 dump_internalization = opt_set[dump_internalization_opt];
517 show_model = opt_set[show_model_opt];
518
519 // timeout (must be positive)
520 if (opt_set[timeout_opt]) {
521 v = opt_val[timeout_opt].i_value;
522 if (v <= 0) {
523 fprintf(stderr, "%s: the timeout must be positive\n", progname);
524 goto error;
525 }
526 timeout = v;
527 }
528
529
530 // specified arithmetic solver: use automatic by default
531 arith_solver = ARITH_SOLVER_AUTOMATIC;
532 if (opt_set[use_floyd_warshall] && opt_set[use_simplex]) {
533 fprintf(stderr, "%s: can't use both Simplex and Floyd-Warshall solvers\n", progname);
534 goto error;
535 }
536 if (opt_set[use_floyd_warshall]) {
537 arith_solver = ARITH_SOLVER_FLOYD_WARSHALL;
538 }
539 if (opt_set[use_simplex]) {
540 arith_solver = ARITH_SOLVER_SIMPLEX;
541 }
542
543 // simplex-specific options
544 eager_lemmas = opt_set[simplex_eager_lemmas];
545
546 // simplex-propagation
547 if (opt_set[simplex_prop_enabled]) {
548 if (arith_solver == ARITH_SOLVER_FLOYD_WARSHALL) {
549 fprintf(stderr, "%s: Simplex option %s not usable if Floyd-Warshall solver is selected\n", progname, opt_name(simplex_prop_enabled));
550 goto error;
551 }
552 params.use_simplex_prop = true;
553 use_default_params = false;
554 }
555
556 if (opt_set[simplex_prop_threshold]) {
557 if (arith_solver == ARITH_SOLVER_FLOYD_WARSHALL) {
558 fprintf(stderr, "%s: Simplex option %s not usable if Floyd-Warshall solver is selected\n", progname, opt_name(simplex_prop_threshold));
559 goto error;
560 }
561 if (! params.use_simplex_prop) {
562 fprintf(stderr, "%s: %s requires %s to be set\n", progname, opt_name(simplex_prop_threshold), opt_name(simplex_prop_enabled));
563 goto error;
564 }
565 v = opt_val[simplex_prop_threshold].i_value;
566 if (v < 0) {
567 fprintf(stderr, "%s: %s can't be negative\n", progname, opt_name(simplex_prop_threshold));
568 goto error;
569 }
570 params.max_prop_row_size = v;
571 use_default_params = false;
572 }
573
574 // Other simplex parameters
575 if (opt_set[simplex_bland_threshold]) {
576 if (arith_solver == ARITH_SOLVER_FLOYD_WARSHALL) {
577 fprintf(stderr, "%s: Simplex option %s not usable if Floyd-Warshall solver is selected\n", progname, opt_name(simplex_bland_threshold));
578 goto error;
579 }
580 v = opt_val[simplex_bland_threshold].i_value;
581 if (v <= 0) {
582 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(simplex_prop_threshold));
583 goto error;
584 }
585 params.bland_threshold = v;
586 use_default_params = false;
587 }
588
589 if (opt_set[simplex_check_period]) {
590 if (arith_solver == ARITH_SOLVER_FLOYD_WARSHALL) {
591 fprintf(stderr, "%s: Simplex option %s not usable if Floyd-Warshall solver is selected\n", progname, opt_name(simplex_check_period));
592 goto error;
593 }
594 v = opt_val[simplex_check_period].i_value;
595 if (v <= 0) {
596 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(simplex_check_period));
597 goto error;
598 }
599 params.integer_check_period = v;
600 use_default_params = false;
601 }
602
603 if (opt_set[simplex_adjust_model]) {
604 if (arith_solver == ARITH_SOLVER_FLOYD_WARSHALL) {
605 fprintf(stderr, "%s: Simplex option %s not usable if Floyd-Warshall solver is selected\n", progname, opt_name(simplex_adjust_model));
606 goto error;
607 }
608 params.adjust_simplex_model = true;
609 use_default_params = false;
610 }
611
612
613 // Restart parameters
614 if (opt_set[fast_restart_opt]) {
615 // set fast_restart flags
616 // set factors to the default
617 params.fast_restart = true;
618 params.c_factor = 1.1;
619 params.d_factor = 1.1;
620 use_default_params = false;
621 }
622
623 if (opt_set[c_threshold_opt]) {
624 v = opt_val[c_threshold_opt].i_value;
625 if (v <= 0) {
626 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(c_threshold_opt));
627 goto error;
628 }
629 params.c_threshold = v;
630 params.d_threshold = v;
631 use_default_params = false;
632 }
633
634 if (opt_set[c_factor_opt]) {
635 x = opt_val[c_factor_opt].d_value;
636 if (x < 1.0) {
637 fprintf(stderr, "%s: %s must be at least 1\n", progname, opt_name(c_factor_opt));
638 goto error;
639 }
640 params.c_factor = x;
641 use_default_params = false;
642 }
643
644 if (opt_set[d_threshold_opt]) {
645 if (params.fast_restart && opt_set[c_threshold_opt]) {
646 v = opt_val[d_threshold_opt].i_value;
647 if (v < params.c_threshold) {
648 fprintf(stderr, "%s: %s must be at least as large as %s\n", progname,
649 opt_name(d_threshold_opt), opt_name(c_threshold_opt));
650 goto error;
651 }
652 params.d_threshold = v;
653 use_default_params = false;
654 } else {
655 fprintf(stderr, "%s: option %s requires both %s and %s\n", progname,
656 opt_name(d_threshold_opt), opt_name(fast_restart_opt),
657 opt_name(c_threshold_opt));
658 goto error;
659 }
660 }
661
662 if (opt_set[d_factor_opt]) {
663 if (params.fast_restart) {
664 x = opt_val[d_factor_opt].d_value;
665 if (x < 1.0) {
666 fprintf(stderr, "%s: %s must be at least 1\n", progname, opt_name(d_factor_opt));
667 goto error;
668 }
669 params.d_factor = x;
670 use_default_params = false;
671 }
672 }
673
674 if (opt_set[r_threshold_opt]) {
675 v = opt_val[r_threshold_opt].i_value;
676 if (v <= 0) {
677 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(r_threshold_opt));
678 goto error;
679 }
680 params.r_threshold = v;
681 use_default_params = false;
682 }
683
684 if (opt_set[r_fraction_opt]) {
685 x = opt_val[r_fraction_opt].d_value;
686 if (x < 0) {
687 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(r_fraction_opt));
688 goto error;
689 }
690 params.r_fraction = x;
691 use_default_params = false;
692 }
693
694 if (opt_set[r_factor_opt]) {
695 x = opt_val[r_factor_opt].d_value;
696 if (x < 1.0) {
697 fprintf(stderr, "%s: %s must be at least 1\n", progname, opt_name(r_factor_opt));
698 goto error;
699 }
700 params.r_factor = x;
701 use_default_params = false;
702 }
703
704 // Variable activity and randomness
705 if (opt_set[var_decay_opt]) {
706 x = opt_val[var_decay_opt].d_value;
707 if (x < 0 || x > 1.0) {
708 fprintf(stderr, "%s: %s must be between 0.0 and 1.0\n", progname, opt_name(var_decay_opt));
709 goto error;
710 }
711 params.var_decay = x;
712 use_default_params = false;
713 }
714
715 if (opt_set[randomness_opt]) {
716 x = opt_val[randomness_opt].d_value;
717 if (x < 0 || x > 1.0) {
718 fprintf(stderr, "%s: %s must be between 0.0 and 1.0\n", progname, opt_name(randomness_opt));
719 goto error;
720 }
721 params.randomness = x;
722 use_default_params = false;
723 }
724
725 if (opt_set[randomseed_opt]) {
726 v = opt_val[randomseed_opt].i_value;
727 params.random_seed = (uint32_t) v;
728 }
729
730 // Branching mode
731 if (opt_set[theory_neg_branching_opt]) {
732 if (params.branching != BRANCHING_DEFAULT) {
733 fprintf(stderr, "%s: conflict between branching options %s and %s (pick one)\n", progname,
734 opt_name(neg_branching_opt), branching_name(params.branching));
735 goto error;
736 }
737 params.branching = BRANCHING_TH_NEG;
738 use_default_params = false;
739 }
740
741 if (opt_set[theory_pos_branching_opt]) {
742 if (params.branching != BRANCHING_DEFAULT) {
743 fprintf(stderr, "%s: conflict between branching options %s and %s (pick one)\n", progname,
744 opt_name(neg_branching_opt), branching_name(params.branching));
745 goto error;
746 }
747 params.branching = BRANCHING_TH_POS;
748 use_default_params = false;
749 }
750
751 if (opt_set[neg_branching_opt]) {
752 if (params.branching != BRANCHING_DEFAULT) {
753 fprintf(stderr, "%s: conflict between branching options %s and %s (pick one)\n", progname,
754 opt_name(neg_branching_opt), branching_name(params.branching));
755 goto error;
756 }
757 params.branching = BRANCHING_NEGATIVE;
758 use_default_params = false;
759 }
760
761 if (opt_set[pos_branching_opt]) {
762 if (params.branching != BRANCHING_DEFAULT) {
763 fprintf(stderr, "%s: conflict between branching options %s and %s (pick one)\n", progname,
764 opt_name(pos_branching_opt), branching_name(params.branching));
765 goto error;
766 }
767 params.branching = BRANCHING_POSITIVE;
768 use_default_params = false;
769 }
770
771 if (opt_set[theory_branching_opt]) {
772 if (params.branching != BRANCHING_DEFAULT) {
773 fprintf(stderr, "%s: conflict between branching options %s and %s (pick one)\n", progname,
774 opt_name(theory_branching_opt), branching_name(params.branching));
775 goto error;
776 }
777 params.branching = BRANCHING_THEORY;
778 use_default_params = false;
779 }
780
781 if (opt_set[clause_decay_opt]) {
782 x = opt_val[clause_decay_opt].d_value;
783 if (x < 0 || x > 1.0) {
784 fprintf(stderr, "%s: %s must be between 0.0 and 1.0\n", progname, opt_name(clause_decay_opt));
785 goto error;
786 }
787 params.clause_decay = x;
788 use_default_params = false;
789 }
790
791 if (opt_set[cache_tclause_opt]) {
792 params.cache_tclauses = true;
793 params.tclause_size = 8;
794 use_default_params = false;
795 }
796
797 if (opt_set[tclause_size_opt]) {
798 if (params.cache_tclauses) {
799 v = opt_val[tclause_size_opt].i_value;
800 if (v < 0) {
801 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(tclause_size_opt));
802 goto error;
803 }
804 params.tclause_size = v;
805 use_default_params = false;
806 }
807 }
808
809 // Egraph options
810 if (opt_set[dyn_ack_opt]) {
811 params.use_dyn_ack = true;
812 // use default max_ackermann, aux_eq_ratio, aux_eq_quota from context_solver.c
813 use_default_params = false;
814 }
815
816 if (opt_set[dyn_boolack_opt]) {
817 params.use_bool_dyn_ack = true;
818 use_default_params = false;
819 }
820
821 if (opt_set[max_ackermann_opt]) {
822 if (params.use_dyn_ack) {
823 v = opt_val[max_ackermann_opt].i_value;
824 if (v < 0) {
825 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(max_ackermann_opt));
826 goto error;
827 }
828 params.max_ackermann = v;
829 } else {
830 fprintf(stderr, "%s: %s requires %s\n", progname, opt_name(max_ackermann_opt), opt_name(dyn_ack_opt));
831 goto error;
832 }
833 }
834
835 if (opt_set[max_boolackermann_opt]) {
836 if (params.use_bool_dyn_ack) {
837 v = opt_val[max_boolackermann_opt].i_value;
838 if (v < 0) {
839 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(max_boolackermann_opt));
840 goto error;
841 }
842 params.max_boolackermann = v;
843 } else {
844 fprintf(stderr, "%s: %s requires %s\n", progname, opt_name(max_boolackermann_opt),
845 opt_name(dyn_boolack_opt));
846 goto error;
847 }
848 }
849
850 if (opt_set[aux_eq_quota_opt]) {
851 if (params.use_dyn_ack || params.use_bool_dyn_ack) {
852 v = opt_val[aux_eq_quota_opt].i_value;
853 if (v < 0) {
854 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(aux_eq_quota_opt));
855 goto error;
856 }
857 params.aux_eq_quota = v;
858 } else {
859 fprintf(stderr, "%s: %s requires %s or %s\n", progname, opt_name(aux_eq_quota_opt),
860 opt_name(dyn_ack_opt), opt_name(dyn_boolack_opt));
861 goto error;
862 }
863 }
864
865 if (opt_set[aux_eq_ratio_opt]) {
866 if (params.use_dyn_ack || params.use_bool_dyn_ack) {
867 x = opt_val[aux_eq_ratio_opt].d_value;
868 if (x <= 0.0) {
869 fprintf(stderr, "%s: %s must be positive\n", progname, opt_name(aux_eq_ratio_opt));
870 goto error;
871 }
872 params.aux_eq_ratio = x;
873 } else {
874 fprintf(stderr, "%s: %s requires %s or %s\n", progname, opt_name(aux_eq_ratio_opt),
875 opt_name(dyn_ack_opt), opt_name(dyn_boolack_opt));
876 goto error;
877 }
878 }
879
880 if (opt_set[max_interface_eqs_opt]) {
881 v = opt_val[max_interface_eqs_opt].i_value;
882 if (v < 1) {
883 fprintf(stderr, "%s: %s must be at least one\n", progname, opt_name(max_interface_eqs_opt));
884 goto error;
885 }
886 params.max_interface_eqs = v;
887 use_default_params = false;
888 }
889
890
891 // Array solver options
892 if (opt_set[max_update_conflicts]) {
893 v = opt_val[max_update_conflicts].i_value;
894 if (v < 1) {
895 fprintf(stderr, "%s: %s must be at least one\n", progname, opt_name(max_update_conflicts));
896 goto error;
897 }
898 params.max_update_conflicts = v;
899 use_default_params = false;
900 }
901
902 if (opt_set[max_extensionality]) {
903 v = opt_val[max_extensionality].i_value;
904 if (v < 1) {
905 fprintf(stderr, "%s: %s must be at least one\n", progname, opt_name(max_update_conflicts));
906 goto error;
907 }
908 params.max_extensionality = v;
909 use_default_params = false;
910 }
911
912 return;
913
914 error:
915 exit(YICES_EXIT_USAGE);
916 }
917
918
919 /*
920 * Parse the command line and fill-in the parameters
921 */
parse_command_line(int argc,char * argv[])922 static void parse_command_line(int argc, char *argv[]) {
923 cmdline_parser_t parser;
924 cmdline_elem_t elem;
925 uint32_t i;
926 optid_t k;
927
928 filename = NULL;
929 var_elim = false;
930 dump_context = false;
931 dump_internalization = false;
932 timeout = 0;
933
934 for(i=0; i<NUM_OPTIONS; i++) {
935 opt_set[i] = false;
936 }
937
938 init_cmdline_parser(&parser, options, NUM_OPTIONS, argv, argc);
939
940 for (;;) {
941 cmdline_parse_element(&parser, &elem);
942 switch (elem.status) {
943 case cmdline_done:
944 goto done;
945
946 case cmdline_argument:
947 if (filename == NULL) {
948 filename = elem.arg;
949 } else {
950 fprintf(stderr, "%s: too many arguments\n", parser.command_name);
951 yices_usage(parser.command_name);
952 exit(YICES_EXIT_USAGE);
953 }
954 break;
955
956 case cmdline_option:
957 k = elem.key;
958 opt_set[k] = true;
959 switch (k) {
960 case show_version_opt:
961 print_version();
962 exit(YICES_EXIT_SUCCESS);
963
964 case print_help_opt:
965 yices_help(parser.command_name);
966 exit(YICES_EXIT_SUCCESS);
967
968 // boolean options
969 case var_elim_opt:
970 case flatten_opt:
971 case learneq_opt:
972 case breaksym_opt:
973 case arith_elim_opt:
974 case bvarith_elim_opt:
975 case keep_ite_opt:
976 case dump_context_opt:
977 case dump_internalization_opt:
978 case show_model_opt:
979 case fast_restart_opt:
980 case neg_branching_opt:
981 case pos_branching_opt:
982 case theory_branching_opt:
983 case theory_neg_branching_opt:
984 case theory_pos_branching_opt:
985 case cache_tclause_opt:
986 case dyn_ack_opt:
987 case dyn_boolack_opt:
988 case use_floyd_warshall:
989 case use_simplex:
990 case simplex_eager_lemmas:
991 case simplex_prop_enabled:
992 case simplex_adjust_model:
993 break;
994
995 // integer parameters
996 case c_threshold_opt:
997 case d_threshold_opt:
998 case r_threshold_opt:
999 case randomseed_opt:
1000 case tclause_size_opt:
1001 case max_ackermann_opt:
1002 case max_boolackermann_opt:
1003 case aux_eq_quota_opt:
1004 case max_interface_eqs_opt:
1005 case simplex_prop_threshold:
1006 case simplex_bland_threshold:
1007 case simplex_check_period:
1008 case max_update_conflicts:
1009 case max_extensionality:
1010 case timeout_opt:
1011 opt_val[k].i_value = elem.i_value;
1012 break;
1013
1014 // real-valued parameters
1015 case c_factor_opt:
1016 case d_factor_opt:
1017 case r_fraction_opt:
1018 case r_factor_opt:
1019 case var_decay_opt:
1020 case randomness_opt:
1021 case clause_decay_opt:
1022 case aux_eq_ratio_opt:
1023 opt_val[k].d_value = elem.d_value;
1024 break;
1025 }
1026 break;
1027
1028 case cmdline_error:
1029 cmdline_print_error(&parser, &elem);
1030 exit(YICES_EXIT_USAGE);
1031 }
1032 }
1033
1034 done:
1035 check_parameters(parser.command_name);
1036 }
1037
1038
1039
1040 /**********************************
1041 * PRINT STATISTICS AND RESULTS *
1042 *********************************/
1043
1044 /*
1045 * Version header
1046 */
print_yices_header(FILE * f)1047 static void print_yices_header(FILE *f) {
1048 fprintf(f, "Yices %s, Copyright SRI International.\n", yices_version);
1049 fprintf(f, "GMP %s, Copyright Free Software Foundation, Inc\n", gmp_version);
1050 fprintf(f, "Build date: %s\n", yices_build_date);
1051 fprintf(f, "Platform: %s (%s)\n", yices_build_arch, yices_build_mode);
1052 fprintf(f, "Revision: %s\n", yices_rev);
1053 fprintf(f, "----\n");
1054 }
1055
1056
1057 /*
1058 * Benchmark header
1059 */
print_benchmark(FILE * f,smt_benchmark_t * bench)1060 static void print_benchmark(FILE *f, smt_benchmark_t *bench) {
1061 fprintf(f, "Benchmark: %s\n", bench->name);
1062 fprintf(f, "Logic: %s\n", bench->logic_name);
1063 fprintf(f, "Status: %s\n", status2string[bench->status]);
1064 }
1065
1066
1067 /*
1068 * Statistics in the smt_core
1069 */
show_stats(dpll_stats_t * stat)1070 static void show_stats(dpll_stats_t *stat) {
1071 printf("Core\n");
1072 printf(" restarts : %"PRIu32"\n", stat->restarts);
1073 printf(" simplify db : %"PRIu32"\n", stat->simplify_calls);
1074 printf(" reduce db : %"PRIu32"\n", stat->reduce_calls);
1075 printf(" remove irrelevant : %"PRIu32"\n", stat->remove_calls);
1076 printf(" decisions : %"PRIu64"\n", stat->decisions);
1077 printf(" random decisions : %"PRIu64"\n", stat->random_decisions);
1078 printf(" propagations : %"PRIu64"\n", stat->propagations);
1079 printf(" conflicts : %"PRIu64"\n", stat->conflicts);
1080 printf(" theory propagations : %"PRIu32"\n", stat->th_props);
1081 printf(" propagation-lemmas : %"PRIu32"\n", stat->th_prop_lemmas);
1082 printf(" theory conflicts : %"PRIu32"\n", stat->th_conflicts);
1083 printf(" conflict-lemmas : %"PRIu32"\n", stat->th_conflict_lemmas);
1084
1085 printf(" lits in pb. clauses : %"PRIu64"\n", stat->prob_literals);
1086 printf(" lits in learned clauses : %"PRIu64"\n", stat->learned_literals);
1087 printf(" total lits. in learned : %"PRIu64"\n", stat->literals_before_simpl);
1088 printf(" subsumed lits. : %"PRIu64"\n", stat->subsumed_literals);
1089 printf(" deleted pb. clauses : %"PRIu64"\n", stat->prob_clauses_deleted);
1090 printf(" deleted learned clauses : %"PRIu64"\n", stat->learned_clauses_deleted);
1091 printf(" deleted binary clauses : %"PRIu64"\n", stat->bin_clauses_deleted);
1092 }
1093
1094 /*
1095 * Egraph statistics
1096 */
show_egraph_stats(egraph_stats_t * stat)1097 static void show_egraph_stats(egraph_stats_t *stat) {
1098 printf("Egraph\n");
1099 printf(" eq from simplex : %"PRIu32"\n", stat->eq_props);
1100 printf(" app/update reductions : %"PRIu32"\n", stat->app_reductions);
1101 printf(" prop. to core : %"PRIu32"\n", stat->th_props);
1102 printf(" conflicts : %"PRIu32"\n", stat->th_conflicts);
1103 printf(" non-distinct lemmas : %"PRIu32"\n", stat->nd_lemmas);
1104 printf(" auxiliary eqs. created : %"PRIu32"\n", stat->aux_eqs);
1105 printf(" dyn boolack. lemmas : %"PRIu32"\n", stat->boolack_lemmas);
1106 printf(" other dyn ack.lemmas : %"PRIu32"\n", stat->ack_lemmas);
1107 printf(" final checks : %"PRIu32"\n", stat->final_checks);
1108 printf(" interface equalities : %"PRIu32"\n", stat->interface_eqs);
1109 }
1110
1111 /*
1112 * Array/function solver statistics
1113 */
show_funsolver_stats(fun_solver_stats_t * stat)1114 static void show_funsolver_stats(fun_solver_stats_t *stat) {
1115 printf("Arrays\n");
1116 printf(" init. variables : %"PRIu32"\n", stat->num_init_vars);
1117 printf(" init. edges : %"PRIu32"\n", stat->num_init_edges);
1118 printf(" update axiom1 : %"PRIu32"\n", stat->num_update_axiom1);
1119 printf(" update axiom2 : %"PRIu32"\n", stat->num_update_axiom2);
1120 printf(" extensionality axioms : %"PRIu32"\n", stat->num_extensionality_axiom);
1121 }
1122
1123 /*
1124 * Simplex statistics
1125 */
show_simplex_stats(simplex_stats_t * stat)1126 static void show_simplex_stats(simplex_stats_t *stat) {
1127 printf("Simplex\n");
1128 printf(" init. variables : %"PRIu32"\n", stat->num_init_vars);
1129 printf(" init. rows : %"PRIu32"\n", stat->num_init_rows);
1130 printf(" init. atoms : %"PRIu32"\n", stat->num_atoms);
1131 printf(" end atoms : %"PRIu32"\n", stat->num_end_atoms);
1132 printf(" elim. candidates : %"PRIu32"\n", stat->num_elim_candidates);
1133 printf(" elim. rows : %"PRIu32"\n", stat->num_elim_rows);
1134 printf(" fixed vars after simpl. : %"PRIu32"\n", stat->num_simpl_fvars);
1135 printf(" rows after simpl. : %"PRIu32"\n", stat->num_simpl_rows);
1136 printf(" fixed vars : %"PRIu32"\n", stat->num_fixed_vars);
1137 printf(" rows in init. tableau : %"PRIu32"\n", stat->num_rows);
1138 printf(" rows in final tableau : %"PRIu32"\n", stat->num_end_rows);
1139 printf(" calls to make_feasible : %"PRIu32"\n", stat->num_make_feasible);
1140 printf(" pivots : %"PRIu32"\n", stat->num_pivots);
1141 printf(" bland-rule activations : %"PRIu32"\n", stat->num_blands);
1142 printf(" simple lemmas : %"PRIu32"\n", stat->num_binary_lemmas);
1143 // printf(" propagation lemmas : %"PRIu32"\n", stat->num_prop_lemmas); (it's always zero)
1144 printf(" prop. to core : %"PRIu32"\n", stat->num_props);
1145 printf(" derived bounds : %"PRIu32"\n", stat->num_bound_props);
1146 printf(" productive propagations : %"PRIu32"\n", stat->num_prop_expl);
1147 printf(" conflicts : %"PRIu32"\n", stat->num_conflicts);
1148 printf(" interface lemmas : %"PRIu32"\n", stat->num_interface_lemmas);
1149 printf(" reduced inter. lemmas : %"PRIu32"\n", stat->num_reduced_inter_lemmas);
1150 printf(" trichotomy lemmas : %"PRIu32"\n", stat->num_tricho_lemmas);
1151 printf(" reduced tricho. lemmas : %"PRIu32"\n", stat->num_reduced_tricho);
1152 if (stat->num_make_intfeasible > 0 || stat->num_dioph_checks > 0) {
1153 printf("Integer arithmetic\n");
1154 printf(" make integer feasible : %"PRIu32"\n", stat->num_make_intfeasible);
1155 printf(" branch atoms : %"PRIu32"\n", stat->num_branch_atoms);
1156 printf(" Gomory cuts : %"PRIu32"\n", stat->num_gomory_cuts);
1157 printf("bound strengthening\n");
1158 printf(" conflicts : %"PRIu32"\n", stat->num_bound_conflicts);
1159 printf(" recheck conflicts : %"PRIu32"\n", stat->num_bound_recheck_conflicts);
1160 printf("integrality tests\n");
1161 printf(" conflicts : %"PRIu32"\n", stat->num_itest_conflicts);
1162 printf(" bound conflicts : %"PRIu32"\n", stat->num_itest_bound_conflicts);
1163 printf(" recheck conflicts : %"PRIu32"\n", stat->num_itest_recheck_conflicts);
1164 printf("diohpantine solver\n");
1165 printf(" gcd conflicts : %"PRIu32"\n", stat->num_dioph_gcd_conflicts);
1166 printf(" dioph checks : %"PRIu32"\n", stat->num_dioph_checks);
1167 printf(" dioph conflicts : %"PRIu32"\n", stat->num_dioph_conflicts);
1168 printf(" bound conflicts : %"PRIu32"\n", stat->num_dioph_bound_conflicts);
1169 printf(" recheck conflicts : %"PRIu32"\n", stat->num_dioph_recheck_conflicts);
1170 }
1171 }
1172
1173
1174 /*
1175 * Bitvector solver statistics
1176 */
show_bvsolver_stats(bv_solver_t * solver)1177 static void show_bvsolver_stats(bv_solver_t *solver) {
1178 printf("Bit-vectors\n");
1179 printf(" variables : %"PRIu32"\n", bv_solver_num_vars(solver));
1180 printf(" atoms : %"PRIu32"\n", bv_solver_num_atoms(solver));
1181 printf(" eq. atoms : %"PRIu32"\n", bv_solver_num_eq_atoms(solver));
1182 printf(" dyn eq. atoms : %"PRIu32"\n", solver->stats.on_the_fly_atoms);
1183 printf(" ge atoms : %"PRIu32"\n", bv_solver_num_ge_atoms(solver));
1184 printf(" sge atoms : %"PRIu32"\n", bv_solver_num_sge_atoms(solver));
1185 printf(" equiv lemmas : %"PRIu32"\n", solver->stats.equiv_lemmas);
1186 printf(" equiv conflicts : %"PRIu32"\n", solver->stats.equiv_conflicts);
1187 printf(" semi-equiv lemmas : %"PRIu32"\n", solver->stats.half_equiv_lemmas);
1188 printf(" interface lemmas : %"PRIu32"\n", solver->stats.interface_lemmas);
1189 }
1190
1191
1192
1193 /*
1194 * Get the arithmetic solver
1195 */
context_get_simplex_solver(context_t * ctx)1196 static inline simplex_solver_t *context_get_simplex_solver(context_t *ctx) {
1197 assert(context_has_simplex_solver(ctx));
1198 return (simplex_solver_t *) ctx->arith_solver;
1199 }
1200
1201
1202 /*
1203 * Statistics + result, after the search
1204 */
print_results(void)1205 static void print_results(void) {
1206 smt_core_t *core;
1207 egraph_t *egraph;
1208 simplex_solver_t *simplex;
1209 fun_solver_t *fsolver;
1210 uint32_t resu;
1211 double mem_used;
1212
1213 search_time = get_cpu_time() - start_search_time;
1214 if (search_time < 0.0) {
1215 search_time = 0.0;
1216 }
1217
1218 core = context.core;
1219 resu = context.core->status;
1220
1221 show_stats(&core->stats);
1222 printf(" boolean variables : %"PRIu32"\n", core->nvars);
1223 printf(" atoms : %"PRIu32"\n", core->atoms.natoms);
1224
1225 egraph = context.egraph;
1226 if (egraph != NULL) {
1227 show_egraph_stats(&egraph->stats);
1228 printf(" egraph terms : %"PRIu32"\n", egraph->terms.nterms);
1229 if (context_has_fun_solver(&context)) {
1230 fsolver = context.fun_solver;
1231 show_funsolver_stats(&fsolver->stats);
1232 }
1233 }
1234
1235 if (context_has_simplex_solver(&context)) {
1236 simplex = context_get_simplex_solver(&context);
1237 if (simplex != NULL) {
1238 simplex_collect_statistics(simplex);
1239 show_simplex_stats(&simplex->stats);
1240 }
1241 }
1242
1243 if (context_has_bv_solver(&context)) {
1244 show_bvsolver_stats(context.bv_solver);
1245 }
1246
1247 printf("\nSearch time : %.4f s\n", search_time);
1248 mem_used = mem_size() / (1024 * 1024);
1249 if (mem_used > 0) {
1250 printf("Memory used : %.2f MB\n", mem_used);
1251 }
1252 printf("\n\n");
1253
1254 if (resu == STATUS_SAT) {
1255 printf("sat\n");
1256 } else if (resu == STATUS_UNSAT) {
1257 printf("unsat\n");
1258 } else {
1259 printf("unknown\n");
1260 }
1261
1262 fflush(stdout);
1263 }
1264
1265
1266 /*
1267 * Statistics on problem size, before the search
1268 */
print_presearch_stats(void)1269 static void print_presearch_stats(void) {
1270 smt_core_t *core;
1271 egraph_t *egraph;
1272
1273 core = context.core;
1274 egraph = context.egraph;
1275
1276
1277 printf("boolean variables : %"PRIu32"\n", core->nvars);
1278 printf("atoms : %"PRIu32"\n", core->atoms.natoms);
1279 if (egraph != NULL) {
1280 printf("egraph terms : %"PRIu32"\n", egraph->terms.nterms);
1281 printf("app/update reductions : %"PRIu32"\n", egraph->stats.app_reductions);
1282 }
1283
1284 if (context_has_simplex_solver(&context)) {
1285 printf("arithmetic solver : Simplex\n");
1286 } else if (context_has_idl_solver(&context)) {
1287 printf("arithmetic solver : IDL Floyd-Warshall\n");
1288 } else if (context_has_rdl_solver(&context)) {
1289 printf("arithmetic solver : RDL Floyd-Warshall\n");
1290 }
1291
1292 printf("\n");
1293 fflush(stdout);
1294 }
1295
1296
1297 /*
1298 * Print parameters and settings
1299 */
print_options(FILE * f,context_t * ctx)1300 static void print_options(FILE *f, context_t *ctx) {
1301 simplex_solver_t *simplex;
1302
1303 if (context_has_preprocess_options(ctx)) {
1304 fprintf(f, "Preprocessing:");
1305 if (context_var_elim_enabled(ctx)) {
1306 fprintf(f, " --var-elim");
1307 }
1308 if (context_flatten_or_enabled(ctx)) {
1309 fprintf(f, " --flatten-or");
1310 }
1311 if (context_flatten_diseq_enabled(ctx)) {
1312 fprintf(f, " --flatten-diseq");
1313 }
1314 if (context_eq_abstraction_enabled(ctx)) {
1315 fprintf(f, " --learn-eq");
1316 }
1317 if (context_breaksym_enabled(ctx)) {
1318 fprintf(f, " --learn-eq");
1319 }
1320 if (context_arith_elim_enabled(ctx)) {
1321 fprintf(f, " --arith-elim");
1322 }
1323 if (context_bvarith_elim_enabled(ctx)) {
1324 fprintf(f, " --bvarith-elim");
1325 }
1326 if (context_keep_ite_enabled(ctx)) {
1327 fprintf(f, " --keep-ite");
1328 }
1329 fprintf(f, "\n");
1330 }
1331
1332 if (context_has_arith_solver(ctx)) {
1333 fprintf(f, "Arithmetic: ");
1334 if (context_has_simplex_solver(ctx)) {
1335 fprintf(f, " --simplex");
1336 simplex = context_get_simplex_solver(ctx);
1337 if (simplex_option_enabled(simplex, SIMPLEX_EAGER_LEMMAS)) {
1338 fprintf(f, " --eager-lemmas");
1339 }
1340 if (simplex_option_enabled(simplex, SIMPLEX_PROPAGATION) ||
1341 params.use_simplex_prop) {
1342 fprintf(f, " --simplex-prop --prop-threshold=%"PRIu32, params.max_prop_row_size);
1343 }
1344 if (simplex_option_enabled(simplex, SIMPLEX_ADJUST_MODEL) ||
1345 params.adjust_simplex_model) {
1346 fprintf(f, " --simplex-adjust-model");
1347 }
1348 fprintf(f, " --bland-threshold=%"PRIu32, params.bland_threshold);
1349 fprintf(f, " --icheck-period=%"PRId32, params.integer_check_period);
1350 } else if (context_has_rdl_solver(ctx) || context_has_idl_solver(ctx)) {
1351 fprintf(f, " --floyd-warshall");
1352 }
1353 fprintf(f, "\n");
1354 }
1355
1356 if (context_has_egraph(ctx)) {
1357 fprintf(f, "Egraph: ");
1358 if (params.use_dyn_ack || params.use_bool_dyn_ack) {
1359 if (params.use_dyn_ack) {
1360 fprintf(f, " --dyn-ack --max-ack=%"PRIu32, params.max_ackermann);
1361 }
1362 if (params.use_bool_dyn_ack) {
1363 fprintf(f, " --dyn-bool-ack --max-bool-ack=%"PRIu32, params.max_boolackermann);
1364 }
1365 fprintf(f, " --aux-eq-quota=%"PRIu32" --aux-eq-ratio=%.3f", params.aux_eq_quota, params.aux_eq_ratio);
1366 }
1367 fprintf(f, " --max-interface-eqs=%"PRIu32"\n", params.max_interface_eqs);
1368 }
1369
1370 if (context_has_fun_solver(ctx)) {
1371 fprintf(f, "Array solver: --max-update-conflicts=%"PRIu32" --max-extensionality=%"PRIu32"\n",
1372 params.max_update_conflicts, params.max_extensionality);
1373 }
1374
1375 if (params.fast_restart || params.cache_tclauses || params.branching != BRANCHING_DEFAULT) {
1376 fprintf(f, "Core: ");
1377 if (params.fast_restart) {
1378 fprintf(f, " --fast-restarts");
1379 }
1380 if (params.cache_tclauses) {
1381 fprintf(f, " --cache-tclauses --tclause-size=%"PRIu32, params.tclause_size);
1382 }
1383 switch (params.branching) {
1384 case BRANCHING_DEFAULT:
1385 break;
1386 case BRANCHING_NEGATIVE:
1387 fprintf(f, " --neg-branching");
1388 break;
1389 case BRANCHING_POSITIVE:
1390 fprintf(f, " --pos-branching");
1391 break;
1392 case BRANCHING_THEORY:
1393 fprintf(f, " --theory-branching");
1394 break;
1395 case BRANCHING_TH_NEG:
1396 fprintf(f, " --th-neg-branching");
1397 break;
1398 case BRANCHING_TH_POS:
1399 fprintf(f, " --th-pos-branching");
1400 break;
1401 }
1402 fprintf(f, "\n");
1403 }
1404 fprintf(f, "\n");
1405 }
1406
1407
1408
1409
1410 /*
1411 * Print the translation code returned by assert
1412 */
print_internalization_code(int32_t code)1413 static void print_internalization_code(int32_t code) {
1414 assert(-NUM_INTERNALIZATION_ERRORS < code && code <= TRIVIALLY_UNSAT);
1415 if (code == TRIVIALLY_UNSAT) {
1416 printf("Assertions simplify to false\n\n");
1417 printf("unsat\n");
1418 fflush(stdout);
1419 } else if (code < 0) {
1420 code = - code;
1421 printf("unknown\n");
1422 fprintf(stderr, "Internalization error: %s\n\n", code2error[code]);
1423 }
1424 }
1425
1426
1427 /*
1428 * Allocate and initialize a model
1429 * - set has_alias true
1430 */
new_model(void)1431 static model_t *new_model(void) {
1432 model_t *tmp;
1433
1434 tmp = (model_t *) safe_malloc(sizeof(model_t));
1435 init_model(tmp, __yices_globals.terms, true);
1436 return tmp;
1437 }
1438
1439
1440 /*
1441 * Free model
1442 */
free_model(model_t * model)1443 static void free_model(model_t *model) {
1444 delete_model(model);
1445 safe_free(model);
1446 }
1447
1448
1449 /*
1450 * TEMPORARY FOR TESTING THE EVALUATOR CODE
1451 */
1452 #include "model/model_eval.h"
1453
1454 #if TEST_EVALUATOR
1455
test_evaluator(FILE * f,model_t * model)1456 static void test_evaluator(FILE *f, model_t *model) {
1457 evaluator_t eval;
1458 term_table_t *terms;
1459 uint32_t i, n;
1460 value_t v;
1461
1462 init_evaluator(&eval, model);
1463 terms = __yices_globals.terms;
1464
1465 n = terms->nelems;
1466 for (i=0; i<n; i++) {
1467 if (good_term(terms, i)) {
1468 fprintf(f, "test eval: term ");
1469 print_term_id(f, i);
1470 fprintf(f, " = ");
1471 print_term_shallow(f, i);
1472 fflush(f);
1473 v = eval_in_model(&eval, i);
1474 fprintf(f, "evaluates to: ");
1475 if (v >= 0) {
1476 vtbl_print_object(f, model_get_vtbl(model), v);
1477 if (object_is_function(model_get_vtbl(model), v)) {
1478 fprintf(f, "\n");
1479 vtbl_print_function(f, model_get_vtbl(model), v, true);
1480 }
1481 fprintf(f, "\n\n");
1482 } else {
1483 fprintf(f, "unknown (code = %"PRId32")\n\n", v);
1484 }
1485 fflush(f);
1486 reset_evaluator(&eval);
1487 }
1488 }
1489
1490 delete_evaluator(&eval);
1491 }
1492 #endif
1493
check_model(FILE * f,smt_benchmark_t * bench,model_t * model)1494 static void check_model(FILE *f, smt_benchmark_t *bench, model_t *model) {
1495 evaluator_t eval;
1496 term_table_t *terms;
1497 uint32_t i, n;
1498 term_t t;
1499 value_t v;
1500
1501 init_evaluator(&eval, model);
1502 terms = __yices_globals.terms;
1503
1504 n = bench->nformulas;
1505 for (i=0; i<n; i++) {
1506 t = bench->formulas[i];
1507 assert(good_term(terms, t));
1508 v = eval_in_model(&eval, t);
1509 if (v < 0 || is_false(model_get_vtbl(model), v)) {
1510 fprintf(f, "\n==== Assertion[%"PRIu32"] ====\n", i);
1511 print_term_id(f, t);
1512 fprintf(f, " = ");
1513 print_term(f, terms, t);
1514 fprintf(f, "\n");
1515 fflush(f);
1516 fprintf(f, "evaluates to: ");
1517 if (v >= 0) {
1518 vtbl_print_object(f, model_get_vtbl(model), v);
1519 fprintf(f, "\n\n");
1520 } else {
1521 fprintf(f, "unknown (code = %"PRId32")\n\n", v);
1522 }
1523 fflush(f);
1524 }
1525 reset_evaluator(&eval);
1526 }
1527
1528 delete_evaluator(&eval);
1529 }
1530
1531
1532 /*
1533 * DUMP SOLVER STATE AFTER INTERNALIZATION
1534 */
1535
1536 /*
1537 * Dump the internalization table into file f
1538 */
dump_internalization_table(FILE * f,context_t * ctx)1539 static void dump_internalization_table(FILE *f, context_t *ctx) {
1540 fprintf(f, "--- Substitutions ---\n");
1541 print_context_intern_subst(f, ctx);
1542 fprintf(f, "\n--- Internalization ---\n");
1543 print_context_intern_mapping(f, ctx);
1544 }
1545
1546
1547 /*
1548 * Dump the initial context + the internalization table (optional)
1549 */
dump_the_context(context_t * context,smt_benchmark_t * bench,char * filename)1550 static void dump_the_context(context_t *context, smt_benchmark_t *bench, char *filename) {
1551 FILE *dump;
1552 bv_solver_t *bv;
1553
1554 dump = fopen(filename, "w");
1555 if (dump == NULL) return;
1556
1557 print_benchmark(dump, bench);
1558 if (dump_internalization) {
1559 dump_internalization_table(dump, context);
1560 }
1561
1562 if (context_has_egraph(context)) {
1563 fprintf(dump, "\n==== TYPE TABLE ====\n");
1564 print_type_table(dump, __yices_globals.types);
1565 fprintf(dump, "\n==== EGRAPH TERMS ====\n");
1566 print_egraph_terms(dump, context->egraph);
1567 // fprintf(dump, "\n==== EGRAPH CLASSES ====\n");
1568 // print_egraph_root_classes_details(dump, context->egraph);
1569 fprintf(dump, "\n==== EGRAPH ATOMS ====\n");
1570 print_egraph_atoms(dump, context->egraph);
1571
1572 }
1573
1574 if (context_has_idl_solver(context)) {
1575 fprintf(dump, "\n==== IDL ATOMS ====\n");
1576 print_idl_atoms(dump, context->arith_solver);
1577 } else if (context_has_rdl_solver(context)) {
1578 fprintf(dump, "\n==== RDL ATOMS ====\n");
1579 } else if (context_has_simplex_solver(context)) {
1580 fprintf(dump, "\n==== SIMPLEX VARIABLES ====\n");
1581 print_simplex_vars(dump, context->arith_solver);
1582 fprintf(dump, "\n==== SIMPLEX ATOMS ====\n");
1583 print_simplex_atoms(dump, context->arith_solver);
1584 fprintf(dump, "\n==== MATRIX ====\n");
1585 print_simplex_matrix(dump, context->arith_solver);
1586 fprintf(dump, "\n==== BOUNDS ====\n");
1587 print_simplex_bounds(dump, context->arith_solver);
1588 fprintf(dump, "\n==== ASSIGNMENT ====\n");
1589 print_simplex_assignment(dump, context->arith_solver);
1590 }
1591
1592 if (context_has_bv_solver(context)) {
1593 bv = context->bv_solver;
1594 fprintf(dump, "\n==== BVSOLVER PARTITION ====\n");
1595 print_bv_solver_partition(dump, bv);
1596 fprintf(dump, "\n==== BVSOLVER TERMS ====\n");
1597 print_bv_solver_vars(dump, bv);
1598 fprintf(dump, "\n==== BVSOLVER ATOMS ====\n");
1599 print_bv_solver_atoms(dump, bv);
1600 }
1601
1602 fprintf(dump, "\n==== CLAUSES ====\n");
1603 print_clauses(dump, context->core);
1604 fprintf(dump, "\n==== BOOLEAN ASSIGNMENT ====\n");
1605 print_boolean_assignment(dump, context->core);
1606 fprintf(dump, "\n");
1607
1608 fclose(dump);
1609 }
1610
1611
1612
1613 /*
1614 * TIMEOUT/INTERRUPTS
1615 */
1616
1617 static const char signum_msg[24] = "\nInterrupted by signal ";
1618 static char signum_buffer[100];
1619
1620 /*
1621 * Write signal number to file 2 (assumed to be stderr): we can't use
1622 * fprintf because it's not safe in a signal handler.
1623 */
write_signum(int signum)1624 static void write_signum(int signum) {
1625 ssize_t w;
1626 uint32_t i, n;
1627
1628 memcpy(signum_buffer, signum_msg, sizeof(signum_msg));
1629
1630 // force signum to be at most two digits
1631 signum = signum % 100;
1632 n = sizeof(signum_msg);
1633 if (signum > 10) {
1634 signum_buffer[n] = (char)('0' + signum/10);
1635 signum_buffer[n + 1] = (char)('0' + signum % 10);
1636 signum_buffer[n + 2] = '\n';
1637 n += 3;
1638 } else {
1639 signum_buffer[n] = (char)('0' + signum);
1640 signum_buffer[n + 1] = '\n';
1641 n += 2;
1642 }
1643
1644 // write to file 2
1645 i = 0;
1646 do {
1647 do {
1648 w = write(2, signum_buffer + i, n);
1649 } while (w < 0 && errno == EAGAIN);
1650 if (w < 0) break; // write error, we can't do much about it.
1651 i += (uint32_t) w;
1652 n -= (uint32_t) w;
1653 } while (n > 0);
1654 }
1655
1656 /*
1657 * Signal handler: call print_results then exit
1658 */
handler(int signum)1659 static void handler(int signum) {
1660 write_signum(signum);
1661 if (context_exists) {
1662 // TODO: Fix this.
1663 // dump_the_context and print_result can deadlock
1664 if (dump_context || dump_internalization) {
1665 dump_the_context(&context, &bench, "yices_exit.dmp");
1666 }
1667 print_results();
1668 }
1669 _exit(YICES_EXIT_INTERRUPTED);
1670 }
1671
1672
1673 /*
1674 * Set the signal handler: to print statistics on
1675 * SIGINT, SIGABRT, SIGXCPU
1676 */
init_handler(void)1677 static void init_handler(void) {
1678 signal(SIGINT, handler);
1679 signal(SIGABRT, handler);
1680 #ifndef MINGW
1681 signal(SIGXCPU, handler);
1682 #endif
1683 }
1684
1685
1686 /*
1687 * Mask the signals
1688 */
clear_handler(void)1689 static void clear_handler(void) {
1690 signal(SIGINT, SIG_IGN);
1691 signal(SIGABRT, SIG_IGN);
1692 #ifndef MINGW
1693 signal(SIGXCPU, SIG_IGN);
1694 #endif
1695 }
1696
1697
1698 /*
1699 * Timeout handler: p = pointer to the context
1700 */
timeout_handler(void * p)1701 static void timeout_handler(void *p) {
1702 context_t *ctx;
1703
1704 ctx = p;
1705 stop_search(ctx->core);
1706 }
1707
1708
1709
1710 /*
1711 * Temporary test. Check whether one of the input assertion is reduced
1712 * to false by simplification. This is checked independent of the
1713 * logic label.
1714 */
benchmark_reduced_to_false(smt_benchmark_t * bench)1715 static bool benchmark_reduced_to_false(smt_benchmark_t *bench) {
1716 uint32_t i, n;
1717 term_t f;
1718
1719 n = bench->nformulas;
1720 for (i=0; i<n; i++) {
1721 f = bench->formulas[i];
1722 assert(is_boolean_term(__yices_globals.terms, f));
1723 if (f == false_term) {
1724 return true;
1725 }
1726 }
1727
1728 return false;
1729 }
1730
1731
1732 /*
1733 * MAIN SOLVER FUNCTION
1734 * - parse input file (assumed to be in SMT-LIB format)
1735 * - solve benchmark
1736 * - return an exit code (defined in yices_exit_codes.h)
1737 */
process_benchmark(char * filename)1738 static int process_benchmark(char *filename) {
1739 param_t *search_options;
1740 model_t *model;
1741 int32_t code;
1742 double mem_used;
1743 smt_logic_t logic;
1744 context_arch_t arch;
1745 bool need_icheck; // true if simplex needs integer check
1746
1747 print_yices_header(stdout);
1748
1749 if (filename != NULL) {
1750 // Read from the given file
1751 if (init_smt_file_lexer(&lexer, filename) < 0) {
1752 perror(filename);
1753 return YICES_EXIT_FILE_NOT_FOUND;
1754 }
1755 } else {
1756 // read from stdin
1757 init_smt_stdin_lexer(&lexer);
1758 }
1759
1760 context_exists = false;
1761 init_handler();
1762
1763 /*
1764 * Parse and build the formula
1765 */
1766 yices_init();
1767 init_smt_tstack(&stack);
1768 init_parser(&parser, &lexer, &stack);
1769 init_benchmark(&bench);
1770 code = parse_smt_benchmark(&parser, &bench);
1771 if (code == 0) {
1772 construction_time = get_cpu_time();
1773 mem_used = mem_size() / (1024 * 1024);
1774 print_benchmark(stdout, &bench);
1775 printf("Construction time: %.4f s\n", construction_time);
1776 printf("Memory used: %.2f MB\n", mem_used);
1777 fflush(stdout);
1778 }
1779
1780 delete_parser(&parser);
1781 close_lexer(&lexer);
1782 delete_tstack(&stack);
1783
1784 if (code < 0) {
1785 code = YICES_EXIT_SYNTAX_ERROR;
1786 goto cleanup_benchmark;
1787 }
1788
1789
1790 /*
1791 * Check whether the simplifier solved it
1792 */
1793 if (benchmark_reduced_to_false(&bench)) {
1794 printf("\nReduced to false\n\nunsat\n");
1795 fflush(stdout);
1796 code = YICES_EXIT_SUCCESS;
1797 goto cleanup_benchmark;
1798 }
1799
1800 /*
1801 * Select architecture based on the benchmark logic and
1802 * command-line options
1803 */
1804 need_icheck = false;
1805 arch = CTX_ARCH_NOSOLVERS; // otherwise GCC gives a warning
1806
1807 if (bench.logic_name != NULL) {
1808 logic = smt_logic_code(bench.logic_name);
1809 switch (logic) {
1810 case QF_ALIA:
1811 case QF_AUFLIA:
1812 /*
1813 * Arrays + uf + simplex
1814 */
1815 arch = CTX_ARCH_EGFUNSPLX;
1816 break;
1817
1818 case QF_AX:
1819 /*
1820 * Egraph + array solver
1821 */
1822 arch = CTX_ARCH_EGFUN;
1823 break;
1824
1825 case QF_IDL:
1826 /*
1827 * Default for QF_IDL: automatic
1828 * unless --simplex or --floyd-warshall was given on the command line
1829 */
1830 switch (arith_solver) {
1831 case ARITH_SOLVER_AUTOMATIC:
1832 arch = CTX_ARCH_AUTO_IDL;
1833 break;
1834 case ARITH_SOLVER_SIMPLEX:
1835 arch = CTX_ARCH_SPLX;
1836 break;
1837 case ARITH_SOLVER_FLOYD_WARSHALL:
1838 arch = CTX_ARCH_IFW;
1839 break;
1840 }
1841 break;
1842
1843 case QF_RDL:
1844 /*
1845 * Default for QF_RDL: automatic
1846 * unless --simplex or --floyd-warshall was given on the command line
1847 */
1848 switch (arith_solver) {
1849 case ARITH_SOLVER_AUTOMATIC:
1850 arch = CTX_ARCH_AUTO_RDL;
1851 break;
1852 case ARITH_SOLVER_SIMPLEX:
1853 arch = CTX_ARCH_SPLX;
1854 break;
1855 case ARITH_SOLVER_FLOYD_WARSHALL:
1856 arch = CTX_ARCH_RFW;
1857 break;
1858 }
1859 break;
1860
1861 case QF_UF:
1862 /*
1863 * Egraph only
1864 */
1865 arch = CTX_ARCH_EG;
1866 break;
1867
1868
1869 case QF_LRA:
1870 /*
1871 * SIMPLEX only
1872 */
1873 arch = CTX_ARCH_SPLX;
1874 break;
1875
1876 case QF_LIA:
1877 /*
1878 * SIMPLEX only, activate periodic integer checks
1879 */
1880 need_icheck = true;
1881 arch = CTX_ARCH_SPLX;
1882 break;
1883
1884 case QF_UFIDL:
1885 /*
1886 * Some SMT-LIB benchmarks labeled as QF_UFIDL are actually
1887 * pure IDL so we allow IDL floyd-warshall here.
1888 * The default is EGRAPH + SIMPLEX.
1889 */
1890 switch (arith_solver) {
1891 case ARITH_SOLVER_AUTOMATIC:
1892 case ARITH_SOLVER_SIMPLEX:
1893 arch = CTX_ARCH_EGSPLX;
1894 break;
1895 case ARITH_SOLVER_FLOYD_WARSHALL:
1896 arch = CTX_ARCH_IFW;
1897 break;
1898 }
1899 break;
1900
1901 case QF_UFLRA:
1902 /*
1903 * EGRAPH + SIMPLEX
1904 */
1905 arch = CTX_ARCH_EGSPLX;
1906 break;
1907
1908 case QF_UFLIA:
1909 case QF_UFLIRA:
1910 /*
1911 * EGRAPH + SIMPLEX, activate periodic integer checks
1912 */
1913 need_icheck = true;
1914 arch = CTX_ARCH_EGSPLX;
1915 break;
1916
1917 case QF_ABV:
1918 case QF_AUFBV:
1919 /*
1920 * EGRAPH + BITVECTOR + ARRAY solver
1921 */
1922 arch = CTX_ARCH_EGFUNBV;
1923 break;
1924
1925 case QF_UFBV:
1926 /*
1927 * EGRAPH + BITVECTOR solver
1928 */
1929 arch = CTX_ARCH_EGBV;
1930 break;
1931
1932 case QF_BV:
1933 /*
1934 * Pure bit-vector problem
1935 */
1936 arch = CTX_ARCH_BV;
1937 // arch = CTX_ARCH_EGBV;
1938 break;
1939
1940 default:
1941 /*
1942 * Not supported or unknown logic
1943 */
1944 print_internalization_code(LOGIC_NOT_SUPPORTED);
1945 code = YICES_EXIT_ERROR;
1946 goto cleanup_benchmark;
1947 }
1948
1949 } else {
1950 fprintf(stderr, "No logic specified\n");
1951 code = YICES_EXIT_ERROR;
1952 goto cleanup_benchmark;
1953 }
1954
1955
1956
1957 /*
1958 * Initialize the context and set options
1959 */
1960 init_context(&context, __yices_globals.terms, logic, CTX_MODE_ONECHECK, arch, false);
1961 if (var_elim) {
1962 enable_variable_elimination(&context);
1963 }
1964 if (flatten_or) {
1965 enable_diseq_and_or_flattening(&context);
1966 }
1967 if (learn_eq && arch == CTX_ARCH_EG) {
1968 enable_eq_abstraction(&context);
1969 }
1970 if (break_sym && arch == CTX_ARCH_EG) {
1971 enable_symmetry_breaking(&context);
1972 }
1973 if (arith_elim) {
1974 enable_arith_elimination(&context);
1975 }
1976 if (bvarith_elim) {
1977 enable_bvarith_elimination(&context);
1978 }
1979 if (keep_ite) {
1980 enable_keep_ite(&context);
1981 }
1982 if (eager_lemmas) {
1983 enable_splx_eager_lemmas(&context);
1984 }
1985 if (need_icheck) {
1986 enable_splx_periodic_icheck(&context);
1987 }
1988 if (dump_context) {
1989 context.options |= DUMP_OPTION_MASK;
1990 }
1991 init_trace (&tracer);
1992 set_trace_vlevel(&tracer, 3);
1993 context_set_trace(&context, &tracer);
1994 context_exists = true;
1995
1996 /*
1997 * Assert then internalize
1998 */
1999 code = assert_formulas(&context, bench.nformulas, bench.formulas);
2000 print_internalization_code(code);
2001 if (code < 0) {
2002 print_results();
2003 code = YICES_EXIT_ERROR;
2004 goto cleanup_context;
2005 }
2006
2007 if (dump_context || dump_internalization) {
2008 dump_the_context(&context, &bench, "yices_start.dmp");
2009 }
2010
2011 if (code != TRIVIALLY_UNSAT) {
2012 /*
2013 * Search
2014 */
2015 if (use_default_params) {
2016 search_options = NULL;
2017 } else {
2018 search_options = ¶ms;
2019 }
2020
2021 print_options(stdout, &context);
2022 print_presearch_stats();
2023 start_search_time = get_cpu_time();
2024
2025 if (timeout > 0) {
2026 init_timeout();
2027 start_timeout(timeout, timeout_handler, &context);
2028 }
2029 code = check_context(&context, search_options);
2030 clear_handler();
2031
2032 if (timeout > 0) {
2033 clear_timeout();
2034 delete_timeout();
2035 }
2036
2037 print_results();
2038
2039 if (show_model && (code == STATUS_SAT || code == STATUS_UNKNOWN)) {
2040 model = new_model();
2041 context_build_model(model, &context);
2042 printf("\nMODEL\n");
2043 model_print(stdout, model);
2044 printf("----\n");
2045
2046 // FOR TESTING
2047 #if TEST_EVALUATOR
2048 test_evaluator(stdout, model);
2049 #endif
2050 check_model(stdout, &bench, model);
2051 free_model(model);
2052 }
2053
2054 }
2055
2056 if (dump_context || dump_internalization) {
2057 dump_the_context(&context, &bench, "yices_end.dmp");
2058 }
2059
2060 code = YICES_EXIT_SUCCESS;
2061
2062
2063 /*
2064 * Cleanup and return code
2065 *
2066 * To cleanup after an error: jump to cleanup_context if the error
2067 * is detected after the context is initialized or to cleanup_benchmark
2068 * if the error is detected before the context is initialized.
2069 */
2070 cleanup_context:
2071 delete_context(&context);
2072 delete_trace(&tracer);
2073 cleanup_benchmark:
2074 delete_benchmark(&bench);
2075 yices_exit();
2076
2077 return code;
2078 }
2079
2080
2081
main(int argc,char * argv[])2082 int main(int argc, char *argv[]) {
2083 parse_command_line(argc, argv);
2084 return process_benchmark(filename);
2085 }
2086
2087