GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/set_defaults.cpp Lines: 658 827 79.6 %
Date: 2021-11-05 Branches: 951 1664 57.2 %

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