GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/nonlinear_extension.cpp Lines: 285 319 89.3 %
Date: 2021-05-22 Branches: 487 966 50.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Gereon Kremer, Tim King
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
 * [[ Add one-line brief description here ]]
14
 *
15
 * [[ Add lengthier description here ]]
16
 * \todo document this file
17
 */
18
19
#include "theory/arith/nl/nonlinear_extension.h"
20
21
#include "options/arith_options.h"
22
#include "theory/arith/arith_state.h"
23
#include "theory/arith/bound_inference.h"
24
#include "theory/arith/inference_manager.h"
25
#include "theory/arith/nl/nl_lemma_utils.h"
26
#include "theory/arith/theory_arith.h"
27
#include "theory/ext_theory.h"
28
#include "theory/rewriter.h"
29
#include "theory/theory_model.h"
30
31
using namespace cvc5::kind;
32
33
namespace cvc5 {
34
namespace theory {
35
namespace arith {
36
namespace nl {
37
38
4914
NonlinearExtension::NonlinearExtension(TheoryArith& containing,
39
                                       ArithState& state,
40
                                       eq::EqualityEngine* ee,
41
4914
                                       ProofNodeManager* pnm)
42
    : d_containing(containing),
43
4914
      d_im(containing.getInferenceManager()),
44
      d_needsLastCall(false),
45
      d_checkCounter(0),
46
      d_extTheoryCb(ee),
47
      d_extTheory(d_extTheoryCb,
48
                  containing.getSatContext(),
49
                  containing.getUserContext(),
50
                  containing.getOutputChannel()),
51
      d_model(containing.getSatContext()),
52
      d_trSlv(d_im, d_model, pnm, containing.getUserContext()),
53
      d_extState(d_im, d_model, pnm, containing.getUserContext()),
54
      d_factoringSlv(&d_extState),
55
      d_monomialBoundsSlv(&d_extState),
56
      d_monomialSlv(&d_extState),
57
      d_splitZeroSlv(&d_extState),
58
      d_tangentPlaneSlv(&d_extState),
59
4914
      d_cadSlv(d_im, d_model, state.getUserContext(), pnm),
60
      d_icpSlv(d_im),
61
14742
      d_iandSlv(d_im, state, d_model)
62
{
63
4914
  d_extTheory.addFunctionKind(kind::NONLINEAR_MULT);
64
4914
  d_extTheory.addFunctionKind(kind::EXPONENTIAL);
65
4914
  d_extTheory.addFunctionKind(kind::SINE);
66
4914
  d_extTheory.addFunctionKind(kind::PI);
67
4914
  d_extTheory.addFunctionKind(kind::IAND);
68
4914
  d_true = NodeManager::currentNM()->mkConst(true);
69
4914
  d_zero = NodeManager::currentNM()->mkConst(Rational(0));
70
4914
  d_one = NodeManager::currentNM()->mkConst(Rational(1));
71
4914
  d_neg_one = NodeManager::currentNM()->mkConst(Rational(-1));
72
73
4914
  ProofChecker* pc = pnm != nullptr ? pnm->getChecker() : nullptr;
74
4914
  if (pc != nullptr)
75
  {
76
543
    d_proofChecker.registerTo(pc);
77
  }
78
4914
}
79
80
4914
NonlinearExtension::~NonlinearExtension() {}
81
82
376529
void NonlinearExtension::preRegisterTerm(TNode n)
83
{
84
  // register terms with extended theory, to find extended terms that can be
85
  // eliminated by context-depedendent simplification.
86
376529
  d_extTheory.registerTerm(n);
87
376529
}
88
89
void NonlinearExtension::processSideEffect(const NlLemma& se)
90
{
91
  d_trSlv.processSideEffect(se);
92
}
93
94
void NonlinearExtension::computeRelevantAssertions(
95
    const std::vector<Node>& assertions, std::vector<Node>& keep)
96
{
97
  Trace("nl-ext-rlv") << "Compute relevant assertions..." << std::endl;
98
  Valuation v = d_containing.getValuation();
99
  for (const Node& a : assertions)
100
  {
101
    if (v.isRelevant(a))
102
    {
103
      keep.push_back(a);
104
    }
105
  }
106
  Trace("nl-ext-rlv") << "...keep " << keep.size() << "/" << assertions.size()
107
                      << " assertions" << std::endl;
108
}
109
110
3031
void NonlinearExtension::getAssertions(std::vector<Node>& assertions)
111
{
112
3031
  Trace("nl-ext-assert-debug") << "Getting assertions..." << std::endl;
113
3031
  bool useRelevance = false;
114
3031
  if (options::nlRlvMode() == options::NlRlvMode::INTERLEAVE)
115
  {
116
558
    useRelevance = (d_checkCounter % 2);
117
  }
118
2473
  else if (options::nlRlvMode() == options::NlRlvMode::ALWAYS)
119
  {
120
44
    useRelevance = true;
121
  }
122
3031
  Valuation v = d_containing.getValuation();
123
124
6062
  BoundInference bounds;
125
126
6062
  std::unordered_set<Node> init_assertions;
127
128
321045
  for (Theory::assertions_iterator it = d_containing.facts_begin();
129
321045
       it != d_containing.facts_end();
130
       ++it)
131
  {
132
318014
    const Assertion& assertion = *it;
133
636028
    Trace("nl-ext-assert-debug")
134
318014
        << "Loaded " << assertion.d_assertion << " from theory" << std::endl;
135
366021
    Node lit = assertion.d_assertion;
136
318014
    if (useRelevance && !v.isRelevant(lit))
137
    {
138
      // not relevant, skip
139
1714
      continue;
140
    }
141
316300
    if (bounds.add(lit, false))
142
    {
143
268293
      continue;
144
    }
145
48007
    init_assertions.insert(lit);
146
  }
147
148
143347
  for (const auto& vb : bounds.get())
149
  {
150
140316
    const Bounds& b = vb.second;
151
140316
    if (!b.lower_bound.isNull())
152
    {
153
95024
      init_assertions.insert(b.lower_bound);
154
    }
155
140316
    if (!b.upper_bound.isNull())
156
    {
157
79461
      init_assertions.insert(b.upper_bound);
158
    }
159
  }
160
161
  // Try to be "more deterministic" by adding assertions in the order they were
162
  // given
163
321045
  for (auto it = d_containing.facts_begin(); it != d_containing.facts_end();
164
       ++it)
165
  {
166
636028
    Node lit = (*it).d_assertion;
167
318014
    auto iait = init_assertions.find(lit);
168
318014
    if (iait != init_assertions.end())
169
    {
170
190754
      Trace("nl-ext-assert-debug") << "Adding " << lit << std::endl;
171
190754
      assertions.push_back(lit);
172
190754
      init_assertions.erase(iait);
173
    }
174
  }
175
  // Now add left over assertions that have been newly created within this
176
  // function by the code above.
177
6259
  for (const Node& a : init_assertions)
178
  {
179
3228
    Trace("nl-ext-assert-debug") << "Adding " << a << std::endl;
180
3228
    assertions.push_back(a);
181
  }
182
6062
  Trace("nl-ext") << "...keep " << assertions.size() << " / "
183
6062
                  << d_containing.numAssertions() << " assertions."
184
3031
                  << std::endl;
185
3031
}
186
187
3031
std::vector<Node> NonlinearExtension::checkModelEval(
188
    const std::vector<Node>& assertions)
189
{
190
3031
  std::vector<Node> false_asserts;
191
197013
  for (size_t i = 0; i < assertions.size(); ++i)
192
  {
193
387964
    Node lit = assertions[i];
194
387964
    Node atom = lit.getKind() == NOT ? lit[0] : lit;
195
387964
    Node litv = d_model.computeConcreteModelValue(lit);
196
193982
    Trace("nl-ext-mv-assert") << "M[[ " << lit << " ]] -> " << litv;
197
193982
    if (litv != d_true)
198
    {
199
39881
      Trace("nl-ext-mv-assert") << " [model-false]" << std::endl;
200
39881
      false_asserts.push_back(lit);
201
    }
202
    else
203
    {
204
154101
      Trace("nl-ext-mv-assert") << std::endl;
205
    }
206
  }
207
3031
  return false_asserts;
208
}
209
210
249
bool NonlinearExtension::checkModel(const std::vector<Node>& assertions)
211
{
212
249
  Trace("nl-ext-cm") << "--- check-model ---" << std::endl;
213
214
  // get the presubstitution
215
249
  Trace("nl-ext-cm-debug") << "  apply pre-substitution..." << std::endl;
216
  // Notice that we do not consider relevance here, since assertions were
217
  // already filtered based on relevance. It is incorrect to filter based on
218
  // relevance here, since we may have discarded literals that are relevant
219
  // that are entailed based on the techniques in getAssertions.
220
498
  std::vector<Node> passertions = assertions;
221
249
  if (options::nlExt() == options::NlExtMode::FULL)
222
  {
223
    // preprocess the assertions with the trancendental solver
224
232
    if (!d_trSlv.preprocessAssertionsCheckModel(passertions))
225
    {
226
      return false;
227
    }
228
  }
229
249
  if (options::nlCad())
230
  {
231
17
    d_cadSlv.constructModelIfAvailable(passertions);
232
  }
233
234
249
  Trace("nl-ext-cm") << "-----" << std::endl;
235
249
  unsigned tdegree = d_trSlv.getTaylorDegree();
236
498
  std::vector<NlLemma> lemmas;
237
249
  bool ret = d_model.checkModel(passertions, tdegree, lemmas);
238
249
  for (const auto& al: lemmas)
239
  {
240
    d_im.addPendingLemma(al);
241
  }
242
249
  return ret;
243
}
244
245
29453
void NonlinearExtension::check(Theory::Effort e)
246
{
247
29453
  d_im.reset();
248
29453
  Trace("nl-ext") << std::endl;
249
29453
  Trace("nl-ext") << "NonlinearExtension::check, effort = " << e << std::endl;
250
29453
  if (e == Theory::EFFORT_FULL)
251
  {
252
26424
    d_needsLastCall = true;
253
52848
    if (options::nlExtRewrites())
254
    {
255
52848
      std::vector<Node> nred;
256
26424
      if (!d_extTheory.doInferences(0, nred))
257
      {
258
51776
        Trace("nl-ext") << "...sent no lemmas, # extf to reduce = "
259
25888
                        << nred.size() << std::endl;
260
25888
        if (nred.empty())
261
        {
262
22457
          d_needsLastCall = false;
263
        }
264
      }
265
      else
266
      {
267
536
        Trace("nl-ext") << "...sent lemmas." << std::endl;
268
      }
269
    }
270
  }
271
  else
272
  {
273
    // If we computed lemmas during collectModelInfo, send them now.
274
3029
    if (d_im.hasPendingLemma())
275
    {
276
2753
      d_im.doPendingFacts();
277
2753
      d_im.doPendingLemmas();
278
2753
      d_im.doPendingPhaseRequirements();
279
2753
      return;
280
    }
281
    // Otherwise, we will answer SAT. The values that we approximated are
282
    // recorded as approximations here.
283
276
    TheoryModel* tm = d_containing.getValuation().getModel();
284
304
    for (std::pair<const Node, std::pair<Node, Node>>& a : d_approximations)
285
    {
286
28
      if (a.second.second.isNull())
287
      {
288
28
        tm->recordApproximation(a.first, a.second.first);
289
      }
290
      else
291
      {
292
        tm->recordApproximation(a.first, a.second.first, a.second.second);
293
      }
294
    }
295
283
    for (const auto& vw : d_witnesses)
296
    {
297
7
      tm->recordApproximation(vw.first, vw.second);
298
    }
299
  }
300
}
301
302
3031
Result::Sat NonlinearExtension::modelBasedRefinement(const std::set<Node>& termSet)
303
{
304
3031
  ++(d_stats.d_mbrRuns);
305
3031
  d_checkCounter++;
306
307
  // get the assertions
308
6062
  std::vector<Node> assertions;
309
3031
  getAssertions(assertions);
310
311
6062
  Trace("nl-ext-mv-assert")
312
3031
      << "Getting model values... check for [model-false]" << std::endl;
313
  // get the assertions that are false in the model
314
6062
  const std::vector<Node> false_asserts = checkModelEval(assertions);
315
3031
  Trace("nl-ext") << "# false asserts = " << false_asserts.size() << std::endl;
316
317
  // get the extended terms belonging to this theory
318
6062
  std::vector<Node> xtsAll;
319
3031
  d_extTheory.getTerms(xtsAll);
320
  // only consider those that are currently relevant based on the current
321
  // assertions, i.e. those contained in termSet
322
6062
  std::vector<Node> xts;
323
26486
  for (const Node& x : xtsAll)
324
  {
325
23455
    if (termSet.find(x) != termSet.end())
326
    {
327
22784
      xts.push_back(x);
328
    }
329
  }
330
331
3031
  if (Trace.isOn("nl-ext-debug"))
332
  {
333
    Trace("nl-ext-debug") << "  processing NonlinearExtension::check : "
334
                          << std::endl;
335
    Trace("nl-ext-debug") << "     " << false_asserts.size()
336
                          << " false assertions" << std::endl;
337
    Trace("nl-ext-debug") << "     " << xts.size()
338
                          << " extended terms: " << std::endl;
339
    Trace("nl-ext-debug") << "       ";
340
    for (unsigned j = 0; j < xts.size(); j++)
341
    {
342
      Trace("nl-ext-debug") << xts[j] << " ";
343
    }
344
    Trace("nl-ext-debug") << std::endl;
345
  }
346
347
  // compute whether shared terms have correct values
348
3031
  unsigned num_shared_wrong_value = 0;
349
6062
  std::vector<Node> shared_term_value_splits;
350
  // must ensure that shared terms are equal to their concrete value
351
3031
  Trace("nl-ext-mv") << "Shared terms : " << std::endl;
352
15050
  for (context::CDList<TNode>::const_iterator its =
353
3031
           d_containing.shared_terms_begin();
354
18081
       its != d_containing.shared_terms_end();
355
       ++its)
356
  {
357
30100
    TNode shared_term = *its;
358
    // compute its value in the model, and its evaluation in the model
359
30100
    Node stv0 = d_model.computeConcreteModelValue(shared_term);
360
30100
    Node stv1 = d_model.computeAbstractModelValue(shared_term);
361
15050
    d_model.printModelValue("nl-ext-mv", shared_term);
362
15050
    if (stv0 != stv1)
363
    {
364
925
      num_shared_wrong_value++;
365
1850
      Trace("nl-ext-mv") << "Bad shared term value : " << shared_term
366
925
                         << std::endl;
367
925
      if (shared_term != stv0)
368
      {
369
        // split on the value, this is non-terminating in general, TODO :
370
        // improve this
371
1818
        Node eq = shared_term.eqNode(stv0);
372
909
        shared_term_value_splits.push_back(eq);
373
      }
374
      else
375
      {
376
        // this can happen for transcendental functions
377
        // the problem is that we cannot evaluate transcendental functions
378
        // (they don't have a rewriter that returns constants)
379
        // thus, the actual value in their model can be themselves, hence we
380
        // have no reference point to rule out the current model.  In this
381
        // case, we may set incomplete below.
382
      }
383
    }
384
  }
385
6062
  Trace("nl-ext-debug") << "     " << num_shared_wrong_value
386
3031
                        << " shared terms with wrong model value." << std::endl;
387
  bool needsRecheck;
388
306
  do
389
  {
390
3047
    d_model.resetCheck();
391
3047
    needsRecheck = false;
392
    // complete_status:
393
    //   1 : we may answer SAT, -1 : we may not answer SAT, 0 : unknown
394
3047
    int complete_status = 1;
395
    // We require a check either if an assertion is false or a shared term has
396
    // a wrong value
397
3047
    if (!false_asserts.empty() || num_shared_wrong_value > 0)
398
    {
399
2841
      complete_status = num_shared_wrong_value > 0 ? -1 : 0;
400
2841
      runStrategy(Theory::Effort::EFFORT_FULL, assertions, false_asserts, xts);
401
2841
      if (d_im.hasSentLemma() || d_im.hasPendingLemma())
402
      {
403
2574
        d_im.clearWaitingLemmas();
404
5331
        return Result::Sat::UNSAT;
405
      }
406
    }
407
946
    Trace("nl-ext") << "Finished check with status : " << complete_status
408
473
                    << std::endl;
409
410
    // if we did not add a lemma during check and there is a chance for SAT
411
473
    if (complete_status == 0)
412
    {
413
498
      Trace("nl-ext")
414
249
          << "Check model based on bounds for irrational-valued functions..."
415
249
          << std::endl;
416
      // check the model based on simple solving of equalities and using
417
      // error bounds on the Taylor approximation of transcendental functions.
418
249
      if (checkModel(assertions))
419
      {
420
68
        complete_status = 1;
421
      }
422
249
      if (d_im.hasUsed())
423
      {
424
        d_im.clearWaitingLemmas();
425
        return Result::Sat::UNSAT;
426
      }
427
    }
428
429
    // if we have not concluded SAT
430
473
    if (complete_status != 1)
431
    {
432
      // flush the waiting lemmas
433
199
      if (d_im.hasWaitingLemma())
434
      {
435
165
        std::size_t count = d_im.numWaitingLemmas();
436
165
        d_im.flushWaitingLemmas();
437
330
        Trace("nl-ext") << "...added " << count << " waiting lemmas."
438
165
                        << std::endl;
439
165
        return Result::Sat::UNSAT;
440
      }
441
      // resort to splitting on shared terms with their model value
442
      // if we did not add any lemmas
443
34
      if (num_shared_wrong_value > 0)
444
      {
445
18
        complete_status = -1;
446
18
        if (!shared_term_value_splits.empty())
447
        {
448
88
          for (const Node& eq : shared_term_value_splits)
449
          {
450
144
            Node req = Rewriter::rewrite(eq);
451
144
            Node literal = d_containing.getValuation().ensureLiteral(req);
452
72
            d_containing.getOutputChannel().requirePhase(literal, true);
453
72
            Trace("nl-ext-debug") << "Split on : " << literal << std::endl;
454
144
            Node split = literal.orNode(literal.negate());
455
72
            d_im.addPendingLemma(split,
456
                                 InferenceId::ARITH_NL_SHARED_TERM_VALUE_SPLIT,
457
                                 nullptr,
458
                                 true);
459
          }
460
16
          if (d_im.hasWaitingLemma())
461
          {
462
14
            d_im.flushWaitingLemmas();
463
28
            Trace("nl-ext") << "...added " << d_im.numPendingLemmas()
464
14
                            << " shared term value split lemmas." << std::endl;
465
14
            return Result::Sat::UNSAT;
466
          }
467
        }
468
        else
469
        {
470
          // this can happen if we are trying to do theory combination with
471
          // trancendental functions
472
          // since their model value cannot even be computed exactly
473
        }
474
      }
475
476
      // we are incomplete
477
40
      if (options::nlExt() == options::NlExtMode::FULL
478
40
          && options::nlExtIncPrecision() && d_model.usedApproximate())
479
      {
480
16
        d_trSlv.incrementTaylorDegree();
481
16
        needsRecheck = true;
482
        // increase precision for PI?
483
        // Difficult since Taylor series is very slow to converge
484
32
        Trace("nl-ext") << "...increment Taylor degree to "
485
16
                        << d_trSlv.getTaylorDegree() << std::endl;
486
      }
487
      else
488
      {
489
8
        Trace("nl-ext") << "...failed to send lemma in "
490
4
                           "NonLinearExtension, set incomplete"
491
4
                        << std::endl;
492
4
        d_containing.getOutputChannel().setIncomplete(IncompleteId::ARITH_NL);
493
4
        return Result::Sat::SAT_UNKNOWN;
494
      }
495
    }
496
290
    d_im.clearWaitingLemmas();
497
  } while (needsRecheck);
498
499
  // did not add lemmas
500
274
  return Result::Sat::SAT;
501
}
502
503
8496
void NonlinearExtension::interceptModel(std::map<Node, Node>& arithModel,
504
                                        const std::set<Node>& termSet)
505
{
506
8496
  if (!needsCheckLastEffort())
507
  {
508
    // no non-linear constraints, we are done
509
5465
    return;
510
  }
511
3031
  Trace("nl-ext") << "NonlinearExtension::interceptModel begin" << std::endl;
512
3031
  d_model.reset(d_containing.getValuation().getModel(), arithModel);
513
  // run a last call effort check
514
3031
  Trace("nl-ext") << "interceptModel: do model-based refinement" << std::endl;
515
3031
  Result::Sat res = modelBasedRefinement(termSet);
516
3031
  if (res == Result::Sat::SAT)
517
  {
518
274
    Trace("nl-ext") << "interceptModel: do model repair" << std::endl;
519
274
    d_approximations.clear();
520
274
    d_witnesses.clear();
521
    // modify the model values
522
274
    d_model.getModelValueRepair(arithModel, d_approximations, d_witnesses);
523
  }
524
}
525
526
5753
void NonlinearExtension::presolve()
527
{
528
5753
  Trace("nl-ext") << "NonlinearExtension::presolve" << std::endl;
529
5753
}
530
531
2841
void NonlinearExtension::runStrategy(Theory::Effort effort,
532
                                     const std::vector<Node>& assertions,
533
                                     const std::vector<Node>& false_asserts,
534
                                     const std::vector<Node>& xts)
535
{
536
2841
  ++(d_stats.d_checkRuns);
537
538
2841
  if (Trace.isOn("nl-strategy"))
539
  {
540
    for (const auto& a : assertions)
541
    {
542
      Trace("nl-strategy") << "Input assertion: " << a << std::endl;
543
    }
544
  }
545
2841
  if (!d_strategy.isStrategyInit())
546
  {
547
437
    d_strategy.initializeStrategy();
548
  }
549
550
2841
  auto steps = d_strategy.getStrategy();
551
2841
  bool stop = false;
552
85595
  while (!stop && steps.hasNext())
553
  {
554
41377
    InferStep step = steps.next();
555
41377
    Trace("nl-strategy") << "Step " << step << std::endl;
556
41377
    switch (step)
557
    {
558
19400
      case InferStep::BREAK: stop = d_im.hasPendingLemma(); break;
559
363
      case InferStep::FLUSH_WAITING_LEMMAS: d_im.flushWaitingLemmas(); break;
560
47
      case InferStep::CAD_FULL: d_cadSlv.checkFull(); break;
561
47
      case InferStep::CAD_INIT: d_cadSlv.initLastCall(assertions); break;
562
262
      case InferStep::NL_FACTORING:
563
262
        d_factoringSlv.check(assertions, false_asserts);
564
262
        break;
565
2511
      case InferStep::IAND_INIT:
566
2511
        d_iandSlv.initLastCall(assertions, false_asserts, xts);
567
2511
        break;
568
281
      case InferStep::IAND_FULL: d_iandSlv.checkFullRefine(); break;
569
2511
      case InferStep::IAND_INITIAL: d_iandSlv.checkInitialRefine(); break;
570
32
      case InferStep::ICP:
571
32
        d_icpSlv.reset(assertions);
572
32
        d_icpSlv.check();
573
32
        break;
574
2829
      case InferStep::NL_INIT:
575
2829
        d_extState.init(xts);
576
2829
        d_monomialBoundsSlv.init();
577
2829
        d_monomialSlv.init(xts);
578
2829
        break;
579
528
      case InferStep::NL_MONOMIAL_INFER_BOUNDS:
580
528
        d_monomialBoundsSlv.checkBounds(assertions, false_asserts);
581
528
        break;
582
1608
      case InferStep::NL_MONOMIAL_MAGNITUDE0:
583
1608
        d_monomialSlv.checkMagnitude(0);
584
1608
        break;
585
1075
      case InferStep::NL_MONOMIAL_MAGNITUDE1:
586
1075
        d_monomialSlv.checkMagnitude(1);
587
1075
        break;
588
783
      case InferStep::NL_MONOMIAL_MAGNITUDE2:
589
783
        d_monomialSlv.checkMagnitude(2);
590
783
        break;
591
2436
      case InferStep::NL_MONOMIAL_SIGN: d_monomialSlv.checkSign(); break;
592
      case InferStep::NL_RESOLUTION_BOUNDS:
593
        d_monomialBoundsSlv.checkResBounds();
594
        break;
595
      case InferStep::NL_SPLIT_ZERO: d_splitZeroSlv.check(); break;
596
      case InferStep::NL_TANGENT_PLANES: d_tangentPlaneSlv.check(false); break;
597
21
      case InferStep::NL_TANGENT_PLANES_WAITING:
598
21
        d_tangentPlaneSlv.check(true);
599
21
        break;
600
2736
      case InferStep::TRANS_INIT:
601
2736
        d_trSlv.initLastCall(xts);
602
2736
        break;
603
2569
      case InferStep::TRANS_INITIAL:
604
2569
        d_trSlv.checkTranscendentalInitialRefine();
605
2569
        break;
606
1106
      case InferStep::TRANS_MONOTONIC:
607
1106
        d_trSlv.checkTranscendentalMonotonic();
608
1106
        break;
609
232
      case InferStep::TRANS_TANGENT_PLANES:
610
232
        d_trSlv.checkTranscendentalTangentPlanes();
611
232
        break;
612
    }
613
  }
614
615
2841
  Trace("nl-ext") << "finished strategy" << std::endl;
616
5682
  Trace("nl-ext") << "  ...finished with " << d_im.numWaitingLemmas()
617
2841
                  << " waiting lemmas." << std::endl;
618
5682
  Trace("nl-ext") << "  ...finished with " << d_im.numPendingLemmas()
619
2841
                  << " pending lemmas." << std::endl;
620
2841
}
621
622
}  // namespace nl
623
}  // namespace arith
624
}  // namespace theory
625
28191
}  // namespace cvc5