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(&params);
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 = &params;
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