GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/set_defaults.cpp Lines: 652 821 79.4 %
Date: 2021-09-07 Branches: 930 1652 56.3 %

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