1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Morgan Deters, Tim King |
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 instantiation engine class |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/ematching/instantiation_engine.h" |
17 |
|
|
18 |
|
#include "options/quantifiers_options.h" |
19 |
|
#include "theory/quantifiers/ematching/inst_strategy_e_matching.h" |
20 |
|
#include "theory/quantifiers/ematching/inst_strategy_e_matching_user.h" |
21 |
|
#include "theory/quantifiers/ematching/trigger.h" |
22 |
|
#include "theory/quantifiers/first_order_model.h" |
23 |
|
#include "theory/quantifiers/quantifiers_attributes.h" |
24 |
|
#include "theory/quantifiers/term_database.h" |
25 |
|
#include "theory/quantifiers/term_util.h" |
26 |
|
|
27 |
|
using namespace cvc5::kind; |
28 |
|
using namespace cvc5::context; |
29 |
|
using namespace cvc5::theory::quantifiers::inst; |
30 |
|
|
31 |
|
namespace cvc5 { |
32 |
|
namespace theory { |
33 |
|
namespace quantifiers { |
34 |
|
|
35 |
6503 |
InstantiationEngine::InstantiationEngine(QuantifiersState& qs, |
36 |
|
QuantifiersInferenceManager& qim, |
37 |
|
QuantifiersRegistry& qr, |
38 |
6503 |
TermRegistry& tr) |
39 |
|
: QuantifiersModule(qs, qim, qr, tr), |
40 |
|
d_instStrategies(), |
41 |
|
d_isup(), |
42 |
|
d_i_ag(), |
43 |
|
d_quants(), |
44 |
|
d_trdb(qs, qim, qr, tr), |
45 |
6503 |
d_quant_rel(nullptr) |
46 |
|
{ |
47 |
6503 |
if (options::relevantTriggers()) |
48 |
|
{ |
49 |
4 |
d_quant_rel.reset(new quantifiers::QuantRelevance); |
50 |
|
} |
51 |
6503 |
if (options::eMatching()) { |
52 |
|
// these are the instantiation strategies for E-matching |
53 |
|
// user-provided patterns |
54 |
6501 |
if (options::userPatternsQuant() != options::UserPatMode::IGNORE) |
55 |
|
{ |
56 |
6501 |
d_isup.reset(new InstStrategyUserPatterns(d_trdb, qs, qim, qr, tr)); |
57 |
6501 |
d_instStrategies.push_back(d_isup.get()); |
58 |
|
} |
59 |
|
|
60 |
|
// auto-generated patterns |
61 |
13002 |
d_i_ag.reset(new InstStrategyAutoGenTriggers( |
62 |
6501 |
d_trdb, qs, qim, qr, tr, d_quant_rel.get())); |
63 |
6501 |
d_instStrategies.push_back(d_i_ag.get()); |
64 |
|
} |
65 |
6503 |
} |
66 |
|
|
67 |
13006 |
InstantiationEngine::~InstantiationEngine() {} |
68 |
|
|
69 |
7854 |
void InstantiationEngine::presolve() { |
70 |
23558 |
for( unsigned i=0; i<d_instStrategies.size(); ++i ){ |
71 |
15704 |
d_instStrategies[i]->presolve(); |
72 |
|
} |
73 |
7854 |
} |
74 |
|
|
75 |
2340 |
void InstantiationEngine::doInstantiationRound( Theory::Effort effort ){ |
76 |
2340 |
size_t lastWaiting = d_qim.numPendingLemmas(); |
77 |
|
//iterate over an internal effort level e |
78 |
2340 |
int e = 0; |
79 |
2340 |
int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2; |
80 |
2340 |
bool finished = false; |
81 |
|
//while unfinished, try effort level=0,1,2.... |
82 |
11700 |
while( !finished && e<=eLimit ){ |
83 |
4680 |
Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl; |
84 |
4680 |
finished = true; |
85 |
|
//instantiate each quantifier |
86 |
85996 |
for( unsigned i=0; i<d_quants.size(); i++ ){ |
87 |
162632 |
Node q = d_quants[i]; |
88 |
81316 |
Debug("inst-engine-debug") << "IE: Instantiate " << q << "..." << std::endl; |
89 |
|
//int e_use = d_quantEngine->getRelevance( q )==-1 ? e - 1 : e; |
90 |
81316 |
int e_use = e; |
91 |
81316 |
if( e_use>=0 ){ |
92 |
81316 |
Trace("inst-engine-debug") << "inst-engine : " << q << std::endl; |
93 |
|
//check each instantiation strategy |
94 |
243948 |
for( unsigned j=0; j<d_instStrategies.size(); j++ ){ |
95 |
162632 |
InstStrategy* is = d_instStrategies[j]; |
96 |
162632 |
Trace("inst-engine-debug") << "Do " << is->identify() << " " << e_use << std::endl; |
97 |
162632 |
InstStrategyStatus quantStatus = is->process(q, effort, e_use); |
98 |
325264 |
Trace("inst-engine-debug") |
99 |
162632 |
<< " -> unfinished= " |
100 |
325264 |
<< (quantStatus == InstStrategyStatus::STATUS_UNFINISHED) |
101 |
162632 |
<< ", conflict=" << d_qstate.isInConflict() << std::endl; |
102 |
162632 |
if (d_qstate.isInConflict()) |
103 |
|
{ |
104 |
|
return; |
105 |
|
} |
106 |
162632 |
else if (quantStatus == InstStrategyStatus::STATUS_UNFINISHED) |
107 |
|
{ |
108 |
67292 |
finished = false; |
109 |
|
} |
110 |
|
} |
111 |
|
} |
112 |
|
} |
113 |
|
//do not consider another level if already added lemma at this level |
114 |
4680 |
if (d_qim.numPendingLemmas() > lastWaiting) |
115 |
|
{ |
116 |
1206 |
finished = true; |
117 |
|
} |
118 |
4680 |
e++; |
119 |
|
} |
120 |
|
} |
121 |
|
|
122 |
67032 |
bool InstantiationEngine::needsCheck( Theory::Effort e ){ |
123 |
67032 |
return d_qstate.getInstWhenNeedsCheck(e); |
124 |
|
} |
125 |
|
|
126 |
24317 |
void InstantiationEngine::reset_round( Theory::Effort e ){ |
127 |
|
//if not, proceed to instantiation round |
128 |
|
//reset the instantiation strategies |
129 |
72945 |
for( unsigned i=0; i<d_instStrategies.size(); ++i ){ |
130 |
48628 |
InstStrategy* is = d_instStrategies[i]; |
131 |
48628 |
is->processResetInstantiationRound( e ); |
132 |
|
} |
133 |
24317 |
} |
134 |
|
|
135 |
38538 |
void InstantiationEngine::check(Theory::Effort e, QEffort quant_e) |
136 |
|
{ |
137 |
51681 |
CodeTimer codeTimer(d_qstate.getStats().d_ematching_time); |
138 |
38538 |
if (quant_e != QEFFORT_STANDARD) |
139 |
|
{ |
140 |
25395 |
return; |
141 |
|
} |
142 |
13143 |
double clSet = 0; |
143 |
13143 |
if (Trace.isOn("inst-engine")) |
144 |
|
{ |
145 |
|
clSet = double(clock()) / double(CLOCKS_PER_SEC); |
146 |
|
Trace("inst-engine") << "---Instantiation Engine Round, effort = " << e |
147 |
|
<< "---" << std::endl; |
148 |
|
} |
149 |
|
// collect all active quantified formulas belonging to this |
150 |
13143 |
bool quantActive = false; |
151 |
13143 |
d_quants.clear(); |
152 |
13143 |
FirstOrderModel* m = d_treg.getModel(); |
153 |
13143 |
size_t nquant = m->getNumAssertedQuantifiers(); |
154 |
70342 |
for (size_t i = 0; i < nquant; i++) |
155 |
|
{ |
156 |
114398 |
Node q = m->getAssertedQuantifier(i, true); |
157 |
57199 |
if (shouldProcess(q) && m->isQuantifierActive(q)) |
158 |
|
{ |
159 |
40658 |
quantActive = true; |
160 |
40658 |
d_quants.push_back(q); |
161 |
|
} |
162 |
|
} |
163 |
26286 |
Trace("inst-engine-debug") |
164 |
13143 |
<< "InstEngine: check: # asserted quantifiers " << d_quants.size() << "/"; |
165 |
13143 |
Trace("inst-engine-debug") << nquant << " " << quantActive << std::endl; |
166 |
13143 |
if (quantActive) |
167 |
|
{ |
168 |
2340 |
size_t lastWaiting = d_qim.numPendingLemmas(); |
169 |
2340 |
doInstantiationRound(e); |
170 |
2340 |
if (d_qstate.isInConflict()) |
171 |
|
{ |
172 |
|
Assert(d_qim.numPendingLemmas() > lastWaiting); |
173 |
|
Trace("inst-engine") << "Conflict, added lemmas = " |
174 |
|
<< (d_qim.numPendingLemmas() - lastWaiting) |
175 |
|
<< std::endl; |
176 |
|
} |
177 |
2340 |
else if (d_qim.hasPendingLemma()) |
178 |
|
{ |
179 |
2412 |
Trace("inst-engine") << "Added lemmas = " |
180 |
2412 |
<< (d_qim.numPendingLemmas() - lastWaiting) |
181 |
1206 |
<< std::endl; |
182 |
|
} |
183 |
|
} |
184 |
|
else |
185 |
|
{ |
186 |
10803 |
d_quants.clear(); |
187 |
|
} |
188 |
13143 |
if (Trace.isOn("inst-engine")) |
189 |
|
{ |
190 |
|
double clSet2 = double(clock()) / double(CLOCKS_PER_SEC); |
191 |
|
Trace("inst-engine") << "Finished instantiation engine, time = " |
192 |
|
<< (clSet2 - clSet) << std::endl; |
193 |
|
} |
194 |
|
} |
195 |
|
|
196 |
574 |
bool InstantiationEngine::checkCompleteFor( Node q ) { |
197 |
|
//TODO? |
198 |
574 |
return false; |
199 |
|
} |
200 |
|
|
201 |
22735 |
void InstantiationEngine::checkOwnership(Node q) |
202 |
|
{ |
203 |
22735 |
if( options::strictTriggers() && q.getNumChildren()==3 ){ |
204 |
|
//if strict triggers, take ownership of this quantified formula |
205 |
|
bool hasPat = false; |
206 |
|
for( unsigned i=0; i<q[2].getNumChildren(); i++ ){ |
207 |
|
if( q[2][i].getKind()==INST_PATTERN || q[2][i].getKind()==INST_NO_PATTERN ){ |
208 |
|
hasPat = true; |
209 |
|
break; |
210 |
|
} |
211 |
|
} |
212 |
|
if( hasPat ){ |
213 |
|
d_qreg.setOwner(q, this, 1); |
214 |
|
} |
215 |
|
} |
216 |
22735 |
} |
217 |
|
|
218 |
22735 |
void InstantiationEngine::registerQuantifier(Node q) |
219 |
|
{ |
220 |
22735 |
if (!shouldProcess(q)) |
221 |
|
{ |
222 |
3393 |
return; |
223 |
|
} |
224 |
19342 |
if (d_quant_rel) |
225 |
|
{ |
226 |
344 |
d_quant_rel->registerQuantifier(q); |
227 |
|
} |
228 |
|
// take into account user patterns |
229 |
19342 |
if (q.getNumChildren() == 3) |
230 |
|
{ |
231 |
8284 |
Node subsPat = d_qreg.substituteBoundVariablesToInstConstants(q[2], q); |
232 |
|
// add patterns |
233 |
8610 |
for (const Node& p : subsPat) |
234 |
|
{ |
235 |
4468 |
if (p.getKind() == INST_PATTERN) |
236 |
|
{ |
237 |
4065 |
addUserPattern(q, p); |
238 |
|
} |
239 |
403 |
else if (p.getKind() == INST_NO_PATTERN) |
240 |
|
{ |
241 |
8 |
addUserNoPattern(q, p); |
242 |
|
} |
243 |
|
} |
244 |
|
} |
245 |
|
} |
246 |
|
|
247 |
4065 |
void InstantiationEngine::addUserPattern(Node q, Node pat) { |
248 |
4065 |
if (d_isup) { |
249 |
4065 |
d_isup->addUserPattern(q, pat); |
250 |
|
} |
251 |
4065 |
} |
252 |
|
|
253 |
8 |
void InstantiationEngine::addUserNoPattern(Node q, Node pat) { |
254 |
8 |
if (d_i_ag) { |
255 |
8 |
d_i_ag->addUserNoPattern(q, pat); |
256 |
|
} |
257 |
8 |
} |
258 |
|
|
259 |
79934 |
bool InstantiationEngine::shouldProcess(Node q) |
260 |
|
{ |
261 |
79934 |
if (!d_qreg.hasOwnership(q, this)) |
262 |
|
{ |
263 |
17047 |
return false; |
264 |
|
} |
265 |
|
// also ignore internal quantifiers |
266 |
62887 |
QuantAttributes& qattr = d_qreg.getQuantAttributes(); |
267 |
62887 |
if (qattr.isInternal(q)) |
268 |
|
{ |
269 |
2843 |
return false; |
270 |
|
} |
271 |
60044 |
return true; |
272 |
|
} |
273 |
|
|
274 |
|
} // namespace quantifiers |
275 |
|
} // namespace theory |
276 |
29340 |
} // namespace cvc5 |