1 /********************* */
2 /*! \file instantiate.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Tim King, Morgan Deters
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
11 **
12 ** \brief Implementation of instantiate
13 **/
14
15 #include "theory/quantifiers/instantiate.h"
16
17 #include "options/quantifiers_options.h"
18 #include "smt/smt_statistics_registry.h"
19 #include "theory/quantifiers/first_order_model.h"
20 #include "theory/quantifiers/cegqi/inst_strategy_cegqi.h"
21 #include "theory/quantifiers/quantifiers_attributes.h"
22 #include "theory/quantifiers/quantifiers_rewriter.h"
23 #include "theory/quantifiers/term_database.h"
24 #include "theory/quantifiers/term_enumeration.h"
25 #include "theory/quantifiers/term_util.h"
26
27 using namespace CVC4::kind;
28 using namespace CVC4::context;
29
30 namespace CVC4 {
31 namespace theory {
32 namespace quantifiers {
33
Instantiate(QuantifiersEngine * qe,context::UserContext * u)34 Instantiate::Instantiate(QuantifiersEngine* qe, context::UserContext* u)
35 : d_qe(qe),
36 d_term_db(nullptr),
37 d_term_util(nullptr),
38 d_total_inst_count_debug(0),
39 d_c_inst_match_trie_dom(u)
40 {
41 }
42
~Instantiate()43 Instantiate::~Instantiate()
44 {
45 for (std::pair<const Node, inst::CDInstMatchTrie*>& t : d_c_inst_match_trie)
46 {
47 delete t.second;
48 }
49 d_c_inst_match_trie.clear();
50 }
51
reset(Theory::Effort e)52 bool Instantiate::reset(Theory::Effort e)
53 {
54 if (!d_recorded_inst.empty())
55 {
56 Trace("quant-engine-debug") << "Removing " << d_recorded_inst.size()
57 << " instantiations..." << std::endl;
58 // remove explicitly recorded instantiations
59 for (std::pair<Node, std::vector<Node> >& r : d_recorded_inst)
60 {
61 removeInstantiationInternal(r.first, r.second);
62 }
63 d_recorded_inst.clear();
64 }
65 d_term_db = d_qe->getTermDatabase();
66 d_term_util = d_qe->getTermUtil();
67 return true;
68 }
69
registerQuantifier(Node q)70 void Instantiate::registerQuantifier(Node q) {}
checkComplete()71 bool Instantiate::checkComplete()
72 {
73 if (!d_recorded_inst.empty())
74 {
75 Trace("quant-engine-debug")
76 << "Set incomplete due to recorded instantiations." << std::endl;
77 return false;
78 }
79 return true;
80 }
81
addNotify(InstantiationNotify * in)82 void Instantiate::addNotify(InstantiationNotify* in)
83 {
84 d_inst_notify.push_back(in);
85 }
86
notifyFlushLemmas()87 void Instantiate::notifyFlushLemmas()
88 {
89 for (InstantiationNotify*& in : d_inst_notify)
90 {
91 in->filterInstantiations();
92 }
93 }
94
addInstantiation(Node q,InstMatch & m,bool mkRep,bool modEq,bool doVts)95 bool Instantiate::addInstantiation(
96 Node q, InstMatch& m, bool mkRep, bool modEq, bool doVts)
97 {
98 Assert(q[0].getNumChildren() == m.d_vals.size());
99 return addInstantiation(q, m.d_vals, mkRep, modEq, doVts);
100 }
101
addInstantiation(Node q,std::vector<Node> & terms,bool mkRep,bool modEq,bool doVts)102 bool Instantiate::addInstantiation(
103 Node q, std::vector<Node>& terms, bool mkRep, bool modEq, bool doVts)
104 {
105 // For resource-limiting (also does a time check).
106 d_qe->getOutputChannel().safePoint(options::quantifierStep());
107 Assert(!d_qe->inConflict());
108 Assert(terms.size() == q[0].getNumChildren());
109 Assert(d_term_db != nullptr);
110 Assert(d_term_util != nullptr);
111 Trace("inst-add-debug") << "For quantified formula " << q
112 << ", add instantiation: " << std::endl;
113 for (unsigned i = 0, size = terms.size(); i < size; i++)
114 {
115 Trace("inst-add-debug") << " " << q[0][i];
116 Trace("inst-add-debug2") << " -> " << terms[i];
117 TypeNode tn = q[0][i].getType();
118 if (terms[i].isNull())
119 {
120 terms[i] = getTermForType(tn);
121 }
122 if (mkRep)
123 {
124 // pick the best possible representative for instantiation, based on past
125 // use and simplicity of term
126 terms[i] = d_qe->getInternalRepresentative(terms[i], q, i);
127 }
128 else
129 {
130 // ensure the type is correct
131 terms[i] = quantifiers::TermUtil::ensureType(terms[i], tn);
132 }
133 Trace("inst-add-debug") << " -> " << terms[i] << std::endl;
134 if (terms[i].isNull())
135 {
136 Trace("inst-add-debug")
137 << " --> Failed to make term vector, due to term/type restrictions."
138 << std::endl;
139 return false;
140 }
141 #ifdef CVC4_ASSERTIONS
142 bool bad_inst = false;
143 if (quantifiers::TermUtil::containsUninterpretedConstant(terms[i]))
144 {
145 Trace("inst") << "***& inst contains uninterpreted constant : "
146 << terms[i] << std::endl;
147 bad_inst = true;
148 }
149 else if (!terms[i].getType().isSubtypeOf(q[0][i].getType()))
150 {
151 Trace("inst") << "***& inst bad type : " << terms[i] << " "
152 << terms[i].getType() << "/" << q[0][i].getType()
153 << std::endl;
154 bad_inst = true;
155 }
156 else if (options::cbqi())
157 {
158 Node icf = quantifiers::TermUtil::getInstConstAttr(terms[i]);
159 if (!icf.isNull())
160 {
161 if (icf == q)
162 {
163 Trace("inst") << "***& inst contains inst constant attr : "
164 << terms[i] << std::endl;
165 bad_inst = true;
166 }
167 else if (quantifiers::TermUtil::containsTerms(
168 terms[i], d_term_util->d_inst_constants[q]))
169 {
170 Trace("inst") << "***& inst contains inst constants : " << terms[i]
171 << std::endl;
172 bad_inst = true;
173 }
174 }
175 }
176 // this assertion is critical to soundness
177 if (bad_inst)
178 {
179 Trace("inst") << "***& Bad Instantiate " << q << " with " << std::endl;
180 for (unsigned j = 0; j < terms.size(); j++)
181 {
182 Trace("inst") << " " << terms[j] << std::endl;
183 }
184 Assert(false);
185 }
186 #endif
187 }
188
189 // Note we check for entailment before checking for term vector duplication.
190 // Although checking for term vector duplication is a faster check, it is
191 // included automatically with recordInstantiationInternal, hence we prefer
192 // two checks instead of three. In experiments, it is 1% slower or so to call
193 // existsInstantiation here.
194 // Alternatively, we could return an (index, trie node) in the call to
195 // existsInstantiation here, where this would return the node in the trie
196 // where we determined that there is definitely no duplication, and then
197 // continue from that point in recordInstantiation below. However, for
198 // simplicity, we do not pursue this option (as it would likely only
199 // lead to very small gains).
200
201 // check for positive entailment
202 if (options::instNoEntail())
203 {
204 // should check consistency of equality engine
205 // (if not aborting on utility's reset)
206 std::map<TNode, TNode> subs;
207 for (unsigned i = 0, size = terms.size(); i < size; i++)
208 {
209 subs[q[0][i]] = terms[i];
210 }
211 if (d_term_db->isEntailed(q[1], subs, false, true))
212 {
213 Trace("inst-add-debug") << " --> Currently entailed." << std::endl;
214 ++(d_statistics.d_inst_duplicate_ent);
215 return false;
216 }
217 }
218
219 // check based on instantiation level
220 if (options::instMaxLevel() != -1 || options::lteRestrictInstClosure())
221 {
222 for (Node& t : terms)
223 {
224 if (!d_term_db->isTermEligibleForInstantiation(t, q, true))
225 {
226 return false;
227 }
228 }
229 }
230
231 // record the instantiation
232 bool recorded = recordInstantiationInternal(q, terms, modEq);
233 if (!recorded)
234 {
235 Trace("inst-add-debug") << " --> Already exists (no record)." << std::endl;
236 ++(d_statistics.d_inst_duplicate_eq);
237 return false;
238 }
239
240 // construct the instantiation
241 Trace("inst-add-debug") << "Constructing instantiation..." << std::endl;
242 Assert(d_term_util->d_vars[q].size() == terms.size());
243 // get the instantiation
244 Node body = getInstantiation(q, d_term_util->d_vars[q], terms, doVts);
245 Node orig_body = body;
246 if (options::cbqiNestedQE())
247 {
248 InstStrategyCegqi* icegqi = d_qe->getInstStrategyCegqi();
249 if (icegqi)
250 {
251 body = icegqi->doNestedQE(q, terms, body, doVts);
252 }
253 }
254 body = quantifiers::QuantifiersRewriter::preprocess(body, true);
255 Trace("inst-debug") << "...preprocess to " << body << std::endl;
256
257 // construct the lemma
258 Trace("inst-assert") << "(assert " << body << ")" << std::endl;
259
260 if (d_qe->usingModelEqualityEngine() && options::instNoModelTrue())
261 {
262 Node val_body = d_qe->getModel()->getValue(body);
263 if (val_body.isConst() && val_body.getConst<bool>())
264 {
265 Trace("inst-add-debug") << " --> True in model." << std::endl;
266 ++(d_statistics.d_inst_duplicate_model_true);
267 return false;
268 }
269 }
270
271 Node lem = NodeManager::currentNM()->mkNode(kind::OR, q.negate(), body);
272 lem = Rewriter::rewrite(lem);
273
274 // check for lemma duplication
275 if (!d_qe->addLemma(lem, true, false))
276 {
277 Trace("inst-add-debug") << " --> Lemma already exists." << std::endl;
278 ++(d_statistics.d_inst_duplicate);
279 return false;
280 }
281
282 d_total_inst_debug[q]++;
283 d_temp_inst_debug[q]++;
284 d_total_inst_count_debug++;
285 if (Trace.isOn("inst"))
286 {
287 Trace("inst") << "*** Instantiate " << q << " with " << std::endl;
288 for (unsigned i = 0, size = terms.size(); i < size; i++)
289 {
290 if (Trace.isOn("inst"))
291 {
292 Trace("inst") << " " << terms[i];
293 if (Trace.isOn("inst-debug"))
294 {
295 Trace("inst-debug") << ", type=" << terms[i].getType()
296 << ", var_type=" << q[0][i].getType();
297 }
298 Trace("inst") << std::endl;
299 }
300 }
301 }
302 if (options::instMaxLevel() != -1)
303 {
304 if (doVts)
305 {
306 // virtual term substitution/instantiation level features are
307 // incompatible
308 Assert(false);
309 }
310 else
311 {
312 uint64_t maxInstLevel = 0;
313 for (const Node& tc : terms)
314 {
315 if (tc.hasAttribute(InstLevelAttribute())
316 && tc.getAttribute(InstLevelAttribute()) > maxInstLevel)
317 {
318 maxInstLevel = tc.getAttribute(InstLevelAttribute());
319 }
320 }
321 QuantAttributes::setInstantiationLevelAttr(
322 orig_body, q[1], maxInstLevel + 1);
323 }
324 }
325 QuantifiersModule::QEffort elevel = d_qe->getCurrentQEffort();
326 if (elevel > QuantifiersModule::QEFFORT_CONFLICT
327 && elevel < QuantifiersModule::QEFFORT_NONE
328 && !d_inst_notify.empty())
329 {
330 // notify listeners
331 for (InstantiationNotify*& in : d_inst_notify)
332 {
333 if (!in->notifyInstantiation(elevel, q, lem, terms, body))
334 {
335 Trace("inst-add-debug") << "...we are in conflict." << std::endl;
336 d_qe->setConflict();
337 Assert(d_qe->getNumLemmasWaiting() > 0);
338 break;
339 }
340 }
341 }
342 if (options::trackInstLemmas())
343 {
344 bool recorded;
345 if (options::incrementalSolving())
346 {
347 recorded = d_c_inst_match_trie[q]->recordInstLemma(q, terms, lem);
348 }
349 else
350 {
351 recorded = d_inst_match_trie[q].recordInstLemma(q, terms, lem);
352 }
353 Trace("inst-add-debug") << "...was recorded : " << recorded << std::endl;
354 Assert(recorded);
355 }
356 Trace("inst-add-debug") << " --> Success." << std::endl;
357 ++(d_statistics.d_instantiations);
358 return true;
359 }
360
removeInstantiation(Node q,Node lem,std::vector<Node> & terms)361 bool Instantiate::removeInstantiation(Node q,
362 Node lem,
363 std::vector<Node>& terms)
364 {
365 // lem must occur in d_waiting_lemmas
366 if (d_qe->removeLemma(lem))
367 {
368 return removeInstantiationInternal(q, terms);
369 }
370 return false;
371 }
372
recordInstantiation(Node q,std::vector<Node> & terms,bool modEq,bool addedLem)373 bool Instantiate::recordInstantiation(Node q,
374 std::vector<Node>& terms,
375 bool modEq,
376 bool addedLem)
377 {
378 return recordInstantiationInternal(q, terms, modEq, addedLem);
379 }
380
existsInstantiation(Node q,std::vector<Node> & terms,bool modEq)381 bool Instantiate::existsInstantiation(Node q,
382 std::vector<Node>& terms,
383 bool modEq)
384 {
385 if (options::incrementalSolving())
386 {
387 std::map<Node, inst::CDInstMatchTrie*>::iterator it =
388 d_c_inst_match_trie.find(q);
389 if (it != d_c_inst_match_trie.end())
390 {
391 return it->second->existsInstMatch(
392 d_qe, q, terms, d_qe->getUserContext(), modEq);
393 }
394 }
395 else
396 {
397 std::map<Node, inst::InstMatchTrie>::iterator it =
398 d_inst_match_trie.find(q);
399 if (it != d_inst_match_trie.end())
400 {
401 return it->second.existsInstMatch(d_qe, q, terms, modEq);
402 }
403 }
404 return false;
405 }
406
getInstantiation(Node q,std::vector<Node> & vars,std::vector<Node> & terms,bool doVts)407 Node Instantiate::getInstantiation(Node q,
408 std::vector<Node>& vars,
409 std::vector<Node>& terms,
410 bool doVts)
411 {
412 Node body;
413 Assert(vars.size() == terms.size());
414 Assert(q[0].getNumChildren() == vars.size());
415 // TODO (#1386) : optimize this
416 body = q[1].substitute(vars.begin(), vars.end(), terms.begin(), terms.end());
417 if (doVts)
418 {
419 // do virtual term substitution
420 body = Rewriter::rewrite(body);
421 Trace("quant-vts-debug") << "Rewrite vts symbols in " << body << std::endl;
422 Node body_r = d_term_util->rewriteVtsSymbols(body);
423 Trace("quant-vts-debug") << " ...result: " << body_r
424 << std::endl;
425 body = body_r;
426 }
427 return body;
428 }
429
getInstantiation(Node q,InstMatch & m,bool doVts)430 Node Instantiate::getInstantiation(Node q, InstMatch& m, bool doVts)
431 {
432 Assert(d_term_util->d_vars.find(q) != d_term_util->d_vars.end());
433 Assert(m.d_vals.size() == q[0].getNumChildren());
434 return getInstantiation(q, d_term_util->d_vars[q], m.d_vals, doVts);
435 }
436
getInstantiation(Node q,std::vector<Node> & terms,bool doVts)437 Node Instantiate::getInstantiation(Node q, std::vector<Node>& terms, bool doVts)
438 {
439 Assert(d_term_util->d_vars.find(q) != d_term_util->d_vars.end());
440 return getInstantiation(q, d_term_util->d_vars[q], terms, doVts);
441 }
442
recordInstantiationInternal(Node q,std::vector<Node> & terms,bool modEq,bool addedLem)443 bool Instantiate::recordInstantiationInternal(Node q,
444 std::vector<Node>& terms,
445 bool modEq,
446 bool addedLem)
447 {
448 if (!addedLem)
449 {
450 // record the instantiation for deletion later
451 d_recorded_inst.push_back(std::pair<Node, std::vector<Node> >(q, terms));
452 }
453 if (options::incrementalSolving())
454 {
455 Trace("inst-add-debug")
456 << "Adding into context-dependent inst trie, modEq = " << modEq
457 << std::endl;
458 inst::CDInstMatchTrie* imt;
459 std::map<Node, inst::CDInstMatchTrie*>::iterator it =
460 d_c_inst_match_trie.find(q);
461 if (it != d_c_inst_match_trie.end())
462 {
463 imt = it->second;
464 }
465 else
466 {
467 imt = new inst::CDInstMatchTrie(d_qe->getUserContext());
468 d_c_inst_match_trie[q] = imt;
469 }
470 d_c_inst_match_trie_dom.insert(q);
471 return imt->addInstMatch(d_qe, q, terms, d_qe->getUserContext(), modEq);
472 }
473 Trace("inst-add-debug") << "Adding into inst trie" << std::endl;
474 return d_inst_match_trie[q].addInstMatch(d_qe, q, terms, modEq);
475 }
476
removeInstantiationInternal(Node q,std::vector<Node> & terms)477 bool Instantiate::removeInstantiationInternal(Node q, std::vector<Node>& terms)
478 {
479 if (options::incrementalSolving())
480 {
481 std::map<Node, inst::CDInstMatchTrie*>::iterator it =
482 d_c_inst_match_trie.find(q);
483 if (it != d_c_inst_match_trie.end())
484 {
485 return it->second->removeInstMatch(q, terms);
486 }
487 return false;
488 }
489 return d_inst_match_trie[q].removeInstMatch(q, terms);
490 }
491
getTermForType(TypeNode tn)492 Node Instantiate::getTermForType(TypeNode tn)
493 {
494 if (tn.isClosedEnumerable())
495 {
496 return d_qe->getTermEnumeration()->getEnumerateTerm(tn, 0);
497 }
498 return d_qe->getTermDatabase()->getOrMakeTypeGroundTerm(tn);
499 }
500
printInstantiations(std::ostream & out)501 bool Instantiate::printInstantiations(std::ostream& out)
502 {
503 bool useUnsatCore = false;
504 std::vector<Node> active_lemmas;
505 if (options::trackInstLemmas() && getUnsatCoreLemmas(active_lemmas))
506 {
507 useUnsatCore = true;
508 }
509 bool printed = false;
510 if (options::incrementalSolving())
511 {
512 for (std::pair<const Node, inst::CDInstMatchTrie*>& t : d_c_inst_match_trie)
513 {
514 bool firstTime = true;
515 t.second->print(out, t.first, firstTime, useUnsatCore, active_lemmas);
516 if (!firstTime)
517 {
518 out << ")" << std::endl;
519 }
520 printed = printed || !firstTime;
521 }
522 }
523 else
524 {
525 for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
526 {
527 bool firstTime = true;
528 t.second.print(out, t.first, firstTime, useUnsatCore, active_lemmas);
529 if (!firstTime)
530 {
531 out << ")" << std::endl;
532 }
533 printed = printed || !firstTime;
534 }
535 }
536 return printed;
537 }
538
getInstantiatedQuantifiedFormulas(std::vector<Node> & qs)539 void Instantiate::getInstantiatedQuantifiedFormulas(std::vector<Node>& qs)
540 {
541 if (options::incrementalSolving())
542 {
543 for (context::CDHashSet<Node, NodeHashFunction>::const_iterator it =
544 d_c_inst_match_trie_dom.begin();
545 it != d_c_inst_match_trie_dom.end();
546 ++it)
547 {
548 qs.push_back(*it);
549 }
550 }
551 else
552 {
553 for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
554 {
555 qs.push_back(t.first);
556 }
557 }
558 }
559
getUnsatCoreLemmas(std::vector<Node> & active_lemmas)560 bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas)
561 {
562 // only if unsat core available
563 if (options::proof())
564 {
565 if (!ProofManager::currentPM()->unsatCoreAvailable())
566 {
567 return false;
568 }
569 }
570
571 Trace("inst-unsat-core") << "Get instantiations in unsat core..."
572 << std::endl;
573 ProofManager::currentPM()->getLemmasInUnsatCore(theory::THEORY_QUANTIFIERS,
574 active_lemmas);
575 if (Trace.isOn("inst-unsat-core"))
576 {
577 Trace("inst-unsat-core") << "Quantifiers lemmas in unsat core: "
578 << std::endl;
579 for (const Node& lem : active_lemmas)
580 {
581 Trace("inst-unsat-core") << " " << lem << std::endl;
582 }
583 Trace("inst-unsat-core") << std::endl;
584 }
585 return true;
586 }
587
getUnsatCoreLemmas(std::vector<Node> & active_lemmas,std::map<Node,Node> & weak_imp)588 bool Instantiate::getUnsatCoreLemmas(std::vector<Node>& active_lemmas,
589 std::map<Node, Node>& weak_imp)
590 {
591 if (getUnsatCoreLemmas(active_lemmas))
592 {
593 for (unsigned i = 0, size = active_lemmas.size(); i < size; ++i)
594 {
595 Node n = ProofManager::currentPM()->getWeakestImplicantInUnsatCore(
596 active_lemmas[i]);
597 if (n != active_lemmas[i])
598 {
599 Trace("inst-unsat-core") << " weaken : " << active_lemmas[i] << " -> "
600 << n << std::endl;
601 }
602 weak_imp[active_lemmas[i]] = n;
603 }
604 return true;
605 }
606 return false;
607 }
608
getInstantiationTermVectors(Node q,std::vector<std::vector<Node>> & tvecs)609 void Instantiate::getInstantiationTermVectors(
610 Node q, std::vector<std::vector<Node> >& tvecs)
611 {
612 std::vector<Node> lemmas;
613 getInstantiations(q, lemmas);
614 std::map<Node, Node> quant;
615 std::map<Node, std::vector<Node> > tvec;
616 getExplanationForInstLemmas(lemmas, quant, tvec);
617 for (std::pair<const Node, std::vector<Node> >& t : tvec)
618 {
619 tvecs.push_back(t.second);
620 }
621 }
622
getInstantiationTermVectors(std::map<Node,std::vector<std::vector<Node>>> & insts)623 void Instantiate::getInstantiationTermVectors(
624 std::map<Node, std::vector<std::vector<Node> > >& insts)
625 {
626 if (options::incrementalSolving())
627 {
628 for (std::pair<const Node, inst::CDInstMatchTrie*>& t : d_c_inst_match_trie)
629 {
630 getInstantiationTermVectors(t.first, insts[t.first]);
631 }
632 }
633 else
634 {
635 for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
636 {
637 getInstantiationTermVectors(t.first, insts[t.first]);
638 }
639 }
640 }
641
getExplanationForInstLemmas(const std::vector<Node> & lems,std::map<Node,Node> & quant,std::map<Node,std::vector<Node>> & tvec)642 void Instantiate::getExplanationForInstLemmas(
643 const std::vector<Node>& lems,
644 std::map<Node, Node>& quant,
645 std::map<Node, std::vector<Node> >& tvec)
646 {
647 if (options::trackInstLemmas())
648 {
649 if (options::incrementalSolving())
650 {
651 for (std::pair<const Node, inst::CDInstMatchTrie*>& t :
652 d_c_inst_match_trie)
653 {
654 t.second->getExplanationForInstLemmas(t.first, lems, quant, tvec);
655 }
656 }
657 else
658 {
659 for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
660 {
661 t.second.getExplanationForInstLemmas(t.first, lems, quant, tvec);
662 }
663 }
664 #ifdef CVC4_ASSERTIONS
665 for (unsigned j = 0; j < lems.size(); j++)
666 {
667 Assert(quant.find(lems[j]) != quant.end());
668 Assert(tvec.find(lems[j]) != tvec.end());
669 }
670 #endif
671 }
672 Assert(false);
673 }
674
getInstantiations(std::map<Node,std::vector<Node>> & insts)675 void Instantiate::getInstantiations(std::map<Node, std::vector<Node> >& insts)
676 {
677 bool useUnsatCore = false;
678 std::vector<Node> active_lemmas;
679 if (options::trackInstLemmas() && getUnsatCoreLemmas(active_lemmas))
680 {
681 useUnsatCore = true;
682 }
683
684 if (options::incrementalSolving())
685 {
686 for (std::pair<const Node, inst::CDInstMatchTrie*>& t : d_c_inst_match_trie)
687 {
688 t.second->getInstantiations(
689 insts[t.first], t.first, d_qe, useUnsatCore, active_lemmas);
690 }
691 }
692 else
693 {
694 for (std::pair<const Node, inst::InstMatchTrie>& t : d_inst_match_trie)
695 {
696 t.second.getInstantiations(
697 insts[t.first], t.first, d_qe, useUnsatCore, active_lemmas);
698 }
699 }
700 }
701
getInstantiations(Node q,std::vector<Node> & insts)702 void Instantiate::getInstantiations(Node q, std::vector<Node>& insts)
703 {
704 if (options::incrementalSolving())
705 {
706 std::map<Node, inst::CDInstMatchTrie*>::iterator it =
707 d_c_inst_match_trie.find(q);
708 if (it != d_c_inst_match_trie.end())
709 {
710 std::vector<Node> active_lemmas;
711 it->second->getInstantiations(
712 insts, it->first, d_qe, false, active_lemmas);
713 }
714 }
715 else
716 {
717 std::map<Node, inst::InstMatchTrie>::iterator it =
718 d_inst_match_trie.find(q);
719 if (it != d_inst_match_trie.end())
720 {
721 std::vector<Node> active_lemmas;
722 it->second.getInstantiations(
723 insts, it->first, d_qe, false, active_lemmas);
724 }
725 }
726 }
727
getInstantiatedConjunction(Node q)728 Node Instantiate::getInstantiatedConjunction(Node q)
729 {
730 Assert(q.getKind() == FORALL);
731 std::vector<Node> insts;
732 getInstantiations(q, insts);
733 if (insts.empty())
734 {
735 return NodeManager::currentNM()->mkConst(true);
736 }
737 Node ret;
738 if (insts.size() == 1)
739 {
740 ret = insts[0];
741 }
742 else
743 {
744 ret = NodeManager::currentNM()->mkNode(kind::AND, insts);
745 }
746 // have to remove q
747 // may want to do this in a better way
748 TNode tq = q;
749 TNode tt = NodeManager::currentNM()->mkConst(true);
750 ret = ret.substitute(tq, tt);
751 return ret;
752 }
753
debugPrint()754 void Instantiate::debugPrint()
755 {
756 // debug information
757 if (Trace.isOn("inst-per-quant-round"))
758 {
759 for (std::pair<const Node, int>& i : d_temp_inst_debug)
760 {
761 Trace("inst-per-quant-round") << " * " << i.second << " for " << i.first
762 << std::endl;
763 d_temp_inst_debug[i.first] = 0;
764 }
765 }
766 }
767
debugPrintModel()768 void Instantiate::debugPrintModel()
769 {
770 if (Trace.isOn("inst-per-quant"))
771 {
772 for (std::pair<const Node, int>& i : d_total_inst_debug)
773 {
774 Trace("inst-per-quant") << " * " << i.second << " for " << i.first
775 << std::endl;
776 }
777 }
778 }
779
Statistics()780 Instantiate::Statistics::Statistics()
781 : d_instantiations("Instantiate::Instantiations_Total", 0),
782 d_inst_duplicate("Instantiate::Duplicate_Inst", 0),
783 d_inst_duplicate_eq("Instantiate::Duplicate_Inst_Eq", 0),
784 d_inst_duplicate_ent("Instantiate::Duplicate_Inst_Entailed", 0),
785 d_inst_duplicate_model_true("Instantiate::Duplicate_Inst_Model_True", 0)
786 {
787 smtStatisticsRegistry()->registerStat(&d_instantiations);
788 smtStatisticsRegistry()->registerStat(&d_inst_duplicate);
789 smtStatisticsRegistry()->registerStat(&d_inst_duplicate_eq);
790 smtStatisticsRegistry()->registerStat(&d_inst_duplicate_ent);
791 smtStatisticsRegistry()->registerStat(&d_inst_duplicate_model_true);
792 }
793
~Statistics()794 Instantiate::Statistics::~Statistics()
795 {
796 smtStatisticsRegistry()->unregisterStat(&d_instantiations);
797 smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate);
798 smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate_eq);
799 smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate_ent);
800 smtStatisticsRegistry()->unregisterStat(&d_inst_duplicate_model_true);
801 }
802
803 } /* CVC4::theory::quantifiers namespace */
804 } /* CVC4::theory namespace */
805 } /* CVC4 namespace */
806