GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/set_defaults.cpp Lines: 593 727 81.6 %
Date: 2021-08-16 Branches: 976 1780 54.8 %

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