Integrate central equality engine approach into theory engine, add option and regress...
[cvc5.git] / src / smt / set_defaults.cpp
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Andres Noetzli, Haniel Barbosa
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8 * in the top-level source directory and their institutional affiliations.
9 * All rights reserved. See the file COPYING in the top-level source
10 * directory for licensing information.
11 * ****************************************************************************
12 *
13 * Implementation of setting default options.
14 */
15
16 #include "smt/set_defaults.h"
17
18 #include <sstream>
19
20 #include "base/output.h"
21 #include "options/arith_options.h"
22 #include "options/arrays_options.h"
23 #include "options/base_options.h"
24 #include "options/booleans_options.h"
25 #include "options/bv_options.h"
26 #include "options/datatypes_options.h"
27 #include "options/decision_options.h"
28 #include "options/language.h"
29 #include "options/main_options.h"
30 #include "options/open_ostream.h"
31 #include "options/option_exception.h"
32 #include "options/printer_options.h"
33 #include "options/proof_options.h"
34 #include "options/prop_options.h"
35 #include "options/quantifiers_options.h"
36 #include "options/sep_options.h"
37 #include "options/set_language.h"
38 #include "options/smt_options.h"
39 #include "options/strings_options.h"
40 #include "options/theory_options.h"
41 #include "options/uf_options.h"
42 #include "smt/logic_exception.h"
43 #include "theory/theory.h"
44
45 using namespace cvc5::theory;
46
47 namespace cvc5 {
48 namespace smt {
49
50 void setDefaults(LogicInfo& logic, bool isInternalSubsolver)
51 {
52 Options& opts = Options::current();
53 // implied options
54 if (options::debugCheckModels())
55 {
56 opts.smt.checkModels = true;
57 }
58 if (options::checkModels() || options::dumpModels())
59 {
60 opts.smt.produceModels = true;
61 }
62 if (options::checkModels())
63 {
64 opts.smt.produceAssignments = true;
65 }
66 // unsat cores and proofs shenanigans
67 if (options::dumpUnsatCoresFull())
68 {
69 opts.driver.dumpUnsatCores = true;
70 }
71 if (options::checkUnsatCores() || options::dumpUnsatCores()
72 || options::unsatAssumptions() || options::minimalUnsatCores()
73 || options::unsatCoresMode() != options::UnsatCoresMode::OFF)
74 {
75 opts.smt.unsatCores = true;
76 }
77 if (options::unsatCores()
78 && options::unsatCoresMode() == options::UnsatCoresMode::OFF)
79 {
80 if (opts.smt.unsatCoresModeWasSetByUser)
81 {
82 Notice()
83 << "Overriding OFF unsat-core mode since cores were requested.\n";
84 }
85 opts.smt.unsatCoresMode = options::UnsatCoresMode::ASSUMPTIONS;
86 }
87
88 if (options::checkProofs() || options::dumpProofs())
89 {
90 opts.smt.produceProofs = true;
91 }
92
93 if (options::produceProofs()
94 && options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF)
95 {
96 if (opts.smt.unsatCoresModeWasSetByUser)
97 {
98 Notice() << "Forcing full-proof mode for unsat cores mode since proofs "
99 "were requested.\n";
100 }
101 // enable unsat cores, because they are available as a consequence of proofs
102 opts.smt.unsatCores = true;
103 opts.smt.unsatCoresMode = options::UnsatCoresMode::FULL_PROOF;
104 }
105
106 // set proofs on if not yet set
107 if (options::unsatCores() && !options::produceProofs())
108 {
109 if (opts.smt.produceProofsWasSetByUser)
110 {
111 Notice()
112 << "Forcing proof production since new unsat cores were requested.\n";
113 }
114 opts.smt.produceProofs = true;
115 }
116
117 // if unsat cores are disabled, then unsat cores mode should be OFF
118 Assert(options::unsatCores()
119 == (options::unsatCoresMode() != options::UnsatCoresMode::OFF));
120
121 if (opts.bv.bitvectorAigSimplificationsWasSetByUser)
122 {
123 Notice() << "SmtEngine: setting bitvectorAig" << std::endl;
124 opts.bv.bitvectorAig = true;
125 }
126 if (opts.bv.bitvectorAlgebraicBudgetWasSetByUser)
127 {
128 Notice() << "SmtEngine: setting bitvectorAlgebraicSolver" << std::endl;
129 opts.bv.bitvectorAlgebraicSolver = true;
130 }
131
132 bool isSygus = language::isInputLangSygus(options::inputLanguage());
133 bool usesSygus = isSygus;
134
135 if (options::bitblastMode() == options::BitblastMode::EAGER)
136 {
137 if (options::produceModels()
138 && (logic.isTheoryEnabled(THEORY_ARRAYS)
139 || logic.isTheoryEnabled(THEORY_UF)))
140 {
141 if (opts.bv.bitblastModeWasSetByUser
142 || opts.smt.produceModelsWasSetByUser)
143 {
144 throw OptionException(std::string(
145 "Eager bit-blasting currently does not support model generation "
146 "for the combination of bit-vectors with arrays or uinterpreted "
147 "functions. Try --bitblast=lazy"));
148 }
149 Notice() << "SmtEngine: setting bit-blast mode to lazy to support model"
150 << "generation" << std::endl;
151 opts.bv.bitblastMode = options::BitblastMode::LAZY;
152 }
153 else if (!options::incrementalSolving())
154 {
155 opts.smt.ackermann = true;
156 }
157
158 if (options::incrementalSolving() && !logic.isPure(THEORY_BV))
159 {
160 throw OptionException(
161 "Incremental eager bit-blasting is currently "
162 "only supported for QF_BV. Try --bitblast=lazy.");
163 }
164 }
165
166 /* Disable bit-level propagation by default for the BITBLAST solver. */
167 if (options::bvSolver() == options::BVSolver::BITBLAST)
168 {
169 opts.bv.bitvectorPropagate = false;
170 }
171
172 if (options::solveIntAsBV() > 0)
173 {
174 // not compatible with incremental
175 if (options::incrementalSolving())
176 {
177 throw OptionException(
178 "solving integers as bitvectors is currently not supported "
179 "when solving incrementally.");
180 }
181 // Int to BV currently always eliminates arithmetic completely (or otherwise
182 // fails). Thus, it is safe to eliminate arithmetic. Also, bit-vectors
183 // are required.
184 logic = logic.getUnlockedCopy();
185 logic.enableTheory(THEORY_BV);
186 logic.disableTheory(THEORY_ARITH);
187 logic.lock();
188 }
189
190 if (options::solveBVAsInt() != options::SolveBVAsIntMode::OFF)
191 {
192 if (options::boolToBitvector() != options::BoolToBVMode::OFF)
193 {
194 throw OptionException(
195 "solving bitvectors as integers is incompatible with --bool-to-bv.");
196 }
197 if (options::BVAndIntegerGranularity() > 8)
198 {
199 /**
200 * The granularity sets the size of the ITE in each element
201 * of the sum that is generated for bitwise operators.
202 * The size of the ITE is 2^{2*granularity}.
203 * Since we don't want to introduce ITEs with unbounded size,
204 * we bound the granularity.
205 */
206 throw OptionException("solve-bv-as-int accepts values from 0 to 8.");
207 }
208 if (logic.isTheoryEnabled(THEORY_BV))
209 {
210 logic = logic.getUnlockedCopy();
211 logic.enableTheory(THEORY_ARITH);
212 logic.arithNonLinear();
213 logic.lock();
214 }
215 }
216
217 // set options about ackermannization
218 if (options::ackermann() && options::produceModels()
219 && (logic.isTheoryEnabled(THEORY_ARRAYS)
220 || logic.isTheoryEnabled(THEORY_UF)))
221 {
222 if (opts.smt.produceModelsWasSetByUser)
223 {
224 throw OptionException(std::string(
225 "Ackermannization currently does not support model generation."));
226 }
227 Notice() << "SmtEngine: turn off ackermannization to support model"
228 << "generation" << std::endl;
229 opts.smt.ackermann = false;
230 }
231
232 if (options::ackermann())
233 {
234 if (options::incrementalSolving())
235 {
236 throw OptionException(
237 "Incremental Ackermannization is currently not supported.");
238 }
239
240 if (logic.isQuantified())
241 {
242 throw LogicException("Cannot use Ackermannization on quantified formula");
243 }
244
245 if (logic.isTheoryEnabled(THEORY_UF))
246 {
247 logic = logic.getUnlockedCopy();
248 logic.disableTheory(THEORY_UF);
249 logic.lock();
250 }
251 if (logic.isTheoryEnabled(THEORY_ARRAYS))
252 {
253 logic = logic.getUnlockedCopy();
254 logic.disableTheory(THEORY_ARRAYS);
255 logic.lock();
256 }
257 }
258
259 // --ite-simp is an experimental option designed for QF_LIA/nec. This
260 // technique is experimental. This benchmark set also requires removing ITEs
261 // during preprocessing, before repeating simplification. Hence, we enable
262 // this by default.
263 if (options::doITESimp())
264 {
265 if (!opts.smt.earlyIteRemovalWasSetByUser)
266 {
267 opts.smt.earlyIteRemoval = true;
268 }
269 }
270
271 // Set default options associated with strings-exp. We also set these options
272 // if we are using eager string preprocessing, which may introduce quantified
273 // formulas at preprocess time.
274 //
275 // We don't want to set this option when we are in logics that contain ALL.
276 if (!logic.hasEverything() && logic.isTheoryEnabled(THEORY_STRINGS))
277 {
278 // If the user explicitly set a logic that includes strings, but is not
279 // the generic "ALL" logic, then enable stringsExp.
280 opts.strings.stringExp = true;
281 Trace("smt") << "Turning stringExp on since logic does not have everything "
282 "and string theory is enabled\n";
283 }
284 if (options::stringExp() || !options::stringLazyPreproc())
285 {
286 // We require quantifiers since extended functions reduce using them.
287 if (!logic.isQuantified())
288 {
289 logic = logic.getUnlockedCopy();
290 logic.enableQuantifiers();
291 logic.lock();
292 Trace("smt") << "turning on quantifier logic, for strings-exp"
293 << std::endl;
294 }
295 // Note we allow E-matching by default to support combinations of sequences
296 // and quantifiers. We also do not enable fmfBound here, which would
297 // enable bounded integer instantiation for *all* quantifiers. Instead,
298 // the bounded integers module will always process internally generated
299 // quantifiers (those marked with InternalQuantAttribute).
300 }
301 // whether we must disable proofs
302 bool disableProofs = false;
303 if (options::globalNegate())
304 {
305 // When global negate answers "unsat", it is not due to showing a set of
306 // formulas is unsat. Thus, proofs do not apply.
307 disableProofs = true;
308 }
309
310 // new unsat core specific restrictions for proofs
311 if (options::unsatCores()
312 && options::unsatCoresMode() != options::UnsatCoresMode::FULL_PROOF)
313 {
314 // no fine-graininess
315 if (!opts.proof.proofGranularityModeWasSetByUser)
316 {
317 opts.proof.proofGranularityMode = options::ProofGranularityMode::OFF;
318 }
319 }
320
321 if (options::arraysExp())
322 {
323 if (!logic.isQuantified())
324 {
325 logic = logic.getUnlockedCopy();
326 logic.enableQuantifiers();
327 logic.lock();
328 }
329 // Allows to answer sat more often by default.
330 if (!opts.quantifiers.fmfBoundWasSetByUser)
331 {
332 opts.quantifiers.fmfBound = true;
333 Trace("smt") << "turning on fmf-bound, for arrays-exp" << std::endl;
334 }
335 }
336
337 // sygus inference may require datatypes
338 if (!isInternalSubsolver)
339 {
340 if (options::produceAbducts()
341 || options::produceInterpols() != options::ProduceInterpols::NONE
342 || options::sygusInference() || options::sygusRewSynthInput())
343 {
344 // since we are trying to recast as sygus, we assume the input is sygus
345 isSygus = true;
346 usesSygus = true;
347 }
348 else if (options::sygusInst())
349 {
350 // sygus instantiation uses sygus, but it is not a sygus problem
351 usesSygus = true;
352 }
353 }
354
355 // We now know whether the input uses sygus. Update the logic to incorporate
356 // the theories we need internally for handling sygus problems.
357 if (usesSygus)
358 {
359 logic = logic.getUnlockedCopy();
360 logic.enableSygus();
361 logic.lock();
362 if (isSygus)
363 {
364 // When sygus answers "unsat", it is not due to showing a set of
365 // formulas is unsat in the standard way. Thus, proofs do not apply.
366 disableProofs = true;
367 }
368 }
369
370 // if we requiring disabling proofs, disable them now
371 if (disableProofs && options::produceProofs())
372 {
373 opts.smt.unsatCores = false;
374 opts.smt.unsatCoresMode = options::UnsatCoresMode::OFF;
375 if (options::produceProofs())
376 {
377 Notice() << "SmtEngine: turning off produce-proofs." << std::endl;
378 }
379 opts.smt.produceProofs = false;
380 opts.smt.checkProofs = false;
381 opts.proof.proofEagerChecking = false;
382 }
383
384 // sygus core connective requires unsat cores
385 if (options::sygusCoreConnective())
386 {
387 opts.smt.unsatCores = true;
388 if (options::unsatCoresMode() == options::UnsatCoresMode::OFF)
389 {
390 opts.smt.unsatCoresMode = options::UnsatCoresMode::ASSUMPTIONS;
391 }
392 }
393
394 if ((options::checkModels() || options::checkSynthSol()
395 || options::produceAbducts()
396 || options::produceInterpols() != options::ProduceInterpols::NONE
397 || options::modelCoresMode() != options::ModelCoresMode::NONE
398 || options::blockModelsMode() != options::BlockModelsMode::NONE
399 || options::produceProofs())
400 && !options::produceAssertions())
401 {
402 Notice() << "SmtEngine: turning on produce-assertions to support "
403 << "option requiring assertions." << std::endl;
404 opts.smt.produceAssertions = true;
405 }
406
407 if (options::bvAssertInput() && options::produceProofs())
408 {
409 Notice() << "Disabling bv-assert-input since it is incompatible with proofs."
410 << std::endl;
411 opts.bv.bvAssertInput = false;
412 }
413
414 // whether we want to force safe unsat cores, i.e., if we are in the default
415 // ASSUMPTIONS mode, since other ones are experimental
416 bool safeUnsatCores =
417 options::unsatCoresMode() == options::UnsatCoresMode::ASSUMPTIONS;
418
419 // Disable options incompatible with incremental solving, unsat cores or
420 // output an error if enabled explicitly. It is also currently incompatible
421 // with arithmetic, force the option off.
422 if (options::incrementalSolving() || safeUnsatCores)
423 {
424 if (options::unconstrainedSimp())
425 {
426 if (opts.smt.unconstrainedSimpWasSetByUser)
427 {
428 throw OptionException(
429 "unconstrained simplification not supported with old unsat "
430 "cores/incremental solving");
431 }
432 Notice() << "SmtEngine: turning off unconstrained simplification to "
433 "support old unsat cores/incremental solving"
434 << std::endl;
435 opts.smt.unconstrainedSimp = false;
436 }
437 }
438 else
439 {
440 // Turn on unconstrained simplification for QF_AUFBV
441 if (!opts.smt.unconstrainedSimpWasSetByUser)
442 {
443 bool uncSimp = !logic.isQuantified() && !options::produceModels()
444 && !options::produceAssignments()
445 && !options::checkModels()
446 && logic.isTheoryEnabled(THEORY_ARRAYS)
447 && logic.isTheoryEnabled(THEORY_BV)
448 && !logic.isTheoryEnabled(THEORY_ARITH);
449 Trace("smt") << "setting unconstrained simplification to " << uncSimp
450 << std::endl;
451 opts.smt.unconstrainedSimp = uncSimp;
452 }
453 }
454
455 if (options::incrementalSolving())
456 {
457 if (options::sygusInference())
458 {
459 if (opts.quantifiers.sygusInferenceWasSetByUser)
460 {
461 throw OptionException(
462 "sygus inference not supported with incremental solving");
463 }
464 Notice() << "SmtEngine: turning off sygus inference to support "
465 "incremental solving"
466 << std::endl;
467 opts.quantifiers.sygusInference = false;
468 }
469 }
470
471 if (options::solveBVAsInt() != options::SolveBVAsIntMode::OFF)
472 {
473 /**
474 * Operations on 1 bits are better handled as Boolean operations
475 * than as integer operations.
476 * Therefore, we enable bv-to-bool, which runs before
477 * the translation to integers.
478 */
479 opts.bv.bitvectorToBool = true;
480 }
481
482 // Disable options incompatible with unsat cores or output an error if enabled
483 // explicitly
484 if (safeUnsatCores)
485 {
486 if (options::simplificationMode() != options::SimplificationMode::NONE)
487 {
488 if (opts.smt.simplificationModeWasSetByUser)
489 {
490 throw OptionException(
491 "simplification not supported with old unsat cores");
492 }
493 Notice() << "SmtEngine: turning off simplification to support unsat "
494 "cores"
495 << std::endl;
496 opts.smt.simplificationMode = options::SimplificationMode::NONE;
497 }
498
499 if (options::learnedRewrite())
500 {
501 if (opts.smt.learnedRewriteWasSetByUser)
502 {
503 throw OptionException(
504 "learned rewrites not supported with unsat cores");
505 }
506 Notice() << "SmtEngine: turning off learned rewrites to support "
507 "unsat cores\n";
508 opts.smt.learnedRewrite = false;
509 }
510
511 if (options::pbRewrites())
512 {
513 if (opts.arith.pbRewritesWasSetByUser)
514 {
515 throw OptionException(
516 "pseudoboolean rewrites not supported with unsat cores");
517 }
518 Notice() << "SmtEngine: turning off pseudoboolean rewrites to support "
519 "unsat cores\n";
520 opts.arith.pbRewrites = false;
521 }
522
523 if (options::sortInference())
524 {
525 if (opts.smt.sortInferenceWasSetByUser)
526 {
527 throw OptionException("sort inference not supported with unsat cores");
528 }
529 Notice() << "SmtEngine: turning off sort inference to support unsat "
530 "cores\n";
531 opts.smt.sortInference = false;
532 }
533
534 if (options::preSkolemQuant())
535 {
536 if (opts.quantifiers.preSkolemQuantWasSetByUser)
537 {
538 throw OptionException(
539 "pre-skolemization not supported with unsat cores");
540 }
541 Notice() << "SmtEngine: turning off pre-skolemization to support "
542 "unsat cores\n";
543 opts.quantifiers.preSkolemQuant = false;
544 }
545
546 if (options::bitvectorToBool())
547 {
548 if (opts.bv.bitvectorToBoolWasSetByUser)
549 {
550 throw OptionException("bv-to-bool not supported with unsat cores");
551 }
552 Notice() << "SmtEngine: turning off bitvector-to-bool to support "
553 "unsat cores\n";
554 opts.bv.bitvectorToBool = false;
555 }
556
557 if (options::boolToBitvector() != options::BoolToBVMode::OFF)
558 {
559 if (opts.bv.boolToBitvectorWasSetByUser)
560 {
561 throw OptionException(
562 "bool-to-bv != off not supported with unsat cores");
563 }
564 Notice() << "SmtEngine: turning off bool-to-bv to support unsat cores\n";
565 opts.bv.boolToBitvector = options::BoolToBVMode::OFF;
566 }
567
568 if (options::bvIntroducePow2())
569 {
570 if (opts.bv.bvIntroducePow2WasSetByUser)
571 {
572 throw OptionException("bv-intro-pow2 not supported with unsat cores");
573 }
574 Notice() << "SmtEngine: turning off bv-intro-pow2 to support unsat cores";
575 opts.bv.bvIntroducePow2 = false;
576 }
577
578 if (options::repeatSimp())
579 {
580 if (opts.smt.repeatSimpWasSetByUser)
581 {
582 throw OptionException("repeat-simp not supported with unsat cores");
583 }
584 Notice() << "SmtEngine: turning off repeat-simp to support unsat cores\n";
585 opts.smt.repeatSimp = false;
586 }
587
588 if (options::globalNegate())
589 {
590 if (opts.quantifiers.globalNegateWasSetByUser)
591 {
592 throw OptionException("global-negate not supported with unsat cores");
593 }
594 Notice() << "SmtEngine: turning off global-negate to support unsat "
595 "cores\n";
596 opts.quantifiers.globalNegate = false;
597 }
598
599 if (options::bitvectorAig())
600 {
601 throw OptionException("bitblast-aig not supported with unsat cores");
602 }
603
604 if (options::doITESimp())
605 {
606 throw OptionException("ITE simp not supported with unsat cores");
607 }
608 }
609 else
610 {
611 // by default, nonclausal simplification is off for QF_SAT
612 if (!opts.smt.simplificationModeWasSetByUser)
613 {
614 bool qf_sat = logic.isPure(THEORY_BOOL) && !logic.isQuantified();
615 Trace("smt") << "setting simplification mode to <"
616 << logic.getLogicString() << "> " << (!qf_sat) << std::endl;
617 // simplification=none works better for SMT LIB benchmarks with
618 // quantifiers, not others opts.set(options::simplificationMode, qf_sat ||
619 // quantifiers ? options::SimplificationMode::NONE :
620 // options::SimplificationMode::BATCH);
621 opts.smt.simplificationMode = qf_sat
622 ? options::SimplificationMode::NONE
623 : options::SimplificationMode::BATCH;
624 }
625 }
626
627 if (options::cegqiBv() && logic.isQuantified())
628 {
629 if (options::boolToBitvector() != options::BoolToBVMode::OFF)
630 {
631 if (opts.bv.boolToBitvectorWasSetByUser)
632 {
633 throw OptionException(
634 "bool-to-bv != off not supported with CBQI BV for quantified "
635 "logics");
636 }
637 Notice() << "SmtEngine: turning off bool-to-bitvector to support CBQI BV"
638 << std::endl;
639 opts.bv.boolToBitvector = options::BoolToBVMode::OFF;
640 }
641 }
642
643 // cases where we need produce models
644 if (!options::produceModels()
645 && (options::produceAssignments() || options::sygusRewSynthCheck()
646 || usesSygus))
647 {
648 Notice() << "SmtEngine: turning on produce-models" << std::endl;
649 opts.smt.produceModels = true;
650 }
651
652 /////////////////////////////////////////////////////////////////////////////
653 // Theory widening
654 //
655 // Some theories imply the use of other theories to handle certain operators,
656 // e.g. UF to handle partial functions.
657 /////////////////////////////////////////////////////////////////////////////
658 bool needsUf = false;
659 // strings require LIA, UF; widen the logic
660 if (logic.isTheoryEnabled(THEORY_STRINGS))
661 {
662 LogicInfo log(logic.getUnlockedCopy());
663 // Strings requires arith for length constraints, and also UF
664 needsUf = true;
665 if (!logic.isTheoryEnabled(THEORY_ARITH) || logic.isDifferenceLogic())
666 {
667 Notice()
668 << "Enabling linear integer arithmetic because strings are enabled"
669 << std::endl;
670 log.enableTheory(THEORY_ARITH);
671 log.enableIntegers();
672 log.arithOnlyLinear();
673 }
674 else if (!logic.areIntegersUsed())
675 {
676 Notice() << "Enabling integer arithmetic because strings are enabled"
677 << std::endl;
678 log.enableIntegers();
679 }
680 logic = log;
681 logic.lock();
682 }
683 if (options::bvAbstraction())
684 {
685 // bv abstraction may require UF
686 Notice() << "Enabling UF because bvAbstraction requires it." << std::endl;
687 needsUf = true;
688 }
689 else if (options::preSkolemQuantNested()
690 && opts.quantifiers.preSkolemQuantNestedWasSetByUser)
691 {
692 // if pre-skolem nested is explictly set, then we require UF. If it is
693 // not explicitly set, it is disabled below if UF is not present.
694 Notice() << "Enabling UF because preSkolemQuantNested requires it."
695 << std::endl;
696 needsUf = true;
697 }
698 if (needsUf
699 // Arrays, datatypes and sets permit Boolean terms and thus require UF
700 || logic.isTheoryEnabled(THEORY_ARRAYS)
701 || logic.isTheoryEnabled(THEORY_DATATYPES)
702 || logic.isTheoryEnabled(THEORY_SETS)
703 || logic.isTheoryEnabled(THEORY_BAGS)
704 // Non-linear arithmetic requires UF to deal with division/mod because
705 // their expansion introduces UFs for the division/mod-by-zero case.
706 // If we are eliminating non-linear arithmetic via solve-int-as-bv,
707 // then this is not required, since non-linear arithmetic will be
708 // eliminated altogether (or otherwise fail at preprocessing).
709 || (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
710 && options::solveIntAsBV() == 0)
711 // FP requires UF since there are multiple operators that are partially
712 // defined (see http://smtlib.cs.uiowa.edu/papers/BTRW15.pdf for more
713 // details).
714 || logic.isTheoryEnabled(THEORY_FP))
715 {
716 if (!logic.isTheoryEnabled(THEORY_UF))
717 {
718 LogicInfo log(logic.getUnlockedCopy());
719 if (!needsUf)
720 {
721 Notice() << "Enabling UF because " << logic << " requires it."
722 << std::endl;
723 }
724 log.enableTheory(THEORY_UF);
725 logic = log;
726 logic.lock();
727 }
728 }
729 if (options::arithMLTrick())
730 {
731 if (!logic.areIntegersUsed())
732 {
733 // enable integers
734 LogicInfo log(logic.getUnlockedCopy());
735 Notice() << "Enabling integers because arithMLTrick requires it."
736 << std::endl;
737 log.enableIntegers();
738 logic = log;
739 logic.lock();
740 }
741 }
742 /////////////////////////////////////////////////////////////////////////////
743
744 // Set the options for the theoryOf
745 if (!opts.theory.theoryOfModeWasSetByUser)
746 {
747 if (logic.isSharingEnabled() && !logic.isTheoryEnabled(THEORY_BV)
748 && !logic.isTheoryEnabled(THEORY_STRINGS)
749 && !logic.isTheoryEnabled(THEORY_SETS)
750 && !logic.isTheoryEnabled(THEORY_BAGS)
751 && !(logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
752 && !logic.isQuantified()))
753 {
754 Trace("smt") << "setting theoryof-mode to term-based" << std::endl;
755 opts.theory.theoryOfMode = options::TheoryOfMode::THEORY_OF_TERM_BASED;
756 }
757 }
758
759 // by default, symmetry breaker is on only for non-incremental QF_UF
760 if (!opts.uf.ufSymmetryBreakerWasSetByUser)
761 {
762 bool qf_uf_noinc = logic.isPure(THEORY_UF) && !logic.isQuantified()
763 && !options::incrementalSolving() && !safeUnsatCores;
764 Trace("smt") << "setting uf symmetry breaker to " << qf_uf_noinc
765 << std::endl;
766 opts.uf.ufSymmetryBreaker = qf_uf_noinc;
767 }
768
769 // If in arrays, set the UF handler to arrays
770 if (logic.isTheoryEnabled(THEORY_ARRAYS) && !logic.isHigherOrder()
771 && !options::finiteModelFind()
772 && (!logic.isQuantified()
773 || (logic.isQuantified() && !logic.isTheoryEnabled(THEORY_UF))))
774 {
775 Theory::setUninterpretedSortOwner(THEORY_ARRAYS);
776 }
777 else
778 {
779 Theory::setUninterpretedSortOwner(THEORY_UF);
780 }
781
782 if (!opts.smt.simplifyWithCareEnabledWasSetByUser)
783 {
784 bool qf_aufbv =
785 !logic.isQuantified() && logic.isTheoryEnabled(THEORY_ARRAYS)
786 && logic.isTheoryEnabled(THEORY_UF) && logic.isTheoryEnabled(THEORY_BV);
787
788 bool withCare = qf_aufbv;
789 Trace("smt") << "setting ite simplify with care to " << withCare
790 << std::endl;
791 opts.smt.simplifyWithCareEnabled = withCare;
792 }
793 // Turn off array eager index splitting for QF_AUFLIA
794 if (!opts.arrays.arraysEagerIndexSplittingWasSetByUser)
795 {
796 if (not logic.isQuantified() && logic.isTheoryEnabled(THEORY_ARRAYS)
797 && logic.isTheoryEnabled(THEORY_UF)
798 && logic.isTheoryEnabled(THEORY_ARITH))
799 {
800 Trace("smt") << "setting array eager index splitting to false"
801 << std::endl;
802 opts.arrays.arraysEagerIndexSplitting = false;
803 }
804 }
805 // Turn on multiple-pass non-clausal simplification for QF_AUFBV
806 if (!opts.smt.repeatSimpWasSetByUser)
807 {
808 bool repeatSimp = !logic.isQuantified()
809 && (logic.isTheoryEnabled(THEORY_ARRAYS)
810 && logic.isTheoryEnabled(THEORY_UF)
811 && logic.isTheoryEnabled(THEORY_BV))
812 && !safeUnsatCores;
813 Trace("smt") << "setting repeat simplification to " << repeatSimp
814 << std::endl;
815 opts.smt.repeatSimp = repeatSimp;
816 }
817
818 if (options::boolToBitvector() == options::BoolToBVMode::ALL
819 && !logic.isTheoryEnabled(THEORY_BV))
820 {
821 if (opts.bv.boolToBitvectorWasSetByUser)
822 {
823 throw OptionException(
824 "bool-to-bv=all not supported for non-bitvector logics.");
825 }
826 Notice() << "SmtEngine: turning off bool-to-bv for non-bv logic: "
827 << logic.getLogicString() << std::endl;
828 opts.bv.boolToBitvector = options::BoolToBVMode::OFF;
829 }
830
831 if (!opts.bv.bvEagerExplanationsWasSetByUser
832 && logic.isTheoryEnabled(THEORY_ARRAYS)
833 && logic.isTheoryEnabled(THEORY_BV))
834 {
835 Trace("smt") << "enabling eager bit-vector explanations " << std::endl;
836 opts.bv.bvEagerExplanations = true;
837 }
838
839 // Turn on arith rewrite equalities only for pure arithmetic
840 if (!opts.arith.arithRewriteEqWasSetByUser)
841 {
842 bool arithRewriteEq =
843 logic.isPure(THEORY_ARITH) && logic.isLinear() && !logic.isQuantified();
844 Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq
845 << std::endl;
846 opts.arith.arithRewriteEq = arithRewriteEq;
847 }
848 if (!opts.arith.arithHeuristicPivotsWasSetByUser)
849 {
850 int16_t heuristicPivots = 5;
851 if (logic.isPure(THEORY_ARITH) && !logic.isQuantified())
852 {
853 if (logic.isDifferenceLogic())
854 {
855 heuristicPivots = -1;
856 }
857 else if (!logic.areIntegersUsed())
858 {
859 heuristicPivots = 0;
860 }
861 }
862 Trace("smt") << "setting arithHeuristicPivots " << heuristicPivots
863 << std::endl;
864 opts.arith.arithHeuristicPivots = heuristicPivots;
865 }
866 if (!opts.arith.arithPivotThresholdWasSetByUser)
867 {
868 uint16_t pivotThreshold = 2;
869 if (logic.isPure(THEORY_ARITH) && !logic.isQuantified())
870 {
871 if (logic.isDifferenceLogic())
872 {
873 pivotThreshold = 16;
874 }
875 }
876 Trace("smt") << "setting arith arithPivotThreshold " << pivotThreshold
877 << std::endl;
878 opts.arith.arithPivotThreshold = pivotThreshold;
879 }
880 if (!opts.arith.arithStandardCheckVarOrderPivotsWasSetByUser)
881 {
882 int16_t varOrderPivots = -1;
883 if (logic.isPure(THEORY_ARITH) && !logic.isQuantified())
884 {
885 varOrderPivots = 200;
886 }
887 Trace("smt") << "setting arithStandardCheckVarOrderPivots "
888 << varOrderPivots << std::endl;
889 opts.arith.arithStandardCheckVarOrderPivots = varOrderPivots;
890 }
891 if (logic.isPure(THEORY_ARITH) && !logic.areRealsUsed())
892 {
893 if (!opts.arith.nlExtTangentPlanesInterleaveWasSetByUser)
894 {
895 Trace("smt") << "setting nlExtTangentPlanesInterleave to true"
896 << std::endl;
897 opts.arith.nlExtTangentPlanesInterleave = true;
898 }
899 }
900
901 // Set decision mode based on logic (if not set by user)
902 if (!opts.decision.decisionModeWasSetByUser)
903 {
904 options::DecisionMode decMode =
905 // anything that uses sygus uses internal
906 usesSygus ? options::DecisionMode::INTERNAL :
907 // ALL or its supersets
908 logic.hasEverything()
909 ? options::DecisionMode::JUSTIFICATION
910 : ( // QF_BV
911 (not logic.isQuantified() && logic.isPure(THEORY_BV)) ||
912 // QF_AUFBV or QF_ABV or QF_UFBV
913 (not logic.isQuantified()
914 && (logic.isTheoryEnabled(THEORY_ARRAYS)
915 || logic.isTheoryEnabled(THEORY_UF))
916 && logic.isTheoryEnabled(THEORY_BV))
917 ||
918 // QF_AUFLIA (and may be ends up enabling
919 // QF_AUFLRA?)
920 (not logic.isQuantified()
921 && logic.isTheoryEnabled(THEORY_ARRAYS)
922 && logic.isTheoryEnabled(THEORY_UF)
923 && logic.isTheoryEnabled(THEORY_ARITH))
924 ||
925 // QF_LRA
926 (not logic.isQuantified()
927 && logic.isPure(THEORY_ARITH) && logic.isLinear()
928 && !logic.isDifferenceLogic()
929 && !logic.areIntegersUsed())
930 ||
931 // Quantifiers
932 logic.isQuantified() ||
933 // Strings
934 logic.isTheoryEnabled(THEORY_STRINGS)
935 ? options::DecisionMode::JUSTIFICATION
936 : options::DecisionMode::INTERNAL);
937
938 bool stoponly =
939 // ALL or its supersets
940 logic.hasEverything() || logic.isTheoryEnabled(THEORY_STRINGS)
941 ? false
942 : ( // QF_AUFLIA
943 (not logic.isQuantified()
944 && logic.isTheoryEnabled(THEORY_ARRAYS)
945 && logic.isTheoryEnabled(THEORY_UF)
946 && logic.isTheoryEnabled(THEORY_ARITH))
947 ||
948 // QF_LRA
949 (not logic.isQuantified()
950 && logic.isPure(THEORY_ARITH) && logic.isLinear()
951 && !logic.isDifferenceLogic()
952 && !logic.areIntegersUsed())
953 ? true
954 : false);
955
956 opts.decision.decisionMode = decMode;
957 if (stoponly)
958 {
959 if (opts.decision.decisionMode == options::DecisionMode::JUSTIFICATION)
960 {
961 opts.decision.decisionMode = options::DecisionMode::STOPONLY;
962 }
963 else
964 {
965 Assert(opts.decision.decisionMode == options::DecisionMode::INTERNAL);
966 }
967 }
968 Trace("smt") << "setting decision mode to " << opts.decision.decisionMode
969 << std::endl;
970 }
971
972 // set up of central equality engine
973 if (opts.theory.eeMode == options::EqEngineMode::CENTRAL)
974 {
975 if (!opts.arith.arithEqSolverWasSetByUser)
976 {
977 // use the arithmetic equality solver by default
978 opts.arith.arithEqSolver = true;
979 }
980 }
981 if (opts.arith.arithEqSolver)
982 {
983 if (!opts.arith.arithCongManWasSetByUser)
984 {
985 // if we are using the arithmetic equality solver, do not use the
986 // arithmetic congruence manager by default
987 opts.arith.arithCongMan = false;
988 }
989 }
990
991 if (options::incrementalSolving())
992 {
993 // disable modes not supported by incremental
994 opts.smt.sortInference = false;
995 opts.uf.ufssFairnessMonotone = false;
996 opts.quantifiers.globalNegate = false;
997 opts.bv.bvAbstraction = false;
998 opts.arith.arithMLTrick = false;
999 }
1000 if (logic.hasCardinalityConstraints())
1001 {
1002 // must have finite model finding on
1003 opts.quantifiers.finiteModelFind = true;
1004 }
1005
1006 if (options::instMaxLevel() != -1)
1007 {
1008 Notice() << "SmtEngine: turning off cbqi to support instMaxLevel"
1009 << std::endl;
1010 opts.quantifiers.cegqi = false;
1011 }
1012
1013 if ((opts.quantifiers.fmfBoundLazyWasSetByUser && options::fmfBoundLazy())
1014 || (opts.quantifiers.fmfBoundIntWasSetByUser && options::fmfBoundInt()))
1015 {
1016 opts.quantifiers.fmfBound = true;
1017 Trace("smt")
1018 << "turning on fmf-bound, for fmf-bound-int or fmf-bound-lazy\n";
1019 }
1020 // now have determined whether fmfBound is on/off
1021 // apply fmfBound options
1022 if (options::fmfBound())
1023 {
1024 if (!opts.quantifiers.mbqiModeWasSetByUser
1025 || (options::mbqiMode() != options::MbqiMode::NONE
1026 && options::mbqiMode() != options::MbqiMode::FMC))
1027 {
1028 // if bounded integers are set, use no MBQI by default
1029 opts.quantifiers.mbqiMode = options::MbqiMode::NONE;
1030 }
1031 if (!opts.quantifiers.prenexQuantUserWasSetByUser)
1032 {
1033 opts.quantifiers.prenexQuant = options::PrenexQuantMode::NONE;
1034 }
1035 }
1036 if (logic.isHigherOrder())
1037 {
1038 opts.uf.ufHo = true;
1039 // if higher-order, then current variants of model-based instantiation
1040 // cannot be used
1041 if (options::mbqiMode() != options::MbqiMode::NONE)
1042 {
1043 opts.quantifiers.mbqiMode = options::MbqiMode::NONE;
1044 }
1045 if (!opts.quantifiers.hoElimStoreAxWasSetByUser)
1046 {
1047 // by default, use store axioms only if --ho-elim is set
1048 opts.quantifiers.hoElimStoreAx = options::hoElim();
1049 }
1050 if (!options::assignFunctionValues())
1051 {
1052 // must assign function values
1053 opts.theory.assignFunctionValues = true;
1054 }
1055 // Cannot use macros, since lambda lifting and macro elimination are inverse
1056 // operations.
1057 if (options::macrosQuant())
1058 {
1059 opts.quantifiers.macrosQuant = false;
1060 }
1061 // HOL is incompatible with fmfBound
1062 if (options::fmfBound())
1063 {
1064 if (opts.quantifiers.fmfBoundWasSetByUser
1065 || opts.quantifiers.fmfBoundLazyWasSetByUser
1066 || opts.quantifiers.fmfBoundIntWasSetByUser)
1067 {
1068 Notice() << "Disabling bound finite-model finding since it is "
1069 "incompatible with HOL.\n";
1070 }
1071
1072 opts.quantifiers.fmfBound = false;
1073 Trace("smt") << "turning off fmf-bound, since HOL\n";
1074 }
1075 }
1076 if (options::fmfFunWellDefinedRelevant())
1077 {
1078 if (!opts.quantifiers.fmfFunWellDefinedWasSetByUser)
1079 {
1080 opts.quantifiers.fmfFunWellDefined = true;
1081 }
1082 }
1083 if (options::fmfFunWellDefined())
1084 {
1085 if (!opts.quantifiers.finiteModelFindWasSetByUser)
1086 {
1087 opts.quantifiers.finiteModelFind = true;
1088 }
1089 }
1090
1091 // now, have determined whether finite model find is on/off
1092 // apply finite model finding options
1093 if (options::finiteModelFind())
1094 {
1095 // apply conservative quantifiers splitting
1096 if (!opts.quantifiers.quantDynamicSplitWasSetByUser)
1097 {
1098 opts.quantifiers.quantDynamicSplit = options::QuantDSplitMode::DEFAULT;
1099 }
1100 if (!opts.quantifiers.eMatchingWasSetByUser)
1101 {
1102 opts.quantifiers.eMatching = options::fmfInstEngine();
1103 }
1104 if (!opts.quantifiers.instWhenModeWasSetByUser)
1105 {
1106 // instantiate only on last call
1107 if (options::eMatching())
1108 {
1109 opts.quantifiers.instWhenMode = options::InstWhenMode::LAST_CALL;
1110 }
1111 }
1112 }
1113
1114 // apply sygus options
1115 // if we are attempting to rewrite everything to SyGuS, use sygus()
1116 if (usesSygus)
1117 {
1118 if (!options::sygus())
1119 {
1120 Trace("smt") << "turning on sygus" << std::endl;
1121 }
1122 opts.quantifiers.sygus = true;
1123 // must use Ferrante/Rackoff for real arithmetic
1124 if (!opts.quantifiers.cegqiMidpointWasSetByUser)
1125 {
1126 opts.quantifiers.cegqiMidpoint = true;
1127 }
1128 // must disable cegqi-bv since it may introduce witness terms, which
1129 // cannot appear in synthesis solutions
1130 if (!opts.quantifiers.cegqiBvWasSetByUser)
1131 {
1132 opts.quantifiers.cegqiBv = false;
1133 }
1134 if (options::sygusRepairConst())
1135 {
1136 if (!opts.quantifiers.cegqiWasSetByUser)
1137 {
1138 opts.quantifiers.cegqi = true;
1139 }
1140 }
1141 if (options::sygusInference())
1142 {
1143 // optimization: apply preskolemization, makes it succeed more often
1144 if (!opts.quantifiers.preSkolemQuantWasSetByUser)
1145 {
1146 opts.quantifiers.preSkolemQuant = true;
1147 }
1148 if (!opts.quantifiers.preSkolemQuantNestedWasSetByUser)
1149 {
1150 opts.quantifiers.preSkolemQuantNested = true;
1151 }
1152 }
1153 // counterexample-guided instantiation for sygus
1154 if (!opts.quantifiers.cegqiSingleInvModeWasSetByUser)
1155 {
1156 opts.quantifiers.cegqiSingleInvMode = options::CegqiSingleInvMode::USE;
1157 }
1158 if (!opts.quantifiers.quantConflictFindWasSetByUser)
1159 {
1160 opts.quantifiers.quantConflictFind = false;
1161 }
1162 if (!opts.quantifiers.instNoEntailWasSetByUser)
1163 {
1164 opts.quantifiers.instNoEntail = false;
1165 }
1166 if (!opts.quantifiers.cegqiFullEffortWasSetByUser)
1167 {
1168 // should use full effort cbqi for single invocation and repair const
1169 opts.quantifiers.cegqiFullEffort = true;
1170 }
1171 if (options::sygusRew())
1172 {
1173 opts.quantifiers.sygusRewSynth = true;
1174 opts.quantifiers.sygusRewVerify = true;
1175 }
1176 if (options::sygusRewSynthInput())
1177 {
1178 // If we are using synthesis rewrite rules from input, we use
1179 // sygusRewSynth after preprocessing. See passes/synth_rew_rules.h for
1180 // details on this technique.
1181 opts.quantifiers.sygusRewSynth = true;
1182 // we should not use the extended rewriter, since we are interested
1183 // in rewrites that are not in the main rewriter
1184 if (!opts.quantifiers.sygusExtRewWasSetByUser)
1185 {
1186 opts.quantifiers.sygusExtRew = false;
1187 }
1188 }
1189 // Whether we must use "basic" sygus algorithms. A non-basic sygus algorithm
1190 // is one that is specialized for returning a single solution. Non-basic
1191 // sygus algorithms currently include the PBE solver, UNIF+PI, static
1192 // template inference for invariant synthesis, and single invocation
1193 // techniques.
1194 bool reqBasicSygus = false;
1195 if (options::produceAbducts())
1196 {
1197 // if doing abduction, we should filter strong solutions
1198 if (!opts.quantifiers.sygusFilterSolModeWasSetByUser)
1199 {
1200 opts.quantifiers.sygusFilterSolMode = options::SygusFilterSolMode::STRONG;
1201 }
1202 // we must use basic sygus algorithms, since e.g. we require checking
1203 // a sygus side condition for consistency with axioms.
1204 reqBasicSygus = true;
1205 }
1206 if (options::sygusRewSynth() || options::sygusRewVerify()
1207 || options::sygusQueryGen())
1208 {
1209 // rewrite rule synthesis implies that sygus stream must be true
1210 opts.quantifiers.sygusStream = true;
1211 }
1212 if (options::sygusStream() || options::incrementalSolving())
1213 {
1214 // Streaming and incremental mode are incompatible with techniques that
1215 // focus the search towards finding a single solution.
1216 reqBasicSygus = true;
1217 }
1218 // Now, disable options for non-basic sygus algorithms, if necessary.
1219 if (reqBasicSygus)
1220 {
1221 if (!opts.quantifiers.sygusUnifPbeWasSetByUser)
1222 {
1223 opts.quantifiers.sygusUnifPbe = false;
1224 }
1225 if (opts.quantifiers.sygusUnifPiWasSetByUser)
1226 {
1227 opts.quantifiers.sygusUnifPi = options::SygusUnifPiMode::NONE;
1228 }
1229 if (!opts.quantifiers.sygusInvTemplModeWasSetByUser)
1230 {
1231 opts.quantifiers.sygusInvTemplMode = options::SygusInvTemplMode::NONE;
1232 }
1233 if (!opts.quantifiers.cegqiSingleInvModeWasSetByUser)
1234 {
1235 opts.quantifiers.cegqiSingleInvMode = options::CegqiSingleInvMode::NONE;
1236 }
1237 }
1238 if (!opts.datatypes.dtRewriteErrorSelWasSetByUser)
1239 {
1240 opts.datatypes.dtRewriteErrorSel = true;
1241 }
1242 // do not miniscope
1243 if (!opts.quantifiers.miniscopeQuantWasSetByUser)
1244 {
1245 opts.quantifiers.miniscopeQuant = false;
1246 }
1247 if (!opts.quantifiers.miniscopeQuantFreeVarWasSetByUser)
1248 {
1249 opts.quantifiers.miniscopeQuantFreeVar = false;
1250 }
1251 if (!opts.quantifiers.quantSplitWasSetByUser)
1252 {
1253 opts.quantifiers.quantSplit = false;
1254 }
1255 // do not do macros
1256 if (!opts.quantifiers.macrosQuantWasSetByUser)
1257 {
1258 opts.quantifiers.macrosQuant = false;
1259 }
1260 // use tangent planes by default, since we want to put effort into
1261 // the verification step for sygus queries with non-linear arithmetic
1262 if (!opts.arith.nlExtTangentPlanesWasSetByUser)
1263 {
1264 opts.arith.nlExtTangentPlanes = true;
1265 }
1266 }
1267 // counterexample-guided instantiation for non-sygus
1268 // enable if any possible quantifiers with arithmetic, datatypes or bitvectors
1269 if ((logic.isQuantified()
1270 && (logic.isTheoryEnabled(THEORY_ARITH)
1271 || logic.isTheoryEnabled(THEORY_DATATYPES)
1272 || logic.isTheoryEnabled(THEORY_BV)
1273 || logic.isTheoryEnabled(THEORY_FP)))
1274 || options::cegqiAll())
1275 {
1276 if (!opts.quantifiers.cegqiWasSetByUser)
1277 {
1278 opts.quantifiers.cegqi = true;
1279 }
1280 // check whether we should apply full cbqi
1281 if (logic.isPure(THEORY_BV))
1282 {
1283 if (!opts.quantifiers.cegqiFullEffortWasSetByUser)
1284 {
1285 opts.quantifiers.cegqiFullEffort = true;
1286 }
1287 }
1288 }
1289 if (options::cegqi())
1290 {
1291 if (options::incrementalSolving())
1292 {
1293 // cannot do nested quantifier elimination in incremental mode
1294 opts.quantifiers.cegqiNestedQE = false;
1295 }
1296 if (logic.isPure(THEORY_ARITH) || logic.isPure(THEORY_BV))
1297 {
1298 if (!opts.quantifiers.quantConflictFindWasSetByUser)
1299 {
1300 opts.quantifiers.quantConflictFind = false;
1301 }
1302 if (!opts.quantifiers.instNoEntailWasSetByUser)
1303 {
1304 opts.quantifiers.instNoEntail = false;
1305 }
1306 if (!opts.quantifiers.instWhenModeWasSetByUser && options::cegqiModel())
1307 {
1308 // only instantiation should happen at last call when model is avaiable
1309 opts.quantifiers.instWhenMode = options::InstWhenMode::LAST_CALL;
1310 }
1311 }
1312 else
1313 {
1314 // only supported in pure arithmetic or pure BV
1315 opts.quantifiers.cegqiNestedQE = false;
1316 }
1317 if (options::globalNegate())
1318 {
1319 if (!opts.quantifiers.prenexQuantWasSetByUser)
1320 {
1321 opts.quantifiers.prenexQuant = options::PrenexQuantMode::NONE;
1322 }
1323 }
1324 }
1325 // implied options...
1326 if (options::strictTriggers())
1327 {
1328 if (!opts.quantifiers.userPatternsQuantWasSetByUser)
1329 {
1330 opts.quantifiers.userPatternsQuant = options::UserPatMode::TRUST;
1331 }
1332 }
1333 if (opts.quantifiers.qcfModeWasSetByUser || options::qcfTConstraint())
1334 {
1335 opts.quantifiers.quantConflictFind = true;
1336 }
1337 if (options::cegqiNestedQE())
1338 {
1339 opts.quantifiers.prenexQuantUser = true;
1340 if (!opts.quantifiers.preSkolemQuantWasSetByUser)
1341 {
1342 opts.quantifiers.preSkolemQuant = true;
1343 }
1344 }
1345 // for induction techniques
1346 if (options::quantInduction())
1347 {
1348 if (!opts.quantifiers.dtStcInductionWasSetByUser)
1349 {
1350 opts.quantifiers.dtStcInduction = true;
1351 }
1352 if (!opts.quantifiers.intWfInductionWasSetByUser)
1353 {
1354 opts.quantifiers.intWfInduction = true;
1355 }
1356 }
1357 if (options::dtStcInduction())
1358 {
1359 // try to remove ITEs from quantified formulas
1360 if (!opts.quantifiers.iteDtTesterSplitQuantWasSetByUser)
1361 {
1362 opts.quantifiers.iteDtTesterSplitQuant = true;
1363 }
1364 if (!opts.quantifiers.iteLiftQuantWasSetByUser)
1365 {
1366 opts.quantifiers.iteLiftQuant = options::IteLiftQuantMode::ALL;
1367 }
1368 }
1369 if (options::intWfInduction())
1370 {
1371 if (!opts.quantifiers.purifyTriggersWasSetByUser)
1372 {
1373 opts.quantifiers.purifyTriggers = true;
1374 }
1375 }
1376 if (options::conjectureNoFilter())
1377 {
1378 if (!opts.quantifiers.conjectureFilterActiveTermsWasSetByUser)
1379 {
1380 opts.quantifiers.conjectureFilterActiveTerms = false;
1381 }
1382 if (!opts.quantifiers.conjectureFilterCanonicalWasSetByUser)
1383 {
1384 opts.quantifiers.conjectureFilterCanonical = false;
1385 }
1386 if (!opts.quantifiers.conjectureFilterModelWasSetByUser)
1387 {
1388 opts.quantifiers.conjectureFilterModel = false;
1389 }
1390 }
1391 if (opts.quantifiers.conjectureGenPerRoundWasSetByUser)
1392 {
1393 if (options::conjectureGenPerRound() > 0)
1394 {
1395 opts.quantifiers.conjectureGen = true;
1396 }
1397 else
1398 {
1399 opts.quantifiers.conjectureGen = false;
1400 }
1401 }
1402 // can't pre-skolemize nested quantifiers without UF theory
1403 if (!logic.isTheoryEnabled(THEORY_UF) && options::preSkolemQuant())
1404 {
1405 if (!opts.quantifiers.preSkolemQuantNestedWasSetByUser)
1406 {
1407 opts.quantifiers.preSkolemQuantNested = false;
1408 }
1409 }
1410 if (!logic.isTheoryEnabled(THEORY_DATATYPES))
1411 {
1412 opts.quantifiers.quantDynamicSplit = options::QuantDSplitMode::NONE;
1413 }
1414
1415 // until bugs 371,431 are fixed
1416 if (!opts.prop.minisatUseElimWasSetByUser)
1417 {
1418 // cannot use minisat elimination for logics where a theory solver
1419 // introduces new literals into the search. This includes quantifiers
1420 // (quantifier instantiation), and the lemma schemas used in non-linear
1421 // and sets. We also can't use it if models are enabled.
1422 if (logic.isTheoryEnabled(THEORY_SETS)
1423 || logic.isTheoryEnabled(THEORY_BAGS)
1424 || logic.isQuantified()
1425 || options::produceModels() || options::produceAssignments()
1426 || options::checkModels()
1427 || (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()))
1428 {
1429 opts.prop.minisatUseElim = false;
1430 }
1431 }
1432
1433 if (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
1434 && options::nlRlvMode() != options::NlRlvMode::NONE)
1435 {
1436 if (!options::relevanceFilter())
1437 {
1438 if (opts.theory.relevanceFilterWasSetByUser)
1439 {
1440 Warning() << "SmtEngine: turning on relevance filtering to support "
1441 "--nl-ext-rlv="
1442 << options::nlRlvMode() << std::endl;
1443 }
1444 // must use relevance filtering techniques
1445 opts.theory.relevanceFilter = true;
1446 }
1447 }
1448
1449 // For now, these array theory optimizations do not support model-building
1450 if (options::produceModels() || options::produceAssignments()
1451 || options::checkModels())
1452 {
1453 opts.arrays.arraysOptimizeLinear = false;
1454 }
1455
1456 if (options::stringFMF() && !opts.strings.stringProcessLoopModeWasSetByUser)
1457 {
1458 Trace("smt") << "settting stringProcessLoopMode to 'simple' since "
1459 "--strings-fmf enabled"
1460 << std::endl;
1461 opts.strings.stringProcessLoopMode = options::ProcessLoopMode::SIMPLE;
1462 }
1463
1464 // !!! All options that require disabling models go here
1465 bool disableModels = false;
1466 std::string sOptNoModel;
1467 if (opts.smt.unconstrainedSimpWasSetByUser && options::unconstrainedSimp())
1468 {
1469 disableModels = true;
1470 sOptNoModel = "unconstrained-simp";
1471 }
1472 else if (options::sortInference())
1473 {
1474 disableModels = true;
1475 sOptNoModel = "sort-inference";
1476 }
1477 else if (options::minisatUseElim())
1478 {
1479 disableModels = true;
1480 sOptNoModel = "minisat-elimination";
1481 }
1482 else if (options::globalNegate())
1483 {
1484 disableModels = true;
1485 sOptNoModel = "global-negate";
1486 }
1487 if (disableModels)
1488 {
1489 if (options::produceModels())
1490 {
1491 if (opts.smt.produceModelsWasSetByUser)
1492 {
1493 std::stringstream ss;
1494 ss << "Cannot use " << sOptNoModel << " with model generation.";
1495 throw OptionException(ss.str());
1496 }
1497 Notice() << "SmtEngine: turning off produce-models to support "
1498 << sOptNoModel << std::endl;
1499 opts.smt.produceModels = false;
1500 }
1501 if (options::produceAssignments())
1502 {
1503 if (opts.smt.produceAssignmentsWasSetByUser)
1504 {
1505 std::stringstream ss;
1506 ss << "Cannot use " << sOptNoModel
1507 << " with model generation (produce-assignments).";
1508 throw OptionException(ss.str());
1509 }
1510 Notice() << "SmtEngine: turning off produce-assignments to support "
1511 << sOptNoModel << std::endl;
1512 opts.smt.produceAssignments = false;
1513 }
1514 if (options::checkModels())
1515 {
1516 if (opts.smt.checkModelsWasSetByUser)
1517 {
1518 std::stringstream ss;
1519 ss << "Cannot use " << sOptNoModel
1520 << " with model generation (check-models).";
1521 throw OptionException(ss.str());
1522 }
1523 Notice() << "SmtEngine: turning off check-models to support "
1524 << sOptNoModel << std::endl;
1525 opts.smt.checkModels = false;
1526 }
1527 }
1528
1529 if (options::bitblastMode() == options::BitblastMode::EAGER
1530 && !logic.isPure(THEORY_BV) && logic.getLogicString() != "QF_UFBV"
1531 && logic.getLogicString() != "QF_ABV")
1532 {
1533 throw OptionException(
1534 "Eager bit-blasting does not currently support theory combination. "
1535 "Note that in a QF_BV problem UF symbols can be introduced for "
1536 "division. "
1537 "Try --bv-div-zero-const to interpret division by zero as a constant.");
1538 }
1539
1540 if (logic == LogicInfo("QF_UFNRA"))
1541 {
1542 #ifdef CVC5_USE_POLY
1543 if (!options::nlCad() && !opts.arith.nlCadWasSetByUser)
1544 {
1545 opts.arith.nlCad = true;
1546 if (!opts.arith.nlExtWasSetByUser)
1547 {
1548 opts.arith.nlExt = options::NlExtMode::LIGHT;
1549 }
1550 if (!opts.arith.nlRlvModeWasSetByUser)
1551 {
1552 opts.arith.nlRlvMode = options::NlRlvMode::INTERLEAVE;
1553 }
1554 }
1555 #endif
1556 }
1557 #ifndef CVC5_USE_POLY
1558 if (options::nlCad())
1559 {
1560 if (opts.arith.nlCadWasSetByUser)
1561 {
1562 std::stringstream ss;
1563 ss << "Cannot use " << options::arith::nlCad__name << " without configuring with --poly.";
1564 throw OptionException(ss.str());
1565 }
1566 else
1567 {
1568 Notice() << "Cannot use --" << options::arith::nlCad__name
1569 << " without configuring with --poly." << std::endl;
1570 opts.arith.nlCad = false;
1571 opts.arith.nlExt = options::NlExtMode::FULL;
1572 }
1573 }
1574 #endif
1575 }
1576
1577 } // namespace smt
1578 } // namespace cvc5