GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/instantiate.cpp Lines: 278 347 80.1 %
Date: 2021-11-07 Branches: 537 1402 38.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tim King, Morgan Deters
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 instantiate.
14
 */
15
16
#include "theory/quantifiers/instantiate.h"
17
18
#include "expr/node_algorithm.h"
19
#include "options/base_options.h"
20
#include "options/printer_options.h"
21
#include "options/quantifiers_options.h"
22
#include "options/smt_options.h"
23
#include "proof/lazy_proof.h"
24
#include "proof/proof_node_manager.h"
25
#include "smt/logic_exception.h"
26
#include "smt/smt_statistics_registry.h"
27
#include "theory/quantifiers/cegqi/inst_strategy_cegqi.h"
28
#include "theory/quantifiers/entailment_check.h"
29
#include "theory/quantifiers/first_order_model.h"
30
#include "theory/quantifiers/quantifiers_attributes.h"
31
#include "theory/quantifiers/quantifiers_preprocess.h"
32
#include "theory/quantifiers/term_database.h"
33
#include "theory/quantifiers/term_enumeration.h"
34
#include "theory/quantifiers/term_registry.h"
35
#include "theory/quantifiers/term_util.h"
36
#include "theory/rewriter.h"
37
38
using namespace cvc5::kind;
39
using namespace cvc5::context;
40
41
namespace cvc5 {
42
namespace theory {
43
namespace quantifiers {
44
45
15273
Instantiate::Instantiate(Env& env,
46
                         QuantifiersState& qs,
47
                         QuantifiersInferenceManager& qim,
48
                         QuantifiersRegistry& qr,
49
15273
                         TermRegistry& tr)
50
    : QuantifiersUtil(env),
51
      d_qstate(qs),
52
      d_qim(qim),
53
      d_qreg(qr),
54
      d_treg(tr),
55
15273
      d_insts(userContext()),
56
15273
      d_c_inst_match_trie_dom(userContext()),
57
20645
      d_pfInst(isProofEnabled() ? new CDProof(env.getProofNodeManager(),
58
5372
                                              userContext(),
59
5372
                                              "Instantiate::pfInst")
60
71836
                                : nullptr)
61
{
62
15273
}
63
64
45804
Instantiate::~Instantiate()
65
{
66
15977
  for (std::pair<const Node, CDInstMatchTrie*>& t : d_c_inst_match_trie)
67
  {
68
709
    delete t.second;
69
  }
70
15268
  d_c_inst_match_trie.clear();
71
30536
}
72
73
34975
bool Instantiate::reset(Theory::Effort e)
74
{
75
34975
  Trace("inst-debug") << "Reset, effort " << e << std::endl;
76
  // clear explicitly recorded instantiations
77
34975
  d_recordedInst.clear();
78
34975
  d_instDebugTemp.clear();
79
34975
  return true;
80
}
81
82
26099
void Instantiate::registerQuantifier(Node q) {}
83
5540
bool Instantiate::checkComplete(IncompleteId& incId)
84
{
85
5540
  if (!d_recordedInst.empty())
86
  {
87
2
    Trace("quant-engine-debug")
88
1
        << "Set incomplete due to recorded instantiations." << std::endl;
89
1
    incId = IncompleteId::QUANTIFIERS_RECORDED_INST;
90
1
    return false;
91
  }
92
5539
  return true;
93
}
94
95
12031
void Instantiate::addRewriter(InstantiationRewriter* ir)
96
{
97
12031
  d_instRewrite.push_back(ir);
98
12031
}
99
100
181789
bool Instantiate::addInstantiation(Node q,
101
                                   std::vector<Node>& terms,
102
                                   InferenceId id,
103
                                   Node pfArg,
104
                                   bool mkRep,
105
                                   bool doVts)
106
{
107
  // For resource-limiting (also does a time check).
108
181789
  d_qim.safePoint(Resource::QuantifierStep);
109
181789
  Assert(!d_qstate.isInConflict());
110
181789
  Assert(terms.size() == q[0].getNumChildren());
111
363578
  Trace("inst-add-debug") << "For quantified formula " << q
112
181789
                          << ", add instantiation: " << std::endl;
113
690983
  for (unsigned i = 0, size = terms.size(); i < size; i++)
114
  {
115
509194
    Trace("inst-add-debug") << "  " << q[0][i];
116
509194
    Trace("inst-add-debug2") << " -> " << terms[i];
117
1018388
    TypeNode tn = q[0][i].getType();
118
509194
    if (terms[i].isNull())
119
    {
120
2246
      terms[i] = d_treg.getTermForType(tn);
121
    }
122
    // Ensure the type is correct, this for instance ensures that real terms
123
    // are cast to integers for { x -> t } where x has type Int and t has
124
    // type Real.
125
509194
    terms[i] = ensureType(terms[i], tn);
126
509194
    if (mkRep)
127
    {
128
      // pick the best possible representative for instantiation, based on past
129
      // use and simplicity of term
130
72981
      terms[i] = d_treg.getModel()->getInternalRepresentative(terms[i], q, i);
131
    }
132
509194
    Trace("inst-add-debug") << " -> " << terms[i] << std::endl;
133
509194
    if (terms[i].isNull())
134
    {
135
      Trace("inst-add-debug")
136
          << " --> Failed to make term vector, due to term/type restrictions."
137
          << std::endl;
138
      return false;
139
    }
140
#ifdef CVC5_ASSERTIONS
141
509194
    bool bad_inst = false;
142
509194
    if (TermUtil::containsUninterpretedConstant(terms[i]))
143
    {
144
      Trace("inst") << "***& inst contains uninterpreted constant : "
145
                    << terms[i] << std::endl;
146
      bad_inst = true;
147
    }
148
509194
    else if (!terms[i].getType().isSubtypeOf(q[0][i].getType()))
149
    {
150
      Trace("inst") << "***& inst bad type : " << terms[i] << " "
151
                    << terms[i].getType() << "/" << q[0][i].getType()
152
                    << std::endl;
153
      bad_inst = true;
154
    }
155
509194
    else if (options().quantifiers.cegqi)
156
    {
157
955760
      Node icf = TermUtil::getInstConstAttr(terms[i]);
158
477880
      if (!icf.isNull())
159
      {
160
84
        if (icf == q)
161
        {
162
          Trace("inst") << "***& inst contains inst constant attr : "
163
                        << terms[i] << std::endl;
164
          bad_inst = true;
165
        }
166
84
        else if (expr::hasSubterm(terms[i], d_qreg.d_inst_constants[q]))
167
        {
168
          Trace("inst") << "***& inst contains inst constants : " << terms[i]
169
                        << std::endl;
170
          bad_inst = true;
171
        }
172
      }
173
    }
174
    // this assertion is critical to soundness
175
509194
    if (bad_inst)
176
    {
177
      Trace("inst") << "***& Bad Instantiate " << q << " with " << std::endl;
178
      for (unsigned j = 0; j < terms.size(); j++)
179
      {
180
        Trace("inst") << "   " << terms[j] << std::endl;
181
      }
182
      Assert(false);
183
    }
184
#endif
185
  }
186
187
181789
  EntailmentCheck* ec = d_treg.getEntailmentCheck();
188
  // Note we check for entailment before checking for term vector duplication.
189
  // Although checking for term vector duplication is a faster check, it is
190
  // included automatically with recordInstantiationInternal, hence we prefer
191
  // two checks instead of three. In experiments, it is 1% slower or so to call
192
  // existsInstantiation here.
193
  // Alternatively, we could return an (index, trie node) in the call to
194
  // existsInstantiation here, where this would return the node in the trie
195
  // where we determined that there is definitely no duplication, and then
196
  // continue from that point in recordInstantiation below. However, for
197
  // simplicity, we do not pursue this option (as it would likely only
198
  // lead to very small gains).
199
200
  // check for positive entailment
201
181789
  if (options().quantifiers.instNoEntail)
202
  {
203
    // should check consistency of equality engine
204
    // (if not aborting on utility's reset)
205
258100
    std::map<TNode, TNode> subs;
206
662948
    for (unsigned i = 0, size = terms.size(); i < size; i++)
207
    {
208
484847
      subs[q[0][i]] = terms[i];
209
    }
210
178101
    if (ec->isEntailed(q[1], subs, false, true))
211
    {
212
98102
      Trace("inst-add-debug") << " --> Currently entailed." << std::endl;
213
98102
      ++(d_statistics.d_inst_duplicate_ent);
214
98102
      return false;
215
    }
216
  }
217
218
  // check based on instantiation level
219
83687
  if (options().quantifiers.instMaxLevel != -1)
220
  {
221
375
    TermDb* tdb = d_treg.getTermDatabase();
222
1345
    for (Node& t : terms)
223
    {
224
970
      if (!tdb->isTermEligibleForInstantiation(t, q))
225
      {
226
        return false;
227
      }
228
    }
229
  }
230
231
  // record the instantiation
232
83687
  bool recorded = recordInstantiationInternal(q, terms);
233
83687
  if (!recorded)
234
  {
235
38549
    Trace("inst-add-debug") << " --> Already exists (no record)." << std::endl;
236
38549
    ++(d_statistics.d_inst_duplicate_eq);
237
38549
    return false;
238
  }
239
240
  // Set up a proof if proofs are enabled. This proof stores a proof of
241
  // the instantiation body with q as a free assumption.
242
90276
  std::shared_ptr<LazyCDProof> pfTmp;
243
45138
  if (isProofEnabled())
244
  {
245
21622
    pfTmp.reset(new LazyCDProof(d_env.getProofNodeManager(),
246
                                nullptr,
247
                                nullptr,
248
10811
                                "Instantiate::LazyCDProof::tmp"));
249
  }
250
251
  // construct the instantiation
252
45138
  Trace("inst-add-debug") << "Constructing instantiation..." << std::endl;
253
45138
  Assert(d_qreg.d_vars[q].size() == terms.size());
254
  // get the instantiation
255
  Node body = getInstantiation(
256
90276
      q, d_qreg.d_vars[q], terms, id, pfArg, doVts, pfTmp.get());
257
90276
  Node orig_body = body;
258
  // now preprocess, storing the trust node for the rewrite
259
90276
  TrustNode tpBody = d_qreg.getPreprocess().preprocess(body, true);
260
45138
  if (!tpBody.isNull())
261
  {
262
    Assert(tpBody.getKind() == TrustNodeKind::REWRITE);
263
    body = tpBody.getNode();
264
    // do a tranformation step
265
    if (pfTmp != nullptr)
266
    {
267
      //              ----------------- from preprocess
268
      // orig_body    orig_body = body
269
      // ------------------------------ EQ_RESOLVE
270
      // body
271
      Node proven = tpBody.getProven();
272
      // add the transformation proof, or the trusted rule if none provided
273
      pfTmp->addLazyStep(proven,
274
                         tpBody.getGenerator(),
275
                         PfRule::QUANTIFIERS_PREPROCESS,
276
                         true,
277
                         "Instantiate::getInstantiation:qpreprocess");
278
      pfTmp->addStep(body, PfRule::EQ_RESOLVE, {orig_body, proven}, {});
279
    }
280
  }
281
45138
  Trace("inst-debug") << "...preprocess to " << body << std::endl;
282
283
  // construct the lemma
284
45138
  Trace("inst-assert") << "(assert " << body << ")" << std::endl;
285
286
  // construct the instantiation, and rewrite the lemma
287
90276
  Node lem = NodeManager::currentNM()->mkNode(kind::IMPLIES, q, body);
288
289
  // If proofs are enabled, construct the proof, which is of the form:
290
  // ... free assumption q ...
291
  // ------------------------- from pfTmp
292
  // body
293
  // ------------------------- SCOPE
294
  // (=> q body)
295
  // -------------------------- MACRO_SR_PRED_ELIM
296
  // lem
297
45138
  bool hasProof = false;
298
45138
  if (isProofEnabled())
299
  {
300
    // make the proof of body
301
21622
    std::shared_ptr<ProofNode> pfn = pfTmp->getProofFor(body);
302
    // make the scope proof to get (=> q body)
303
21622
    std::vector<Node> assumps;
304
10811
    assumps.push_back(q);
305
    std::shared_ptr<ProofNode> pfns =
306
21622
        d_env.getProofNodeManager()->mkScope({pfn}, assumps);
307
10811
    Assert(assumps.size() == 1 && assumps[0] == q);
308
    // store in the main proof
309
10811
    d_pfInst->addProof(pfns);
310
21622
    Node prevLem = lem;
311
10811
    lem = rewrite(lem);
312
10811
    if (prevLem != lem)
313
    {
314
6393
      d_pfInst->addStep(lem, PfRule::MACRO_SR_PRED_ELIM, {prevLem}, {});
315
    }
316
10811
    hasProof = true;
317
  }
318
  else
319
  {
320
34327
    lem = rewrite(lem);
321
  }
322
323
  // added lemma, which checks for lemma duplication
324
45138
  bool addedLem = false;
325
45138
  if (hasProof)
326
  {
327
    // use proof generator
328
10811
    addedLem =
329
21622
        d_qim.addPendingLemma(lem, id, LemmaProperty::NONE, d_pfInst.get());
330
  }
331
  else
332
  {
333
34327
    addedLem = d_qim.addPendingLemma(lem, id);
334
  }
335
336
45138
  if (!addedLem)
337
  {
338
1638
    Trace("inst-add-debug") << " --> Lemma already exists." << std::endl;
339
1638
    ++(d_statistics.d_inst_duplicate);
340
1638
    return false;
341
  }
342
343
  // add to list of instantiations
344
43500
  InstLemmaList* ill = getOrMkInstLemmaList(q);
345
43500
  ill->d_list.push_back(body);
346
  // add to temporary debug statistics (# inst on this round)
347
43500
  d_instDebugTemp[q]++;
348
43500
  if (Trace.isOn("inst"))
349
  {
350
    Trace("inst") << "*** Instantiate " << q << " with " << std::endl;
351
    for (unsigned i = 0, size = terms.size(); i < size; i++)
352
    {
353
      if (Trace.isOn("inst"))
354
      {
355
        Trace("inst") << "   " << terms[i];
356
        if (Trace.isOn("inst-debug"))
357
        {
358
          Trace("inst-debug") << ", type=" << terms[i].getType()
359
                              << ", var_type=" << q[0][i].getType();
360
        }
361
        Trace("inst") << std::endl;
362
      }
363
    }
364
  }
365
43500
  if (options().quantifiers.instMaxLevel != -1)
366
  {
367
346
    if (doVts)
368
    {
369
      // virtual term substitution/instantiation level features are
370
      // incompatible
371
      std::stringstream ss;
372
      ss << "Cannot combine instantiation strategies that require virtual term "
373
            "substitution with those that restrict instantiation levels";
374
      throw LogicException(ss.str());
375
    }
376
    else
377
    {
378
346
      uint64_t maxInstLevel = 0;
379
1263
      for (const Node& tc : terms)
380
      {
381
1834
        if (tc.hasAttribute(InstLevelAttribute())
382
917
            && tc.getAttribute(InstLevelAttribute()) > maxInstLevel)
383
        {
384
          maxInstLevel = tc.getAttribute(InstLevelAttribute());
385
        }
386
      }
387
346
      QuantAttributes::setInstantiationLevelAttr(
388
          orig_body, q[1], maxInstLevel + 1);
389
    }
390
  }
391
43500
  d_treg.processInstantiation(q, terms);
392
43500
  Trace("inst-add-debug") << " --> Success." << std::endl;
393
43500
  ++(d_statistics.d_instantiations);
394
43500
  return true;
395
}
396
397
5168
bool Instantiate::addInstantiationExpFail(Node q,
398
                                          std::vector<Node>& terms,
399
                                          std::vector<bool>& failMask,
400
                                          InferenceId id,
401
                                          Node pfArg,
402
                                          bool mkRep,
403
                                          bool doVts,
404
                                          bool expFull)
405
{
406
5168
  if (addInstantiation(q, terms, id, pfArg, mkRep, doVts))
407
  {
408
1052
    return true;
409
  }
410
4116
  size_t tsize = terms.size();
411
4116
  failMask.resize(tsize, true);
412
4116
  if (tsize == 1)
413
  {
414
    // will never succeed with 1 variable
415
1614
    return false;
416
  }
417
2502
  EntailmentCheck* echeck = d_treg.getEntailmentCheck();
418
2502
  Trace("inst-exp-fail") << "Explain inst failure..." << terms << std::endl;
419
  // set up information for below
420
2502
  std::vector<Node>& vars = d_qreg.d_vars[q];
421
2502
  Assert(tsize == vars.size());
422
5004
  std::map<TNode, TNode> subs;
423
15704
  for (size_t i = 0; i < tsize; i++)
424
  {
425
13202
    subs[vars[i]] = terms[i];
426
  }
427
  // get the instantiation body
428
2502
  InferenceId idNone = InferenceId::UNKNOWN;
429
5004
  Node nulln;
430
5004
  Node ibody = getInstantiation(q, vars, terms, idNone, nulln, doVts);
431
2502
  ibody = rewrite(ibody);
432
15648
  for (size_t i = 0; i < tsize; i++)
433
  {
434
    // process consecutively in reverse order, which is important since we use
435
    // the fail mask for incrementing in a lexicographic order
436
13202
    size_t ii = (tsize - 1) - i;
437
    // replace with the identity substitution
438
26348
    Node prev = terms[ii];
439
13202
    terms[ii] = vars[ii];
440
13202
    subs.erase(vars[ii]);
441
13202
    if (subs.empty())
442
    {
443
      // will never succeed with empty substitution
444
56
      break;
445
    }
446
13146
    Trace("inst-exp-fail") << "- revert " << ii << std::endl;
447
    // check whether we are still redundant
448
13146
    bool success = false;
449
    // check entailment, only if option is set
450
13146
    if (options().quantifiers.instNoEntail)
451
    {
452
13146
      Trace("inst-exp-fail") << "  check entailment" << std::endl;
453
13146
      success = echeck->isEntailed(q[1], subs, false, true);
454
13146
      Trace("inst-exp-fail") << "  entailed: " << success << std::endl;
455
    }
456
    // check whether the instantiation rewrites to the same thing
457
13146
    if (!success)
458
    {
459
22080
      Node ibodyc = getInstantiation(q, vars, terms, idNone, nulln, doVts);
460
11040
      ibodyc = rewrite(ibodyc);
461
11040
      success = (ibodyc == ibody);
462
11040
      Trace("inst-exp-fail") << "  rewrite invariant: " << success << std::endl;
463
    }
464
13146
    if (success)
465
    {
466
      // if we still fail, we are not critical
467
2178
      failMask[ii] = false;
468
    }
469
    else
470
    {
471
10968
      subs[vars[ii]] = prev;
472
10968
      terms[ii] = prev;
473
      // not necessary to proceed if expFull is false
474
10968
      if (!expFull)
475
      {
476
        break;
477
      }
478
    }
479
  }
480
2502
  if (Trace.isOn("inst-exp-fail"))
481
  {
482
    Trace("inst-exp-fail") << "Fail mask: ";
483
    for (bool b : failMask)
484
    {
485
      Trace("inst-exp-fail") << (b ? 1 : 0);
486
    }
487
    Trace("inst-exp-fail") << std::endl;
488
  }
489
2502
  return false;
490
}
491
492
1
void Instantiate::recordInstantiation(Node q,
493
                                      const std::vector<Node>& terms,
494
                                      bool doVts)
495
{
496
1
  Trace("inst-debug") << "Record instantiation for " << q << std::endl;
497
  // get the instantiation list, which ensures that q is marked as a quantified
498
  // formula we instantiated, despite only recording an instantiation here
499
1
  getOrMkInstLemmaList(q);
500
2
  Node inst = getInstantiation(q, terms, doVts);
501
1
  d_recordedInst[q].push_back(inst);
502
1
}
503
504
bool Instantiate::existsInstantiation(Node q,
505
                                      const std::vector<Node>& terms,
506
                                      bool modEq)
507
{
508
  if (options().base.incrementalSolving)
509
  {
510
    std::map<Node, CDInstMatchTrie*>::iterator it = d_c_inst_match_trie.find(q);
511
    if (it != d_c_inst_match_trie.end())
512
    {
513
      return it->second->existsInstMatch(userContext(), d_qstate, q, terms, modEq);
514
    }
515
  }
516
  else
517
  {
518
    std::map<Node, InstMatchTrie>::iterator it = d_inst_match_trie.find(q);
519
    if (it != d_inst_match_trie.end())
520
    {
521
      return it->second.existsInstMatch(d_qstate, q, terms, modEq);
522
    }
523
  }
524
  return false;
525
}
526
527
58681
Node Instantiate::getInstantiation(Node q,
528
                                   const std::vector<Node>& vars,
529
                                   const std::vector<Node>& terms,
530
                                   InferenceId id,
531
                                   Node pfArg,
532
                                   bool doVts,
533
                                   LazyCDProof* pf)
534
{
535
58681
  Assert(vars.size() == terms.size());
536
58681
  Assert(q[0].getNumChildren() == vars.size());
537
  // Notice that this could be optimized, but no significant performance
538
  // improvements were observed with alternative implementations (see #1386).
539
  Node body =
540
58681
      q[1].substitute(vars.begin(), vars.end(), terms.begin(), terms.end());
541
542
  // store the proof of the instantiated body, with (open) assumption q
543
58681
  if (pf != nullptr)
544
  {
545
    // additional arguments: if the inference id is not unknown, include it,
546
    // followed by the proof argument if non-null. The latter is used e.g.
547
    // to track which trigger caused an instantiation.
548
21622
    std::vector<Node> pfTerms = terms;
549
10811
    if (id != InferenceId::UNKNOWN)
550
    {
551
10808
      pfTerms.push_back(mkInferenceIdNode(id));
552
10808
      if (!pfArg.isNull())
553
      {
554
8723
        pfTerms.push_back(pfArg);
555
      }
556
    }
557
10811
    pf->addStep(body, PfRule::INSTANTIATE, {q}, pfTerms);
558
  }
559
560
  // run rewriters to rewrite the instantiation in sequence.
561
110917
  for (InstantiationRewriter*& ir : d_instRewrite)
562
  {
563
104472
    TrustNode trn = ir->rewriteInstantiation(q, terms, body, doVts);
564
52236
    if (!trn.isNull())
565
    {
566
154
      Node newBody = trn.getNode();
567
      // if using proofs, we store a preprocess + transformation step.
568
77
      if (pf != nullptr)
569
      {
570
44
        Node proven = trn.getProven();
571
22
        pf->addLazyStep(proven,
572
                        trn.getGenerator(),
573
                        PfRule::THEORY_PREPROCESS,
574
                        true,
575
                        "Instantiate::getInstantiation:rewrite_inst");
576
22
        pf->addStep(newBody, PfRule::EQ_RESOLVE, {body, proven}, {});
577
      }
578
77
      body = newBody;
579
    }
580
  }
581
58681
  return body;
582
}
583
584
1
Node Instantiate::getInstantiation(Node q,
585
                                   const std::vector<Node>& terms,
586
                                   bool doVts)
587
{
588
1
  Assert(d_qreg.d_vars.find(q) != d_qreg.d_vars.end());
589
  return getInstantiation(
590
1
      q, d_qreg.d_vars[q], terms, InferenceId::UNKNOWN, Node::null(), doVts);
591
}
592
593
83687
bool Instantiate::recordInstantiationInternal(Node q,
594
                                              const std::vector<Node>& terms)
595
{
596
83687
  if (options().base.incrementalSolving)
597
  {
598
16272
    Trace("inst-add-debug")
599
8136
        << "Adding into context-dependent inst trie" << std::endl;
600
8136
    const auto res = d_c_inst_match_trie.insert({q, nullptr});
601
8136
    if (res.second)
602
    {
603
709
      res.first->second = new CDInstMatchTrie(userContext());
604
    }
605
8136
    d_c_inst_match_trie_dom.insert(q);
606
8136
    return res.first->second->addInstMatch(userContext(), d_qstate, q, terms);
607
  }
608
75551
  Trace("inst-add-debug") << "Adding into inst trie" << std::endl;
609
75551
  return d_inst_match_trie[q].addInstMatch(d_qstate, q, terms);
610
}
611
612
bool Instantiate::removeInstantiationInternal(Node q,
613
                                              const std::vector<Node>& terms)
614
{
615
  if (options().base.incrementalSolving)
616
  {
617
    std::map<Node, CDInstMatchTrie*>::iterator it = d_c_inst_match_trie.find(q);
618
    if (it != d_c_inst_match_trie.end())
619
    {
620
      return it->second->removeInstMatch(q, terms);
621
    }
622
    return false;
623
  }
624
  return d_inst_match_trie[q].removeInstMatch(q, terms);
625
}
626
627
93
void Instantiate::getInstantiatedQuantifiedFormulas(std::vector<Node>& qs) const
628
{
629
174
  for (NodeInstListMap::const_iterator it = d_insts.begin();
630
174
       it != d_insts.end();
631
       ++it)
632
  {
633
81
    qs.push_back(it->first);
634
  }
635
93
}
636
637
72
void Instantiate::getInstantiationTermVectors(
638
    Node q, std::vector<std::vector<Node> >& tvecs)
639
{
640
72
  if (options().base.incrementalSolving)
641
  {
642
    std::map<Node, CDInstMatchTrie*>::const_iterator it =
643
4
        d_c_inst_match_trie.find(q);
644
4
    if (it != d_c_inst_match_trie.end())
645
    {
646
4
      it->second->getInstantiations(q, tvecs);
647
    }
648
  }
649
  else
650
  {
651
    std::map<Node, InstMatchTrie>::const_iterator it =
652
68
        d_inst_match_trie.find(q);
653
68
    if (it != d_inst_match_trie.end())
654
    {
655
68
      it->second.getInstantiations(q, tvecs);
656
    }
657
  }
658
72
}
659
660
8
void Instantiate::getInstantiationTermVectors(
661
    std::map<Node, std::vector<std::vector<Node> > >& insts)
662
{
663
8
  if (options().base.incrementalSolving)
664
  {
665
8
    for (const auto& t : d_c_inst_match_trie)
666
    {
667
4
      getInstantiationTermVectors(t.first, insts[t.first]);
668
    }
669
  }
670
  else
671
  {
672
10
    for (const auto& t : d_inst_match_trie)
673
    {
674
6
      getInstantiationTermVectors(t.first, insts[t.first]);
675
    }
676
  }
677
8
}
678
679
18
void Instantiate::getInstantiations(Node q, std::vector<Node>& insts)
680
{
681
18
  Trace("inst-debug") << "get instantiations for " << q << std::endl;
682
18
  InstLemmaList* ill = getOrMkInstLemmaList(q);
683
18
  insts.insert(insts.end(), ill->d_list.begin(), ill->d_list.end());
684
  // also include recorded instantations (for qe-partial)
685
  std::map<Node, std::vector<Node> >::const_iterator it =
686
18
      d_recordedInst.find(q);
687
18
  if (it != d_recordedInst.end())
688
  {
689
1
    insts.insert(insts.end(), it->second.begin(), it->second.end());
690
  }
691
18
}
692
693
105549
bool Instantiate::isProofEnabled() const
694
{
695
105549
  return d_env.isTheoryProofProducing();
696
}
697
698
14298
void Instantiate::notifyEndRound()
699
{
700
  // debug information
701
14298
  if (Trace.isOn("inst-per-quant-round"))
702
  {
703
    for (std::pair<const Node, uint32_t>& i : d_instDebugTemp)
704
    {
705
      Trace("inst-per-quant-round")
706
          << " * " << i.second << " for " << i.first << std::endl;
707
    }
708
  }
709
14298
  if (isOutputOn(OutputTag::INST))
710
  {
711
2
    bool req = !options().printer.printInstFull;
712
6
    for (std::pair<const Node, uint32_t>& i : d_instDebugTemp)
713
    {
714
8
      Node name;
715
4
      if (!d_qreg.getNameForQuant(i.first, name, req))
716
      {
717
        continue;
718
      }
719
8
      output(OutputTag::INST) << "(num-instantiations " << name << " "
720
4
                              << i.second << ")" << std::endl;
721
    }
722
  }
723
14298
}
724
725
11015
void Instantiate::debugPrintModel()
726
{
727
11015
  if (Trace.isOn("inst-per-quant"))
728
  {
729
    for (NodeInstListMap::iterator it = d_insts.begin(); it != d_insts.end();
730
         ++it)
731
    {
732
      Trace("inst-per-quant") << " * " << (*it).second->d_list.size() << " for "
733
                              << (*it).first << std::endl;
734
    }
735
  }
736
11015
}
737
738
509194
Node Instantiate::ensureType(Node n, TypeNode tn)
739
{
740
509194
  Trace("inst-add-debug2") << "Ensure " << n << " : " << tn << std::endl;
741
1018388
  TypeNode ntn = n.getType();
742
509194
  Assert(ntn.isComparableTo(tn));
743
509194
  if (ntn.isSubtypeOf(tn))
744
  {
745
509178
    return n;
746
  }
747
16
  if (tn.isInteger())
748
  {
749
16
    return NodeManager::currentNM()->mkNode(TO_INTEGER, n);
750
  }
751
  return Node::null();
752
}
753
754
43519
InstLemmaList* Instantiate::getOrMkInstLemmaList(TNode q)
755
{
756
43519
  NodeInstListMap::iterator it = d_insts.find(q);
757
43519
  if (it != d_insts.end())
758
  {
759
36910
    return it->second.get();
760
  }
761
  std::shared_ptr<InstLemmaList> ill =
762
13218
      std::make_shared<InstLemmaList>(userContext());
763
6609
  d_insts.insert(q, ill);
764
6609
  return ill.get();
765
}
766
767
15273
Instantiate::Statistics::Statistics()
768
15273
    : d_instantiations(smtStatisticsRegistry().registerInt(
769
30546
        "Instantiate::Instantiations_Total")),
770
      d_inst_duplicate(
771
30546
          smtStatisticsRegistry().registerInt("Instantiate::Duplicate_Inst")),
772
15273
      d_inst_duplicate_eq(smtStatisticsRegistry().registerInt(
773
30546
          "Instantiate::Duplicate_Inst_Eq")),
774
15273
      d_inst_duplicate_ent(smtStatisticsRegistry().registerInt(
775
61092
          "Instantiate::Duplicate_Inst_Entailed"))
776
{
777
15273
}
778
779
}  // namespace quantifiers
780
}  // namespace theory
781
31137
}  // namespace cvc5