1 /********************* */
2 /*! \file instantiation_engine.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Morgan Deters, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 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
12 ** \brief Implementation of instantiation engine class
15 #include "theory/quantifiers/ematching/instantiation_engine.h"
17 #include "options/quantifiers_options.h"
18 #include "theory/quantifiers/ematching/inst_strategy_e_matching.h"
19 #include "theory/quantifiers/ematching/inst_strategy_e_matching_user.h"
20 #include "theory/quantifiers/ematching/trigger.h"
21 #include "theory/quantifiers/first_order_model.h"
22 #include "theory/quantifiers/quantifiers_attributes.h"
23 #include "theory/quantifiers/term_database.h"
24 #include "theory/quantifiers/term_util.h"
25 #include "theory/quantifiers_engine.h"
28 using namespace CVC4::kind
;
29 using namespace CVC4::context
;
30 using namespace CVC4::theory::inst
;
34 namespace quantifiers
{
36 InstantiationEngine::InstantiationEngine(QuantifiersEngine
* qe
,
38 QuantifiersInferenceManager
& qim
,
39 QuantifiersRegistry
& qr
)
40 : QuantifiersModule(qs
, qim
, qr
, qe
),
47 if (options::relevantTriggers())
49 d_quant_rel
.reset(new quantifiers::QuantRelevance
);
51 if (options::eMatching()) {
52 // these are the instantiation strategies for E-matching
53 // user-provided patterns
54 if (options::userPatternsQuant() != options::UserPatMode::IGNORE
)
56 d_isup
.reset(new InstStrategyUserPatterns(d_quantEngine
, qs
));
57 d_instStrategies
.push_back(d_isup
.get());
60 // auto-generated patterns
62 new InstStrategyAutoGenTriggers(d_quantEngine
, qs
, d_quant_rel
.get()));
63 d_instStrategies
.push_back(d_i_ag
.get());
67 InstantiationEngine::~InstantiationEngine() {}
69 void InstantiationEngine::presolve() {
70 for( unsigned i
=0; i
<d_instStrategies
.size(); ++i
){
71 d_instStrategies
[i
]->presolve();
75 void InstantiationEngine::doInstantiationRound( Theory::Effort effort
){
76 unsigned lastWaiting
= d_quantEngine
->getNumLemmasWaiting();
77 //iterate over an internal effort level e
79 int eLimit
= effort
==Theory::EFFORT_LAST_CALL
? 10 : 2;
80 bool finished
= false;
81 //while unfinished, try effort level=0,1,2....
82 while( !finished
&& e
<=eLimit
){
83 Debug("inst-engine") << "IE: Prepare instantiation (" << e
<< ")." << std::endl
;
85 //instantiate each quantifier
86 for( unsigned i
=0; i
<d_quants
.size(); i
++ ){
88 Debug("inst-engine-debug") << "IE: Instantiate " << q
<< "..." << std::endl
;
89 //int e_use = d_quantEngine->getRelevance( q )==-1 ? e - 1 : e;
92 Trace("inst-engine-debug") << "inst-engine : " << q
<< std::endl
;
93 //check each instantiation strategy
94 for( unsigned j
=0; j
<d_instStrategies
.size(); j
++ ){
95 InstStrategy
* is
= d_instStrategies
[j
];
96 Trace("inst-engine-debug") << "Do " << is
->identify() << " " << e_use
<< std::endl
;
97 InstStrategyStatus quantStatus
= is
->process(q
, effort
, e_use
);
98 Trace("inst-engine-debug")
100 << (quantStatus
== InstStrategyStatus::STATUS_UNFINISHED
)
101 << ", conflict=" << d_qstate
.isInConflict() << std::endl
;
102 if (d_qstate
.isInConflict())
106 else if (quantStatus
== InstStrategyStatus::STATUS_UNFINISHED
)
113 //do not consider another level if already added lemma at this level
114 if( d_quantEngine
->getNumLemmasWaiting()>lastWaiting
){
121 bool InstantiationEngine::needsCheck( Theory::Effort e
){
122 return d_quantEngine
->getInstWhenNeedsCheck( e
);
125 void InstantiationEngine::reset_round( Theory::Effort e
){
126 //if not, proceed to instantiation round
127 //reset the instantiation strategies
128 for( unsigned i
=0; i
<d_instStrategies
.size(); ++i
){
129 InstStrategy
* is
= d_instStrategies
[i
];
130 is
->processResetInstantiationRound( e
);
134 void InstantiationEngine::check(Theory::Effort e
, QEffort quant_e
)
136 CodeTimer
codeTimer(d_quantEngine
->d_statistics
.d_ematching_time
);
137 if (quant_e
!= QEFFORT_STANDARD
)
142 if (Trace
.isOn("inst-engine"))
144 clSet
= double(clock()) / double(CLOCKS_PER_SEC
);
145 Trace("inst-engine") << "---Instantiation Engine Round, effort = " << e
146 << "---" << std::endl
;
148 // collect all active quantified formulas belonging to this
149 bool quantActive
= false;
151 FirstOrderModel
* m
= d_quantEngine
->getModel();
152 size_t nquant
= m
->getNumAssertedQuantifiers();
153 for (size_t i
= 0; i
< nquant
; i
++)
155 Node q
= d_quantEngine
->getModel()->getAssertedQuantifier(i
, true);
156 if (shouldProcess(q
) && m
->isQuantifierActive(q
))
159 d_quants
.push_back(q
);
162 Trace("inst-engine-debug")
163 << "InstEngine: check: # asserted quantifiers " << d_quants
.size() << "/";
164 Trace("inst-engine-debug") << nquant
<< " " << quantActive
<< std::endl
;
167 unsigned lastWaiting
= d_quantEngine
->getNumLemmasWaiting();
168 doInstantiationRound(e
);
169 if (d_qstate
.isInConflict())
171 Assert(d_quantEngine
->getNumLemmasWaiting() > lastWaiting
);
172 Trace("inst-engine") << "Conflict, added lemmas = "
173 << (d_quantEngine
->getNumLemmasWaiting()
177 else if (d_quantEngine
->hasAddedLemma())
179 Trace("inst-engine") << "Added lemmas = "
180 << (d_quantEngine
->getNumLemmasWaiting()
189 if (Trace
.isOn("inst-engine"))
191 double clSet2
= double(clock()) / double(CLOCKS_PER_SEC
);
192 Trace("inst-engine") << "Finished instantiation engine, time = "
193 << (clSet2
- clSet
) << std::endl
;
197 bool InstantiationEngine::checkCompleteFor( Node q
) {
202 void InstantiationEngine::checkOwnership(Node q
)
204 if( options::strictTriggers() && q
.getNumChildren()==3 ){
205 //if strict triggers, take ownership of this quantified formula
207 for( unsigned i
=0; i
<q
[2].getNumChildren(); i
++ ){
208 if( q
[2][i
].getKind()==INST_PATTERN
|| q
[2][i
].getKind()==INST_NO_PATTERN
){
214 d_qreg
.setOwner(q
, this, 1);
219 void InstantiationEngine::registerQuantifier(Node q
)
221 if (!shouldProcess(q
))
227 d_quant_rel
->registerQuantifier(q
);
229 // take into account user patterns
230 if (q
.getNumChildren() == 3)
233 d_quantEngine
->getTermUtil()->substituteBoundVariablesToInstConstants(
236 for (const Node
& p
: subsPat
)
238 if (p
.getKind() == INST_PATTERN
)
240 addUserPattern(q
, p
);
242 else if (p
.getKind() == INST_NO_PATTERN
)
244 addUserNoPattern(q
, p
);
250 void InstantiationEngine::addUserPattern(Node q
, Node pat
) {
252 d_isup
->addUserPattern(q
, pat
);
256 void InstantiationEngine::addUserNoPattern(Node q
, Node pat
) {
258 d_i_ag
->addUserNoPattern(q
, pat
);
262 bool InstantiationEngine::shouldProcess(Node q
)
264 if (!d_qreg
.hasOwnership(q
, this))
268 // also ignore internal quantifiers
269 QuantAttributes
* qattr
= d_quantEngine
->getQuantAttributes();
270 if (qattr
->isInternal(q
))
277 } // namespace quantifiers
278 } // namespace theory