GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/set_defaults.cpp Lines: 657 826 79.5 %
Date: 2021-09-09 Branches: 941 1668 56.4 %

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
9929
SetDefaults::SetDefaults(bool isInternalSubsolver)
50
9929
    : d_isInternalSubsolver(isInternalSubsolver)
51
{
52
9929
}
53
54
9929
void SetDefaults::setDefaults(LogicInfo& logic, Options& opts)
55
{
56
  // initial changes that are independent of logic, and may impact the logic
57
9929
  setDefaultsPre(opts);
58
  // now, finalize the logic
59
9929
  finalizeLogic(logic, opts);
60
  // further changes to options based on the logic
61
9928
  setDefaultsPost(logic, opts);
62
9928
}
63
64
9929
void SetDefaults::setDefaultsPre(Options& opts)
65
{
66
  // implied options
67
9929
  if (opts.smt.debugCheckModels)
68
  {
69
1284
    opts.smt.checkModels = true;
70
  }
71
9929
  if (opts.smt.checkModels || opts.driver.dumpModels)
72
  {
73
1307
    opts.smt.produceModels = true;
74
  }
75
9929
  if (opts.smt.checkModels)
76
  {
77
1304
    opts.smt.produceAssignments = true;
78
  }
79
  // unsat cores and proofs shenanigans
80
9929
  if (opts.driver.dumpUnsatCoresFull)
81
  {
82
4
    opts.driver.dumpUnsatCores = true;
83
  }
84
9929
  if (opts.smt.checkUnsatCores || opts.driver.dumpUnsatCores
85
8765
      || opts.smt.unsatAssumptions || opts.smt.minimalUnsatCores
86
8745
      || opts.smt.unsatCoresMode != options::UnsatCoresMode::OFF)
87
  {
88
2620
    opts.smt.unsatCores = true;
89
  }
90
9929
  if (opts.smt.unsatCores
91
2632
      && opts.smt.unsatCoresMode == options::UnsatCoresMode::OFF)
92
  {
93
1182
    if (opts.smt.unsatCoresModeWasSetByUser)
94
    {
95
      Notice()
96
          << "Overriding OFF unsat-core mode since cores were requested.\n";
97
    }
98
1182
    opts.smt.unsatCoresMode = options::UnsatCoresMode::ASSUMPTIONS;
99
  }
100
101
9929
  if (opts.smt.checkProofs || opts.driver.dumpProofs)
102
  {
103
1165
    opts.smt.produceProofs = true;
104
  }
105
106
9929
  if (opts.smt.produceProofs
107
1233
      && opts.smt.unsatCoresMode != options::UnsatCoresMode::FULL_PROOF)
108
  {
109
1230
    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
1230
    opts.smt.unsatCores = true;
116
1230
    opts.smt.unsatCoresMode = options::UnsatCoresMode::FULL_PROOF;
117
  }
118
119
  // set proofs on if not yet set
120
9929
  if (opts.smt.unsatCores && !opts.smt.produceProofs)
121
  {
122
2557
    if (opts.smt.produceProofsWasSetByUser)
123
    {
124
18
      Notice()
125
          << "Forcing proof production since new unsat cores were requested.\n";
126
    }
127
2557
    opts.smt.produceProofs = true;
128
  }
129
130
  // if unsat cores are disabled, then unsat cores mode should be OFF
131
9929
  Assert(opts.smt.unsatCores
132
         == (opts.smt.unsatCoresMode != options::UnsatCoresMode::OFF));
133
134
9929
  if (opts.bv.bitvectorAigSimplificationsWasSetByUser)
135
  {
136
    Notice() << "SmtEngine: setting bitvectorAig" << std::endl;
137
    opts.bv.bitvectorAig = true;
138
  }
139
9929
  if (opts.bv.bitvectorAlgebraicBudgetWasSetByUser)
140
  {
141
    Notice() << "SmtEngine: setting bitvectorAlgebraicSolver" << std::endl;
142
    opts.bv.bitvectorAlgebraicSolver = true;
143
  }
144
9929
}
145
146
9929
void SetDefaults::finalizeLogic(LogicInfo& logic, Options& opts) const
147
{
148
9929
  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
29065
  else if (!isSygus(opts) && logic.isQuantified()
158
15560
           && (logic.isPure(THEORY_FP)
159
5628
               || (logic.isPure(THEORY_ARITH) && !logic.isLinear())))
160
  {
161
33
    opts.quantifiers.sygusInst = true;
162
  }
163
164
9929
  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
9929
  if (opts.bv.bvSolver == options::BVSolver::BITBLAST)
190
  {
191
8485
    opts.bv.bitvectorPropagate = false;
192
  }
193
194
9929
  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
9929
  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
19930
  if (opts.smt.ackermann && opts.smt.produceModels
234
9944
      && (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
9929
  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
9929
  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
9929
  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
744
    opts.strings.stringExp = true;
285
744
    Trace("smt") << "Turning stringExp on since logic does not have everything "
286
                    "and string theory is enabled\n";
287
  }
288
9929
  if (opts.strings.stringExp || !opts.strings.stringLazyPreproc)
289
  {
290
    // We require quantifiers since extended functions reduce using them.
291
1153
    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
9929
  if (opts.smt.unsatCores
308
3790
      && opts.smt.unsatCoresMode != options::UnsatCoresMode::FULL_PROOF)
309
  {
310
    // no fine-graininess
311
2542
    if (!opts.proof.proofGranularityModeWasSetByUser)
312
    {
313
2542
      opts.proof.proofGranularityMode = options::ProofGranularityMode::OFF;
314
    }
315
  }
316
317
9929
  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
9929
  if (usesSygus(opts))
336
  {
337
682
    logic = logic.getUnlockedCopy();
338
682
    logic.enableSygus();
339
682
    logic.lock();
340
  }
341
342
  // if we requiring disabling proofs, disable them now
343
9929
  if (opts.smt.produceProofs)
344
  {
345
7580
    std::stringstream reasonNoProofs;
346
3790
    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
9929
  if (opts.quantifiers.sygusCoreConnective)
359
  {
360
69
    opts.smt.unsatCores = true;
361
69
    if (opts.smt.unsatCoresMode == options::UnsatCoresMode::OFF)
362
    {
363
5
      opts.smt.unsatCoresMode = options::UnsatCoresMode::ASSUMPTIONS;
364
    }
365
  }
366
367
9929
  if ((opts.smt.checkModels || opts.smt.checkSynthSol || opts.smt.produceAbducts
368
7596
       || opts.smt.produceInterpols != options::ProduceInterpols::NONE
369
7478
       || opts.smt.modelCoresMode != options::ModelCoresMode::NONE
370
7473
       || opts.smt.blockModelsMode != options::BlockModelsMode::NONE
371
7453
       || opts.smt.produceProofs)
372
6156
      && !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
9929
  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
9929
  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
9929
  if (safeUnsatCores(opts))
408
  {
409
    // check if the options are not compatible with unsat cores
410
5090
    std::stringstream reasonNoUc;
411
2545
    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
7384
    if (!opts.smt.unconstrainedSimpWasSetByUser
422
7278
        && !opts.base.incrementalSolving)
423
    {
424
      // It is also currently incompatible with arithmetic, force the option
425
      // off.
426
11272
      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
5718
                     && !logic.isTheoryEnabled(THEORY_ARITH);
432
11272
      Trace("smt") << "setting unconstrained simplification to " << uncSimp
433
5636
                   << std::endl;
434
5636
      opts.smt.unconstrainedSimp = uncSimp;
435
    }
436
437
    // by default, nonclausal simplification is off for QF_SAT
438
7384
    if (!opts.smt.simplificationModeWasSetByUser)
439
    {
440
7358
      bool qf_sat = logic.isPure(THEORY_BOOL) && !logic.isQuantified();
441
14716
      Trace("smt") << "setting simplification mode to <"
442
7358
                   << 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
7358
      opts.smt.simplificationMode = qf_sat ? options::SimplificationMode::NONE
448
                                           : options::SimplificationMode::BATCH;
449
    }
450
  }
451
452
9928
  if (opts.quantifiers.cegqiBv && logic.isQuantified())
453
  {
454
5555
    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
19856
  if (!opts.smt.produceModels
470
10229
      && (opts.smt.produceAssignments || opts.quantifiers.sygusRewSynthCheck
471
6628
          || usesSygus(opts)))
472
  {
473
301
    Notice() << "SmtEngine: turning on produce-models" << std::endl;
474
301
    opts.smt.produceModels = true;
475
  }
476
477
  // widen the logic
478
9928
  widenLogic(logic, opts);
479
480
  // check if we have any options that are not supported with quantified logics
481
9928
  if (logic.isQuantified())
482
  {
483
13678
    std::stringstream reasonNoQuant;
484
6839
    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
9928
}
492
493
9928
void SetDefaults::setDefaultsPost(const LogicInfo& logic, Options& opts) const
494
{
495
  // Set the options for the theoryOf
496
9928
  if (!opts.theory.theoryOfModeWasSetByUser)
497
  {
498
27645
    if (logic.isSharingEnabled() && !logic.isTheoryEnabled(THEORY_BV)
499
2890
        && !logic.isTheoryEnabled(THEORY_STRINGS)
500
2324
        && !logic.isTheoryEnabled(THEORY_SETS)
501
2238
        && !logic.isTheoryEnabled(THEORY_BAGS)
502
12861
        && !(logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
503
701
             && !logic.isQuantified()))
504
    {
505
1800
      Trace("smt") << "setting theoryof-mode to term-based" << std::endl;
506
1800
      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
9928
  if (!opts.uf.ufSymmetryBreakerWasSetByUser)
512
  {
513
10286
    bool qf_uf_noinc = logic.isPure(THEORY_UF) && !logic.isQuantified()
514
264
                       && !opts.base.incrementalSolving
515
10181
                       && !safeUnsatCores(opts);
516
19856
    Trace("smt") << "setting uf symmetry breaker to " << qf_uf_noinc
517
9928
                 << std::endl;
518
9928
    opts.uf.ufSymmetryBreaker = qf_uf_noinc;
519
  }
520
521
  // If in arrays, set the UF handler to arrays
522
24726
  if (logic.isTheoryEnabled(THEORY_ARRAYS) && !logic.isHigherOrder()
523
4743
      && !opts.quantifiers.finiteModelFind
524
14973
      && (!logic.isQuantified()
525
4151
          || (logic.isQuantified() && !logic.isTheoryEnabled(THEORY_UF))))
526
  {
527
447
    Theory::setUninterpretedSortOwner(THEORY_ARRAYS);
528
  }
529
  else
530
  {
531
9481
    Theory::setUninterpretedSortOwner(THEORY_UF);
532
  }
533
534
9928
  if (!opts.smt.simplifyWithCareEnabledWasSetByUser)
535
  {
536
    bool qf_aufbv =
537
13017
        !logic.isQuantified() && logic.isTheoryEnabled(THEORY_ARRAYS)
538
10379
        && logic.isTheoryEnabled(THEORY_UF) && logic.isTheoryEnabled(THEORY_BV);
539
540
9928
    bool withCare = qf_aufbv;
541
19856
    Trace("smt") << "setting ite simplify with care to " << withCare
542
9928
                 << std::endl;
543
9928
    opts.smt.simplifyWithCareEnabled = withCare;
544
  }
545
  // Turn off array eager index splitting for QF_AUFLIA
546
9928
  if (!opts.arrays.arraysEagerIndexSplittingWasSetByUser)
547
  {
548
22945
    if (not logic.isQuantified() && logic.isTheoryEnabled(THEORY_ARRAYS)
549
451
        && logic.isTheoryEnabled(THEORY_UF)
550
10379
        && 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
9928
  if (!opts.smt.repeatSimpWasSetByUser)
559
  {
560
9924
    bool repeatSimp = !logic.isQuantified()
561
3087
                      && (logic.isTheoryEnabled(THEORY_ARRAYS)
562
451
                          && logic.isTheoryEnabled(THEORY_UF)
563
451
                          && logic.isTheoryEnabled(THEORY_BV))
564
10193
                      && !safeUnsatCores(opts);
565
19848
    Trace("smt") << "setting repeat simplification to " << repeatSimp
566
9924
                 << std::endl;
567
9924
    opts.smt.repeatSimp = repeatSimp;
568
  }
569
570
19856
  if (opts.bv.boolToBitvector == options::BoolToBVMode::ALL
571
9928
      && !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
19856
  if (!opts.bv.bvEagerExplanationsWasSetByUser
584
9928
      && logic.isTheoryEnabled(THEORY_ARRAYS)
585
14798
      && logic.isTheoryEnabled(THEORY_BV))
586
  {
587
4456
    Trace("smt") << "enabling eager bit-vector explanations " << std::endl;
588
4456
    opts.bv.bvEagerExplanations = true;
589
  }
590
591
  // Turn on arith rewrite equalities only for pure arithmetic
592
9928
  if (!opts.arith.arithRewriteEqWasSetByUser)
593
  {
594
    bool arithRewriteEq =
595
9919
        logic.isPure(THEORY_ARITH) && logic.isLinear() && !logic.isQuantified();
596
19838
    Trace("smt") << "setting arith rewrite equalities " << arithRewriteEq
597
9919
                 << std::endl;
598
9919
    opts.arith.arithRewriteEq = arithRewriteEq;
599
  }
600
9928
  if (!opts.arith.arithHeuristicPivotsWasSetByUser)
601
  {
602
9928
    int16_t heuristicPivots = 5;
603
9928
    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
19856
    Trace("smt") << "setting arithHeuristicPivots  " << heuristicPivots
615
9928
                 << std::endl;
616
9928
    opts.arith.arithHeuristicPivots = heuristicPivots;
617
  }
618
9928
  if (!opts.arith.arithPivotThresholdWasSetByUser)
619
  {
620
9928
    uint16_t pivotThreshold = 2;
621
9928
    if (logic.isPure(THEORY_ARITH) && !logic.isQuantified())
622
    {
623
729
      if (logic.isDifferenceLogic())
624
      {
625
17
        pivotThreshold = 16;
626
      }
627
    }
628
19856
    Trace("smt") << "setting arith arithPivotThreshold  " << pivotThreshold
629
9928
                 << std::endl;
630
9928
    opts.arith.arithPivotThreshold = pivotThreshold;
631
  }
632
9928
  if (!opts.arith.arithStandardCheckVarOrderPivotsWasSetByUser)
633
  {
634
9928
    int16_t varOrderPivots = -1;
635
9928
    if (logic.isPure(THEORY_ARITH) && !logic.isQuantified())
636
    {
637
729
      varOrderPivots = 200;
638
    }
639
19856
    Trace("smt") << "setting arithStandardCheckVarOrderPivots  "
640
9928
                 << varOrderPivots << std::endl;
641
9928
    opts.arith.arithStandardCheckVarOrderPivots = varOrderPivots;
642
  }
643
9928
  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
9928
  if (!opts.arith.nlRlvAssertBoundsWasSetByUser)
653
  {
654
    // use bound inference to determine when bounds are irrelevant only when
655
    // the logic is quantifier-free
656
9928
    opts.arith.nlRlvAssertBounds = !logic.isQuantified();
657
  }
658
659
  // set the default decision mode
660
9928
  setDefaultDecisionMode(logic, opts);
661
662
  // set up of central equality engine
663
9928
  if (opts.theory.eeMode == options::EqEngineMode::CENTRAL)
664
  {
665
35
    if (!opts.arith.arithEqSolverWasSetByUser)
666
    {
667
      // use the arithmetic equality solver by default
668
31
      opts.arith.arithEqSolver = true;
669
    }
670
  }
671
9928
  if (opts.arith.arithEqSolver)
672
  {
673
39
    if (!opts.arith.arithCongManWasSetByUser)
674
    {
675
      // if we are using the arithmetic equality solver, do not use the
676
      // arithmetic congruence manager by default
677
39
      opts.arith.arithCongMan = false;
678
    }
679
  }
680
681
9928
  if (opts.base.incrementalSolving)
682
  {
683
    // disable modes not supported by incremental
684
2204
    opts.smt.sortInference = false;
685
2204
    opts.uf.ufssFairnessMonotone = false;
686
2204
    opts.quantifiers.globalNegate = false;
687
2204
    opts.quantifiers.cegqiNestedQE = false;
688
2204
    opts.bv.bvAbstraction = false;
689
2204
    opts.arith.arithMLTrick = false;
690
  }
691
692
9928
  if (logic.isHigherOrder())
693
  {
694
191
    opts.uf.ufHo = true;
695
191
    if (!opts.theory.assignFunctionValues)
696
    {
697
      // must assign function values
698
2
      opts.theory.assignFunctionValues = true;
699
    }
700
  }
701
702
  // set all defaults in the quantifiers theory, which includes sygus
703
9928
  setDefaultsQuantifiers(logic, opts);
704
705
  // shared selectors are generally not good to combine with standard
706
  // quantifier techniques e.g. E-matching
707
9928
  if (opts.datatypes.dtSharedSelectorsWasSetByUser)
708
  {
709
55
    if (logic.isQuantified() && !usesSygus(opts))
710
    {
711
30
      opts.datatypes.dtSharedSelectors = false;
712
    }
713
  }
714
715
  // until bugs 371,431 are fixed
716
9928
  if (!opts.prop.minisatUseElimWasSetByUser)
717
  {
718
    // cannot use minisat elimination for logics where a theory solver
719
    // introduces new literals into the search. This includes quantifiers
720
    // (quantifier instantiation), and the lemma schemas used in non-linear
721
    // and sets. We also can't use it if models are enabled.
722
25556
    if (logic.isTheoryEnabled(THEORY_SETS) || logic.isTheoryEnabled(THEORY_BAGS)
723
5700
        || logic.isQuantified() || opts.smt.produceModels
724
2451
        || opts.smt.produceAssignments || opts.smt.checkModels
725
12379
        || (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()))
726
    {
727
7916
      opts.prop.minisatUseElim = false;
728
    }
729
  }
730
731
28100
  if (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
732
15138
      && opts.arith.nlRlvMode != options::NlRlvMode::NONE)
733
  {
734
18
    if (!opts.theory.relevanceFilter)
735
    {
736
18
      if (opts.theory.relevanceFilterWasSetByUser)
737
      {
738
        Warning() << "SmtEngine: turning on relevance filtering to support "
739
                     "--nl-ext-rlv="
740
                  << opts.arith.nlRlvMode << std::endl;
741
      }
742
      // must use relevance filtering techniques
743
18
      opts.theory.relevanceFilter = true;
744
    }
745
  }
746
747
  // For now, these array theory optimizations do not support model-building
748
9928
  if (opts.smt.produceModels || opts.smt.produceAssignments
749
6332
      || opts.smt.checkModels)
750
  {
751
3596
    opts.arrays.arraysOptimizeLinear = false;
752
  }
753
754
9928
  if (opts.strings.stringFMF && !opts.strings.stringProcessLoopModeWasSetByUser)
755
  {
756
100
    Trace("smt") << "settting stringProcessLoopMode to 'simple' since "
757
50
                    "--strings-fmf enabled"
758
50
                 << std::endl;
759
50
    opts.strings.stringProcessLoopMode = options::ProcessLoopMode::SIMPLE;
760
  }
761
762
  // !!! All options that require disabling models go here
763
19856
  std::stringstream reasonNoModel;
764
9928
  if (incompatibleWithModels(opts, reasonNoModel))
765
  {
766
4158
    std::string sOptNoModel = reasonNoModel.str();
767
2079
    if (opts.smt.produceModels)
768
    {
769
47
      if (opts.smt.produceModelsWasSetByUser)
770
      {
771
        std::stringstream ss;
772
        ss << "Cannot use " << sOptNoModel << " with model generation.";
773
        throw OptionException(ss.str());
774
      }
775
47
      Notice() << "SmtEngine: turning off produce-models to support "
776
               << sOptNoModel << std::endl;
777
47
      opts.smt.produceModels = false;
778
    }
779
2079
    if (opts.smt.produceAssignments)
780
    {
781
46
      if (opts.smt.produceAssignmentsWasSetByUser)
782
      {
783
        std::stringstream ss;
784
        ss << "Cannot use " << sOptNoModel
785
           << " with model generation (produce-assignments).";
786
        throw OptionException(ss.str());
787
      }
788
46
      Notice() << "SmtEngine: turning off produce-assignments to support "
789
               << sOptNoModel << std::endl;
790
46
      opts.smt.produceAssignments = false;
791
    }
792
2079
    if (opts.smt.checkModels)
793
    {
794
46
      if (opts.smt.checkModelsWasSetByUser)
795
      {
796
        std::stringstream ss;
797
        ss << "Cannot use " << sOptNoModel
798
           << " with model generation (check-models).";
799
        throw OptionException(ss.str());
800
      }
801
46
      Notice() << "SmtEngine: turning off check-models to support "
802
               << sOptNoModel << std::endl;
803
46
      opts.smt.checkModels = false;
804
    }
805
  }
806
807
19856
  if (opts.bv.bitblastMode == options::BitblastMode::EAGER
808
9972
      && !logic.isPure(THEORY_BV) && logic.getLogicString() != "QF_UFBV"
809
19856
      && logic.getLogicString() != "QF_ABV")
810
  {
811
    throw OptionException(
812
        "Eager bit-blasting does not currently support theory combination. "
813
        "Note that in a QF_BV problem UF symbols can be introduced for "
814
        "division. "
815
        "Try --bv-div-zero-const to interpret division by zero as a constant.");
816
  }
817
818
#ifdef CVC5_USE_POLY
819
9928
  if (logic == LogicInfo("QF_UFNRA"))
820
  {
821
118
    if (!opts.arith.nlCad && !opts.arith.nlCadWasSetByUser)
822
    {
823
97
      opts.arith.nlCad = true;
824
97
      if (!opts.arith.nlExtWasSetByUser)
825
      {
826
48
        opts.arith.nlExt = options::NlExtMode::LIGHT;
827
      }
828
97
      if (!opts.arith.nlRlvModeWasSetByUser)
829
      {
830
97
        opts.arith.nlRlvMode = options::NlRlvMode::INTERLEAVE;
831
      }
832
    }
833
  }
834
#else
835
  if (opts.arith.nlCad)
836
  {
837
    if (opts.arith.nlCadWasSetByUser)
838
    {
839
      std::stringstream ss;
840
      ss << "Cannot use " << options::arith::nlCad__name
841
         << " without configuring with --poly.";
842
      throw OptionException(ss.str());
843
    }
844
    else
845
    {
846
      Notice() << "Cannot use --" << options::arith::nlCad__name
847
               << " without configuring with --poly." << std::endl;
848
      opts.arith.nlCad = false;
849
      opts.arith.nlExt = options::NlExtMode::FULL;
850
    }
851
  }
852
#endif
853
9928
}
854
855
50050
bool SetDefaults::isSygus(const Options& opts) const
856
{
857
50050
  if (language::isLangSygus(opts.base.inputLanguage))
858
  {
859
2398
    return true;
860
  }
861
47652
  if (!d_isInternalSubsolver)
862
  {
863
35477
    if (opts.smt.produceAbducts
864
35398
        || opts.smt.produceInterpols != options::ProduceInterpols::NONE
865
35348
        || opts.quantifiers.sygusInference
866
35077
        || opts.quantifiers.sygusRewSynthInput)
867
    {
868
      // since we are trying to recast as sygus, we assume the input is sygus
869
400
      return true;
870
    }
871
  }
872
47252
  return false;
873
}
874
875
36332
bool SetDefaults::usesSygus(const Options& opts) const
876
{
877
36332
  if (isSygus(opts))
878
  {
879
2159
    return true;
880
  }
881
34173
  if (!d_isInternalSubsolver && opts.quantifiers.sygusInst)
882
  {
883
    // sygus instantiation uses sygus, but it is not a sygus problem
884
192
    return true;
885
  }
886
33981
  return false;
887
}
888
889
3790
bool SetDefaults::incompatibleWithProofs(Options& opts,
890
                                         std::ostream& reason) const
891
{
892
3790
  if (opts.quantifiers.globalNegate)
893
  {
894
    // When global negate answers "unsat", it is not due to showing a set of
895
    // formulas is unsat. Thus, proofs do not apply.
896
1
    reason << "global-negate";
897
1
    return true;
898
  }
899
3789
  if (isSygus(opts))
900
  {
901
    // When sygus answers "unsat", it is not due to showing a set of
902
    // formulas is unsat in the standard way. Thus, proofs do not apply.
903
7
    reason << "sygus";
904
7
    return true;
905
  }
906
  // options that are automatically set to support proofs
907
3782
  if (opts.bv.bvAssertInput)
908
  {
909
2
    Notice()
910
        << "Disabling bv-assert-input since it is incompatible with proofs."
911
        << std::endl;
912
2
    opts.bv.bvAssertInput = false;
913
  }
914
  // If proofs are required and the user did not specify a specific BV solver,
915
  // we make sure to use the proof producing BITBLAST_INTERNAL solver.
916
3782
  if (opts.bv.bvSolver != options::BVSolver::BITBLAST_INTERNAL
917
2354
      && !opts.bv.bvSolverWasSetByUser
918
2335
      && opts.bv.bvSatSolver == options::SatSolverMode::MINISAT)
919
  {
920
2323
    Notice() << "Forcing internal bit-vector solver due to proof production."
921
             << std::endl;
922
2323
    opts.bv.bvSolver = options::BVSolver::BITBLAST_INTERNAL;
923
  }
924
3782
  return false;
925
}
926
927
9928
bool SetDefaults::incompatibleWithModels(const Options& opts,
928
                                         std::ostream& reason) const
929
{
930
9928
  if (opts.smt.unconstrainedSimpWasSetByUser && opts.smt.unconstrainedSimp)
931
  {
932
104
    reason << "unconstrained-simp";
933
104
    return true;
934
  }
935
9824
  else if (opts.smt.sortInference)
936
  {
937
20
    reason << "sort-inference";
938
20
    return true;
939
  }
940
9804
  else if (opts.prop.minisatUseElim)
941
  {
942
1949
    reason << "minisat-elimination";
943
1949
    return true;
944
  }
945
7855
  else if (opts.quantifiers.globalNegate)
946
  {
947
6
    reason << "global-negate";
948
6
    return true;
949
  }
950
7849
  return false;
951
}
952
953
2204
bool SetDefaults::incompatibleWithIncremental(const LogicInfo& logic,
954
                                              Options& opts,
955
                                              std::ostream& reason,
956
                                              std::ostream& suggest) const
957
{
958
2204
  if (opts.smt.ackermann)
959
  {
960
    reason << "ackermann";
961
    return true;
962
  }
963
2204
  if (opts.smt.unconstrainedSimp)
964
  {
965
    if (opts.smt.unconstrainedSimpWasSetByUser)
966
    {
967
      reason << "unconstrained simplification";
968
      return true;
969
    }
970
    Notice() << "SmtEngine: turning off unconstrained simplification to "
971
                "support incremental solving"
972
             << std::endl;
973
    opts.smt.unconstrainedSimp = false;
974
  }
975
4408
  if (opts.bv.bitblastMode == options::BitblastMode::EAGER
976
2204
      && !logic.isPure(THEORY_BV))
977
  {
978
    reason << "eager bit-blasting in non-QF_BV logic";
979
    suggest << "Try --bitblast=lazy.";
980
    return true;
981
  }
982
2204
  if (opts.quantifiers.sygusInference)
983
  {
984
    if (opts.quantifiers.sygusInferenceWasSetByUser)
985
    {
986
      reason << "sygus inference";
987
      return true;
988
    }
989
    Notice() << "SmtEngine: turning off sygus inference to support "
990
                "incremental solving"
991
             << std::endl;
992
    opts.quantifiers.sygusInference = false;
993
  }
994
2204
  if (opts.smt.solveIntAsBV > 0)
995
  {
996
    reason << "solveIntAsBV";
997
    return true;
998
  }
999
2204
  return false;
1000
}
1001
1002
2545
bool SetDefaults::incompatibleWithUnsatCores(Options& opts,
1003
                                             std::ostream& reason) const
1004
{
1005
2545
  if (opts.smt.simplificationMode != options::SimplificationMode::NONE)
1006
  {
1007
1165
    if (opts.smt.simplificationModeWasSetByUser)
1008
    {
1009
      reason << "simplification";
1010
      return true;
1011
    }
1012
1165
    Notice() << "SmtEngine: turning off simplification to support unsat "
1013
                "cores"
1014
             << std::endl;
1015
1165
    opts.smt.simplificationMode = options::SimplificationMode::NONE;
1016
  }
1017
1018
2545
  if (opts.smt.learnedRewrite)
1019
  {
1020
    if (opts.smt.learnedRewriteWasSetByUser)
1021
    {
1022
      reason << "learned rewrites";
1023
      return true;
1024
    }
1025
    Notice() << "SmtEngine: turning off learned rewrites to support "
1026
                "unsat cores\n";
1027
    opts.smt.learnedRewrite = false;
1028
  }
1029
1030
2545
  if (opts.arith.pbRewrites)
1031
  {
1032
    if (opts.arith.pbRewritesWasSetByUser)
1033
    {
1034
      reason << "pseudoboolean rewrites";
1035
      return true;
1036
    }
1037
    Notice() << "SmtEngine: turning off pseudoboolean rewrites to support "
1038
                "unsat cores\n";
1039
    opts.arith.pbRewrites = false;
1040
  }
1041
1042
2545
  if (opts.smt.sortInference)
1043
  {
1044
    if (opts.smt.sortInferenceWasSetByUser)
1045
    {
1046
      reason << "sort inference";
1047
      return true;
1048
    }
1049
    Notice() << "SmtEngine: turning off sort inference to support unsat "
1050
                "cores\n";
1051
    opts.smt.sortInference = false;
1052
  }
1053
1054
2545
  if (opts.quantifiers.preSkolemQuant)
1055
  {
1056
3
    if (opts.quantifiers.preSkolemQuantWasSetByUser)
1057
    {
1058
      reason << "pre-skolemization";
1059
      return true;
1060
    }
1061
3
    Notice() << "SmtEngine: turning off pre-skolemization to support "
1062
                "unsat cores\n";
1063
3
    opts.quantifiers.preSkolemQuant = false;
1064
  }
1065
1066
2545
  if (opts.bv.bitvectorToBool)
1067
  {
1068
60
    if (opts.bv.bitvectorToBoolWasSetByUser)
1069
    {
1070
      reason << "bv-to-bool";
1071
      return true;
1072
    }
1073
60
    Notice() << "SmtEngine: turning off bitvector-to-bool to support "
1074
                "unsat cores\n";
1075
60
    opts.bv.bitvectorToBool = false;
1076
  }
1077
1078
2545
  if (opts.bv.boolToBitvector != options::BoolToBVMode::OFF)
1079
  {
1080
    if (opts.bv.boolToBitvectorWasSetByUser)
1081
    {
1082
      reason << "bool-to-bv != off";
1083
      return true;
1084
    }
1085
    Notice() << "SmtEngine: turning off bool-to-bv to support unsat cores\n";
1086
    opts.bv.boolToBitvector = options::BoolToBVMode::OFF;
1087
  }
1088
1089
2545
  if (opts.bv.bvIntroducePow2)
1090
  {
1091
    if (opts.bv.bvIntroducePow2WasSetByUser)
1092
    {
1093
      reason << "bv-intro-pow2";
1094
      return true;
1095
    }
1096
    Notice() << "SmtEngine: turning off bv-intro-pow2 to support unsat cores";
1097
    opts.bv.bvIntroducePow2 = false;
1098
  }
1099
1100
2545
  if (opts.smt.repeatSimp)
1101
  {
1102
    if (opts.smt.repeatSimpWasSetByUser)
1103
    {
1104
      reason << "repeat-simp";
1105
      return true;
1106
    }
1107
    Notice() << "SmtEngine: turning off repeat-simp to support unsat cores\n";
1108
    opts.smt.repeatSimp = false;
1109
  }
1110
1111
2545
  if (opts.quantifiers.globalNegate)
1112
  {
1113
    if (opts.quantifiers.globalNegateWasSetByUser)
1114
    {
1115
      reason << "global-negate";
1116
      return true;
1117
    }
1118
    Notice() << "SmtEngine: turning off global-negate to support unsat "
1119
                "cores\n";
1120
    opts.quantifiers.globalNegate = false;
1121
  }
1122
1123
2545
  if (opts.bv.bitvectorAig)
1124
  {
1125
    reason << "bitblast-aig";
1126
    return true;
1127
  }
1128
1129
2545
  if (opts.smt.doITESimp)
1130
  {
1131
1
    reason << "ITE simp";
1132
1
    return true;
1133
  }
1134
2544
  if (opts.smt.unconstrainedSimp)
1135
  {
1136
    if (opts.smt.unconstrainedSimpWasSetByUser)
1137
    {
1138
      reason << "unconstrained simplification";
1139
      return true;
1140
    }
1141
    Notice() << "SmtEngine: turning off unconstrained simplification to "
1142
                "support unsat cores"
1143
             << std::endl;
1144
    opts.smt.unconstrainedSimp = false;
1145
  }
1146
2544
  return false;
1147
}
1148
1149
10451
bool SetDefaults::safeUnsatCores(const Options& opts) const
1150
{
1151
  // whether we want to force safe unsat cores, i.e., if we are in the default
1152
  // ASSUMPTIONS mode, since other ones are experimental
1153
10451
  return opts.smt.unsatCoresMode == options::UnsatCoresMode::ASSUMPTIONS;
1154
}
1155
1156
6839
bool SetDefaults::incompatibleWithQuantifiers(Options& opts,
1157
                                              std::ostream& reason) const
1158
{
1159
6839
  if (opts.smt.ackermann)
1160
  {
1161
    reason << "ackermann";
1162
    return true;
1163
  }
1164
6839
  if (opts.arith.nlRlvMode != options::NlRlvMode::NONE)
1165
  {
1166
    // Theory relevance is incompatible with CEGQI and SyQI, since there is no
1167
    // appropriate policy for the relevance of counterexample lemmas (when their
1168
    // guard is entailed to be false, the entire lemma is relevant, not just the
1169
    // guard). Hence, we throw an option exception if quantifiers are enabled.
1170
    reason << "--nl-ext-rlv";
1171
    return true;
1172
  }
1173
6839
  return false;
1174
}
1175
1176
9928
void SetDefaults::widenLogic(LogicInfo& logic, Options& opts) const
1177
{
1178
9928
  bool needsUf = false;
1179
  // strings require LIA, UF; widen the logic
1180
9928
  if (logic.isTheoryEnabled(THEORY_STRINGS))
1181
  {
1182
9392
    LogicInfo log(logic.getUnlockedCopy());
1183
    // Strings requires arith for length constraints, and also UF
1184
4696
    needsUf = true;
1185
4696
    if (!logic.isTheoryEnabled(THEORY_ARITH) || logic.isDifferenceLogic())
1186
    {
1187
134
      Notice()
1188
          << "Enabling linear integer arithmetic because strings are enabled"
1189
          << std::endl;
1190
134
      log.enableTheory(THEORY_ARITH);
1191
134
      log.enableIntegers();
1192
134
      log.arithOnlyLinear();
1193
    }
1194
4562
    else if (!logic.areIntegersUsed())
1195
    {
1196
      Notice() << "Enabling integer arithmetic because strings are enabled"
1197
               << std::endl;
1198
      log.enableIntegers();
1199
    }
1200
4696
    logic = log;
1201
4696
    logic.lock();
1202
  }
1203
9928
  if (opts.bv.bvAbstraction)
1204
  {
1205
    // bv abstraction may require UF
1206
4
    Notice() << "Enabling UF because bvAbstraction requires it." << std::endl;
1207
4
    needsUf = true;
1208
  }
1209
9924
  else if (opts.quantifiers.preSkolemQuantNested
1210
9907
           && opts.quantifiers.preSkolemQuantNestedWasSetByUser)
1211
  {
1212
    // if pre-skolem nested is explictly set, then we require UF. If it is
1213
    // not explicitly set, it is disabled below if UF is not present.
1214
2
    Notice() << "Enabling UF because preSkolemQuantNested requires it."
1215
             << std::endl;
1216
2
    needsUf = true;
1217
  }
1218
9928
  if (needsUf
1219
      // Arrays, datatypes and sets permit Boolean terms and thus require UF
1220
5226
      || logic.isTheoryEnabled(THEORY_ARRAYS)
1221
4488
      || logic.isTheoryEnabled(THEORY_DATATYPES)
1222
3212
      || logic.isTheoryEnabled(THEORY_SETS)
1223
3138
      || logic.isTheoryEnabled(THEORY_BAGS)
1224
      // Non-linear arithmetic requires UF to deal with division/mod because
1225
      // their expansion introduces UFs for the division/mod-by-zero case.
1226
      // If we are eliminating non-linear arithmetic via solve-int-as-bv,
1227
      // then this is not required, since non-linear arithmetic will be
1228
      // eliminated altogether (or otherwise fail at preprocessing).
1229
3138
      || (logic.isTheoryEnabled(THEORY_ARITH) && !logic.isLinear()
1230
585
          && opts.smt.solveIntAsBV == 0)
1231
      // FP requires UF since there are multiple operators that are partially
1232
      // defined (see http://smtlib.cs.uiowa.edu/papers/BTRW15.pdf for more
1233
      // details).
1234
12481
      || logic.isTheoryEnabled(THEORY_FP))
1235
  {
1236
7441
    if (!logic.isTheoryEnabled(THEORY_UF))
1237
    {
1238
1848
      LogicInfo log(logic.getUnlockedCopy());
1239
924
      if (!needsUf)
1240
      {
1241
515
        Notice() << "Enabling UF because " << logic << " requires it."
1242
                 << std::endl;
1243
      }
1244
924
      log.enableTheory(THEORY_UF);
1245
924
      logic = log;
1246
924
      logic.lock();
1247
    }
1248
  }
1249
9928
  if (opts.arith.arithMLTrick)
1250
  {
1251
8
    if (!logic.areIntegersUsed())
1252
    {
1253
      // enable integers
1254
      LogicInfo log(logic.getUnlockedCopy());
1255
      Notice() << "Enabling integers because arithMLTrick requires it."
1256
               << std::endl;
1257
      log.enableIntegers();
1258
      logic = log;
1259
      logic.lock();
1260
    }
1261
  }
1262
9928
}
1263
1264
9928
void SetDefaults::setDefaultsQuantifiers(const LogicInfo& logic,
1265
                                         Options& opts) const
1266
{
1267
9928
  if (logic.hasCardinalityConstraints())
1268
  {
1269
    // must have finite model finding on
1270
26
    opts.quantifiers.finiteModelFind = true;
1271
  }
1272
1273
9928
  if (opts.quantifiers.instMaxLevel != -1)
1274
  {
1275
4
    Notice() << "SmtEngine: turning off cbqi to support instMaxLevel"
1276
             << std::endl;
1277
4
    opts.quantifiers.cegqi = false;
1278
  }
1279
1280
9928
  if ((opts.quantifiers.fmfBoundLazyWasSetByUser
1281
4
       && opts.quantifiers.fmfBoundLazy)
1282
9924
      || (opts.quantifiers.fmfBoundIntWasSetByUser
1283
14
          && opts.quantifiers.fmfBoundInt))
1284
  {
1285
18
    opts.quantifiers.fmfBound = true;
1286
36
    Trace("smt")
1287
18
        << "turning on fmf-bound, for fmf-bound-int or fmf-bound-lazy\n";
1288
  }
1289
  // now have determined whether fmfBound is on/off
1290
  // apply fmfBound options
1291
9928
  if (opts.quantifiers.fmfBound)
1292
  {
1293
79
    if (!opts.quantifiers.mbqiModeWasSetByUser
1294
        || (opts.quantifiers.mbqiMode != options::MbqiMode::NONE
1295
            && opts.quantifiers.mbqiMode != options::MbqiMode::FMC))
1296
    {
1297
      // if bounded integers are set, use no MBQI by default
1298
79
      opts.quantifiers.mbqiMode = options::MbqiMode::NONE;
1299
    }
1300
79
    if (!opts.quantifiers.prenexQuantUserWasSetByUser)
1301
    {
1302
79
      opts.quantifiers.prenexQuant = options::PrenexQuantMode::NONE;
1303
    }
1304
  }
1305
9928
  if (logic.isHigherOrder())
1306
  {
1307
    // if higher-order, then current variants of model-based instantiation
1308
    // cannot be used
1309
191
    if (opts.quantifiers.mbqiMode != options::MbqiMode::NONE)
1310
    {
1311
139
      opts.quantifiers.mbqiMode = options::MbqiMode::NONE;
1312
    }
1313
191
    if (!opts.quantifiers.hoElimStoreAxWasSetByUser)
1314
    {
1315
      // by default, use store axioms only if --ho-elim is set
1316
190
      opts.quantifiers.hoElimStoreAx = opts.quantifiers.hoElim;
1317
    }
1318
    // Cannot use macros, since lambda lifting and macro elimination are inverse
1319
    // operations.
1320
191
    if (opts.quantifiers.macrosQuant)
1321
    {
1322
      opts.quantifiers.macrosQuant = false;
1323
    }
1324
    // HOL is incompatible with fmfBound
1325
191
    if (opts.quantifiers.fmfBound)
1326
    {
1327
6
      if (opts.quantifiers.fmfBoundWasSetByUser
1328
4
          || opts.quantifiers.fmfBoundLazyWasSetByUser
1329
4
          || opts.quantifiers.fmfBoundIntWasSetByUser)
1330
      {
1331
6
        Notice() << "Disabling bound finite-model finding since it is "
1332
                    "incompatible with HOL.\n";
1333
      }
1334
1335
6
      opts.quantifiers.fmfBound = false;
1336
6
      Trace("smt") << "turning off fmf-bound, since HOL\n";
1337
    }
1338
  }
1339
9928
  if (opts.quantifiers.fmfFunWellDefinedRelevant)
1340
  {
1341
12
    if (!opts.quantifiers.fmfFunWellDefinedWasSetByUser)
1342
    {
1343
12
      opts.quantifiers.fmfFunWellDefined = true;
1344
    }
1345
  }
1346
9928
  if (opts.quantifiers.fmfFunWellDefined)
1347
  {
1348
71
    if (!opts.quantifiers.finiteModelFindWasSetByUser)
1349
    {
1350
69
      opts.quantifiers.finiteModelFind = true;
1351
    }
1352
  }
1353
1354
  // now, have determined whether finite model find is on/off
1355
  // apply finite model finding options
1356
9928
  if (opts.quantifiers.finiteModelFind)
1357
  {
1358
    // apply conservative quantifiers splitting
1359
288
    if (!opts.quantifiers.quantDynamicSplitWasSetByUser)
1360
    {
1361
288
      opts.quantifiers.quantDynamicSplit = options::QuantDSplitMode::DEFAULT;
1362
    }
1363
288
    if (!opts.quantifiers.eMatchingWasSetByUser)
1364
    {
1365
288
      opts.quantifiers.eMatching = opts.quantifiers.fmfInstEngine;
1366
    }
1367
288
    if (!opts.quantifiers.instWhenModeWasSetByUser)
1368
    {
1369
      // instantiate only on last call
1370
288
      if (opts.quantifiers.eMatching)
1371
      {
1372
8
        opts.quantifiers.instWhenMode = options::InstWhenMode::LAST_CALL;
1373
      }
1374
    }
1375
  }
1376
1377
  // apply sygus options
1378
  // if we are attempting to rewrite everything to SyGuS, use sygus()
1379
9928
  if (usesSygus(opts))
1380
  {
1381
682
    setDefaultsSygus(opts);
1382
  }
1383
  // counterexample-guided instantiation for non-sygus
1384
  // enable if any possible quantifiers with arithmetic, datatypes or bitvectors
1385
19856
  if ((logic.isQuantified()
1386
6839
       && (logic.isTheoryEnabled(THEORY_ARITH)
1387
310
           || logic.isTheoryEnabled(THEORY_DATATYPES)
1388
302
           || logic.isTheoryEnabled(THEORY_BV)
1389
114
           || logic.isTheoryEnabled(THEORY_FP)))
1390
13131
      || opts.quantifiers.cegqiAll)
1391
  {
1392
6725
    if (!opts.quantifiers.cegqiWasSetByUser)
1393
    {
1394
6702
      opts.quantifiers.cegqi = true;
1395
    }
1396
    // check whether we should apply full cbqi
1397
6725
    if (logic.isPure(THEORY_BV))
1398
    {
1399
152
      if (!opts.quantifiers.cegqiFullEffortWasSetByUser)
1400
      {
1401
60
        opts.quantifiers.cegqiFullEffort = true;
1402
      }
1403
    }
1404
  }
1405
9928
  if (opts.quantifiers.cegqi)
1406
  {
1407
6723
    if (logic.isPure(THEORY_ARITH) || logic.isPure(THEORY_BV))
1408
    {
1409
265
      if (!opts.quantifiers.quantConflictFindWasSetByUser)
1410
      {
1411
265
        opts.quantifiers.quantConflictFind = false;
1412
      }
1413
265
      if (!opts.quantifiers.instNoEntailWasSetByUser)
1414
      {
1415
265
        opts.quantifiers.instNoEntail = false;
1416
      }
1417
265
      if (!opts.quantifiers.instWhenModeWasSetByUser
1418
265
          && opts.quantifiers.cegqiModel)
1419
      {
1420
        // only instantiation should happen at last call when model is avaiable
1421
265
        opts.quantifiers.instWhenMode = options::InstWhenMode::LAST_CALL;
1422
      }
1423
    }
1424
    else
1425
    {
1426
      // only supported in pure arithmetic or pure BV
1427
6458
      opts.quantifiers.cegqiNestedQE = false;
1428
    }
1429
6723
    if (opts.quantifiers.globalNegate)
1430
    {
1431
6
      if (!opts.quantifiers.prenexQuantWasSetByUser)
1432
      {
1433
6
        opts.quantifiers.prenexQuant = options::PrenexQuantMode::NONE;
1434
      }
1435
    }
1436
  }
1437
  // implied options...
1438
9928
  if (opts.quantifiers.qcfModeWasSetByUser || opts.quantifiers.qcfTConstraint)
1439
  {
1440
8
    opts.quantifiers.quantConflictFind = true;
1441
  }
1442
9928
  if (opts.quantifiers.cegqiNestedQE)
1443
  {
1444
30
    opts.quantifiers.prenexQuantUser = true;
1445
30
    if (!opts.quantifiers.preSkolemQuantWasSetByUser)
1446
    {
1447
30
      opts.quantifiers.preSkolemQuant = true;
1448
    }
1449
  }
1450
  // for induction techniques
1451
9928
  if (opts.quantifiers.quantInduction)
1452
  {
1453
14
    if (!opts.quantifiers.dtStcInductionWasSetByUser)
1454
    {
1455
14
      opts.quantifiers.dtStcInduction = true;
1456
    }
1457
14
    if (!opts.quantifiers.intWfInductionWasSetByUser)
1458
    {
1459
14
      opts.quantifiers.intWfInduction = true;
1460
    }
1461
  }
1462
9928
  if (opts.quantifiers.dtStcInduction)
1463
  {
1464
    // try to remove ITEs from quantified formulas
1465
14
    if (!opts.quantifiers.iteDtTesterSplitQuantWasSetByUser)
1466
    {
1467
14
      opts.quantifiers.iteDtTesterSplitQuant = true;
1468
    }
1469
14
    if (!opts.quantifiers.iteLiftQuantWasSetByUser)
1470
    {
1471
14
      opts.quantifiers.iteLiftQuant = options::IteLiftQuantMode::ALL;
1472
    }
1473
  }
1474
9928
  if (opts.quantifiers.intWfInduction)
1475
  {
1476
20
    if (!opts.quantifiers.purifyTriggersWasSetByUser)
1477
    {
1478
20
      opts.quantifiers.purifyTriggers = true;
1479
    }
1480
  }
1481
9928
  if (opts.quantifiers.conjectureNoFilter)
1482
  {
1483
4
    if (!opts.quantifiers.conjectureFilterActiveTermsWasSetByUser)
1484
    {
1485
4
      opts.quantifiers.conjectureFilterActiveTerms = false;
1486
    }
1487
4
    if (!opts.quantifiers.conjectureFilterCanonicalWasSetByUser)
1488
    {
1489
4
      opts.quantifiers.conjectureFilterCanonical = false;
1490
    }
1491
4
    if (!opts.quantifiers.conjectureFilterModelWasSetByUser)
1492
    {
1493
      opts.quantifiers.conjectureFilterModel = false;
1494
    }
1495
  }
1496
9928
  if (opts.quantifiers.conjectureGenPerRoundWasSetByUser)
1497
  {
1498
    if (opts.quantifiers.conjectureGenPerRound > 0)
1499
    {
1500
      opts.quantifiers.conjectureGen = true;
1501
    }
1502
    else
1503
    {
1504
      opts.quantifiers.conjectureGen = false;
1505
    }
1506
  }
1507
  // can't pre-skolemize nested quantifiers without UF theory
1508
9928
  if (!logic.isTheoryEnabled(THEORY_UF) && opts.quantifiers.preSkolemQuant)
1509
  {
1510
30
    if (!opts.quantifiers.preSkolemQuantNestedWasSetByUser)
1511
    {
1512
30
      opts.quantifiers.preSkolemQuantNested = false;
1513
    }
1514
  }
1515
9928
  if (!logic.isTheoryEnabled(THEORY_DATATYPES))
1516
  {
1517
4390
    opts.quantifiers.quantDynamicSplit = options::QuantDSplitMode::NONE;
1518
  }
1519
9928
}
1520
1521
682
void SetDefaults::setDefaultsSygus(Options& opts) const
1522
{
1523
682
  if (!opts.quantifiers.sygus)
1524
  {
1525
333
    Trace("smt") << "turning on sygus" << std::endl;
1526
  }
1527
682
  opts.quantifiers.sygus = true;
1528
  // must use Ferrante/Rackoff for real arithmetic
1529
682
  if (!opts.quantifiers.cegqiMidpointWasSetByUser)
1530
  {
1531
682
    opts.quantifiers.cegqiMidpoint = true;
1532
  }
1533
  // must disable cegqi-bv since it may introduce witness terms, which
1534
  // cannot appear in synthesis solutions
1535
682
  if (!opts.quantifiers.cegqiBvWasSetByUser)
1536
  {
1537
679
    opts.quantifiers.cegqiBv = false;
1538
  }
1539
682
  if (opts.quantifiers.sygusRepairConst)
1540
  {
1541
160
    if (!opts.quantifiers.cegqiWasSetByUser)
1542
    {
1543
160
      opts.quantifiers.cegqi = true;
1544
    }
1545
  }
1546
682
  if (opts.quantifiers.sygusInference)
1547
  {
1548
    // optimization: apply preskolemization, makes it succeed more often
1549
57
    if (!opts.quantifiers.preSkolemQuantWasSetByUser)
1550
    {
1551
57
      opts.quantifiers.preSkolemQuant = true;
1552
    }
1553
57
    if (!opts.quantifiers.preSkolemQuantNestedWasSetByUser)
1554
    {
1555
57
      opts.quantifiers.preSkolemQuantNested = true;
1556
    }
1557
  }
1558
  // counterexample-guided instantiation for sygus
1559
682
  if (!opts.quantifiers.cegqiSingleInvModeWasSetByUser)
1560
  {
1561
574
    opts.quantifiers.cegqiSingleInvMode = options::CegqiSingleInvMode::USE;
1562
  }
1563
682
  if (!opts.quantifiers.quantConflictFindWasSetByUser)
1564
  {
1565
682
    opts.quantifiers.quantConflictFind = false;
1566
  }
1567
682
  if (!opts.quantifiers.instNoEntailWasSetByUser)
1568
  {
1569
682
    opts.quantifiers.instNoEntail = false;
1570
  }
1571
682
  if (!opts.quantifiers.cegqiFullEffortWasSetByUser)
1572
  {
1573
    // should use full effort cbqi for single invocation and repair const
1574
682
    opts.quantifiers.cegqiFullEffort = true;
1575
  }
1576
682
  if (opts.quantifiers.sygusRew)
1577
  {
1578
6
    opts.quantifiers.sygusRewSynth = true;
1579
6
    opts.quantifiers.sygusRewVerify = true;
1580
  }
1581
682
  if (opts.quantifiers.sygusRewSynthInput)
1582
  {
1583
    // If we are using synthesis rewrite rules from input, we use
1584
    // sygusRewSynth after preprocessing. See passes/synth_rew_rules.h for
1585
    // details on this technique.
1586
    opts.quantifiers.sygusRewSynth = true;
1587
    // we should not use the extended rewriter, since we are interested
1588
    // in rewrites that are not in the main rewriter
1589
    if (!opts.quantifiers.sygusExtRewWasSetByUser)
1590
    {
1591
      opts.quantifiers.sygusExtRew = false;
1592
    }
1593
  }
1594
  // Whether we must use "basic" sygus algorithms. A non-basic sygus algorithm
1595
  // is one that is specialized for returning a single solution. Non-basic
1596
  // sygus algorithms currently include the PBE solver, UNIF+PI, static
1597
  // template inference for invariant synthesis, and single invocation
1598
  // techniques.
1599
682
  bool reqBasicSygus = false;
1600
682
  if (opts.smt.produceAbducts)
1601
  {
1602
    // if doing abduction, we should filter strong solutions
1603
16
    if (!opts.quantifiers.sygusFilterSolModeWasSetByUser)
1604
    {
1605
16
      opts.quantifiers.sygusFilterSolMode = options::SygusFilterSolMode::STRONG;
1606
    }
1607
    // we must use basic sygus algorithms, since e.g. we require checking
1608
    // a sygus side condition for consistency with axioms.
1609
16
    reqBasicSygus = true;
1610
  }
1611
682
  if (opts.quantifiers.sygusRewSynth || opts.quantifiers.sygusRewVerify
1612
675
      || opts.quantifiers.sygusQueryGen)
1613
  {
1614
    // rewrite rule synthesis implies that sygus stream must be true
1615
7
    opts.quantifiers.sygusStream = true;
1616
  }
1617
682
  if (opts.quantifiers.sygusStream || opts.base.incrementalSolving)
1618
  {
1619
    // Streaming and incremental mode are incompatible with techniques that
1620
    // focus the search towards finding a single solution.
1621
17
    reqBasicSygus = true;
1622
  }
1623
  // Now, disable options for non-basic sygus algorithms, if necessary.
1624
682
  if (reqBasicSygus)
1625
  {
1626
31
    if (!opts.quantifiers.sygusUnifPbeWasSetByUser)
1627
    {
1628
31
      opts.quantifiers.sygusUnifPbe = false;
1629
    }
1630
31
    if (opts.quantifiers.sygusUnifPiWasSetByUser)
1631
    {
1632
      opts.quantifiers.sygusUnifPi = options::SygusUnifPiMode::NONE;
1633
    }
1634
31
    if (!opts.quantifiers.sygusInvTemplModeWasSetByUser)
1635
    {
1636
31
      opts.quantifiers.sygusInvTemplMode = options::SygusInvTemplMode::NONE;
1637
    }
1638
31
    if (!opts.quantifiers.cegqiSingleInvModeWasSetByUser)
1639
    {
1640
31
      opts.quantifiers.cegqiSingleInvMode = options::CegqiSingleInvMode::NONE;
1641
    }
1642
  }
1643
  // do not miniscope
1644
682
  if (!opts.quantifiers.miniscopeQuantWasSetByUser)
1645
  {
1646
530
    opts.quantifiers.miniscopeQuant = false;
1647
  }
1648
682
  if (!opts.quantifiers.miniscopeQuantFreeVarWasSetByUser)
1649
  {
1650
532
    opts.quantifiers.miniscopeQuantFreeVar = false;
1651
  }
1652
682
  if (!opts.quantifiers.quantSplitWasSetByUser)
1653
  {
1654
532
    opts.quantifiers.quantSplit = false;
1655
  }
1656
  // do not do macros
1657
682
  if (!opts.quantifiers.macrosQuantWasSetByUser)
1658
  {
1659
682
    opts.quantifiers.macrosQuant = false;
1660
  }
1661
682
}
1662
9928
void SetDefaults::setDefaultDecisionMode(const LogicInfo& logic,
1663
                                         Options& opts) const
1664
{
1665
  // Set decision mode based on logic (if not set by user)
1666
9928
  if (opts.decision.decisionModeWasSetByUser)
1667
  {
1668
136
    return;
1669
  }
1670
  options::DecisionMode decMode =
1671
      // anything that uses sygus uses internal
1672
18918
      usesSygus(opts) ? options::DecisionMode::INTERNAL :
1673
                      // ALL or its supersets
1674
9126
          logic.hasEverything()
1675
14281
              ? options::DecisionMode::JUSTIFICATION
1676
              : (  // QF_BV
1677
12622
                    (not logic.isQuantified() && logic.isPure(THEORY_BV)) ||
1678
                            // QF_AUFBV or QF_ABV or QF_UFBV
1679
4428
                            (not logic.isQuantified()
1680
2312
                             && (logic.isTheoryEnabled(THEORY_ARRAYS)
1681
1878
                                 || logic.isTheoryEnabled(THEORY_UF))
1682
1557
                             && logic.isTheoryEnabled(THEORY_BV))
1683
4003
                            ||
1684
                            // QF_AUFLIA (and may be ends up enabling
1685
                            // QF_AUFLRA?)
1686
4003
                            (not logic.isQuantified()
1687
1887
                             && logic.isTheoryEnabled(THEORY_ARRAYS)
1688
174
                             && logic.isTheoryEnabled(THEORY_UF)
1689
174
                             && logic.isTheoryEnabled(THEORY_ARITH))
1690
3933
                            ||
1691
                            // QF_LRA
1692
3933
                            (not logic.isQuantified()
1693
1817
                             && logic.isPure(THEORY_ARITH) && logic.isLinear()
1694
729
                             && !logic.isDifferenceLogic()
1695
712
                             && !logic.areIntegersUsed())
1696
3685
                            ||
1697
                            // Quantifiers
1698
5254
                            logic.isQuantified() ||
1699
                            // Strings
1700
1569
                            logic.isTheoryEnabled(THEORY_STRINGS)
1701
8741
                        ? options::DecisionMode::JUSTIFICATION
1702
9792
                        : options::DecisionMode::INTERNAL);
1703
1704
  bool stoponly =
1705
      // ALL or its supersets
1706
15468
      logic.hasEverything() || logic.isTheoryEnabled(THEORY_STRINGS)
1707
15316
          ? false
1708
          : (  // QF_AUFLIA
1709
5108
                (not logic.isQuantified()
1710
3039
                 && logic.isTheoryEnabled(THEORY_ARRAYS)
1711
434
                 && logic.isTheoryEnabled(THEORY_UF)
1712
434
                 && logic.isTheoryEnabled(THEORY_ARITH))
1713
                        ||
1714
                        // QF_LRA
1715
7811
                        (not logic.isQuantified() && logic.isPure(THEORY_ARITH)
1716
729
                         && logic.isLinear() && !logic.isDifferenceLogic()
1717
712
                         && !logic.areIntegersUsed())
1718
4940
                    ? true
1719
9792
                    : false);
1720
1721
9792
  opts.decision.decisionMode = decMode;
1722
9792
  if (stoponly)
1723
  {
1724
416
    if (opts.decision.decisionMode == options::DecisionMode::JUSTIFICATION)
1725
    {
1726
416
      opts.decision.decisionMode = options::DecisionMode::STOPONLY;
1727
    }
1728
    else
1729
    {
1730
      Assert(opts.decision.decisionMode == options::DecisionMode::INTERNAL);
1731
    }
1732
  }
1733
19584
  Trace("smt") << "setting decision mode to " << opts.decision.decisionMode
1734
9792
               << std::endl;
1735
}
1736
1737
}  // namespace smt
1738
29505
}  // namespace cvc5