GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/instantiate.cpp Lines: 274 343 79.9 %
Date: 2021-09-07 Branches: 528 1384 38.2 %

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