GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/instantiate.cpp Lines: 268 338 79.3 %
Date: 2021-05-22 Branches: 516 1380 37.4 %

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