GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/set_defaults.cpp Lines: 647 807 80.2 %
Date: 2021-09-06 Branches: 929 1644 56.5 %

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