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 inst match generator class. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/ematching/inst_match_generator.h" |
17 |
|
|
18 |
|
#include "expr/dtype_cons.h" |
19 |
|
#include "options/quantifiers_options.h" |
20 |
|
#include "theory/datatypes/theory_datatypes_utils.h" |
21 |
|
#include "theory/quantifiers/ematching/candidate_generator.h" |
22 |
|
#include "theory/quantifiers/ematching/inst_match_generator_multi.h" |
23 |
|
#include "theory/quantifiers/ematching/inst_match_generator_multi_linear.h" |
24 |
|
#include "theory/quantifiers/ematching/inst_match_generator_simple.h" |
25 |
|
#include "theory/quantifiers/ematching/pattern_term_selector.h" |
26 |
|
#include "theory/quantifiers/ematching/relational_match_generator.h" |
27 |
|
#include "theory/quantifiers/ematching/var_match_generator.h" |
28 |
|
#include "theory/quantifiers/instantiate.h" |
29 |
|
#include "theory/quantifiers/quantifiers_state.h" |
30 |
|
#include "theory/quantifiers/term_database.h" |
31 |
|
#include "theory/quantifiers/term_registry.h" |
32 |
|
#include "theory/quantifiers/term_util.h" |
33 |
|
#include "util/rational.h" |
34 |
|
|
35 |
|
using namespace cvc5::kind; |
36 |
|
|
37 |
|
namespace cvc5 { |
38 |
|
namespace theory { |
39 |
|
namespace quantifiers { |
40 |
|
namespace inst { |
41 |
|
|
42 |
37036 |
InstMatchGenerator::InstMatchGenerator(Trigger* tparent, Node pat) |
43 |
37036 |
: IMGenerator(tparent) |
44 |
|
{ |
45 |
37036 |
d_cg = nullptr; |
46 |
37036 |
d_needsReset = true; |
47 |
37036 |
d_active_add = true; |
48 |
37036 |
Assert(pat.isNull() || quantifiers::TermUtil::hasInstConstAttr(pat)); |
49 |
37036 |
d_pattern = pat; |
50 |
37036 |
d_match_pattern = pat; |
51 |
37036 |
if (!pat.isNull()) |
52 |
|
{ |
53 |
35688 |
d_match_pattern_type = pat.getType(); |
54 |
|
} |
55 |
37036 |
d_next = nullptr; |
56 |
37036 |
d_independent_gen = false; |
57 |
37036 |
} |
58 |
|
|
59 |
109760 |
InstMatchGenerator::~InstMatchGenerator() |
60 |
|
{ |
61 |
64487 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
62 |
27451 |
delete d_children[i]; |
63 |
|
} |
64 |
37036 |
delete d_cg; |
65 |
72724 |
} |
66 |
|
|
67 |
103 |
void InstMatchGenerator::setActiveAdd(bool val){ |
68 |
103 |
d_active_add = val; |
69 |
103 |
if (d_next != nullptr) |
70 |
|
{ |
71 |
80 |
d_next->setActiveAdd(val); |
72 |
|
} |
73 |
103 |
} |
74 |
|
|
75 |
|
int InstMatchGenerator::getActiveScore() |
76 |
|
{ |
77 |
|
if( d_match_pattern.isNull() ){ |
78 |
|
return -1; |
79 |
|
} |
80 |
|
quantifiers::TermDb* tdb = d_treg.getTermDatabase(); |
81 |
|
if (TriggerTermInfo::isAtomicTrigger(d_match_pattern)) |
82 |
|
{ |
83 |
|
Node f = tdb->getMatchOperator(d_match_pattern); |
84 |
|
unsigned ngt = tdb->getNumGroundTerms(f); |
85 |
|
Trace("trigger-active-sel-debug") << "Number of ground terms for " << f << " is " << ngt << std::endl; |
86 |
|
return ngt; |
87 |
|
}else if( d_match_pattern.getKind()==INST_CONSTANT ){ |
88 |
|
TypeNode tn = d_match_pattern.getType(); |
89 |
|
unsigned ngtt = tdb->getNumTypeGroundTerms(tn); |
90 |
|
Trace("trigger-active-sel-debug") << "Number of ground terms for " << tn << " is " << ngtt << std::endl; |
91 |
|
return ngtt; |
92 |
|
} |
93 |
|
return -1; |
94 |
|
} |
95 |
|
|
96 |
37036 |
void InstMatchGenerator::initialize(Node q, |
97 |
|
std::vector<InstMatchGenerator*>& gens) |
98 |
|
{ |
99 |
37036 |
if (d_pattern.isNull()) |
100 |
|
{ |
101 |
1348 |
gens.insert(gens.end(), d_children.begin(), d_children.end()); |
102 |
1348 |
return; |
103 |
|
} |
104 |
71376 |
Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern |
105 |
35688 |
<< std::endl; |
106 |
35688 |
if (d_match_pattern.getKind() == NOT) |
107 |
|
{ |
108 |
2168 |
Assert(d_pattern.getKind() == NOT); |
109 |
|
// we want to add the children of the NOT |
110 |
2168 |
d_match_pattern = d_match_pattern[0]; |
111 |
|
} |
112 |
|
|
113 |
73544 |
if (d_pattern.getKind() == NOT && d_match_pattern.getKind() == EQUAL |
114 |
37856 |
&& d_match_pattern[0].getKind() == INST_CONSTANT |
115 |
71432 |
&& d_match_pattern[1].getKind() == INST_CONSTANT) |
116 |
|
{ |
117 |
|
// special case: disequalities between variables x != y will match ground |
118 |
|
// disequalities. |
119 |
|
} |
120 |
71362 |
else if (d_match_pattern.getKind() == EQUAL |
121 |
35681 |
|| d_match_pattern.getKind() == GEQ) |
122 |
|
{ |
123 |
|
// We are one of the following cases: |
124 |
|
// f(x)~a, f(x)~y, x~a, x~y |
125 |
|
// If we are the first or third case, we ensure that f(x)/x is on the left |
126 |
|
// hand side of the relation d_pattern, d_match_pattern is f(x)/x and |
127 |
|
// d_eq_class_rel (indicating the equivalence class that we are related |
128 |
|
// to) is set to a. |
129 |
2191 |
for (size_t i = 0; i < 2; i++) |
130 |
|
{ |
131 |
2199 |
Node mp = d_match_pattern[i]; |
132 |
2199 |
Node mpo = d_match_pattern[1 - i]; |
133 |
|
// If this side has free variables, and the other side does not or |
134 |
|
// it is a free variable, then we will match on this side of the |
135 |
|
// relation. |
136 |
6573 |
if (quantifiers::TermUtil::hasInstConstAttr(mp) |
137 |
8756 |
&& (!quantifiers::TermUtil::hasInstConstAttr(mpo) |
138 |
19 |
|| mpo.getKind() == INST_CONSTANT)) |
139 |
|
{ |
140 |
2183 |
if (i == 1) |
141 |
|
{ |
142 |
8 |
if (d_match_pattern.getKind() == GEQ) |
143 |
|
{ |
144 |
|
d_pattern = NodeManager::currentNM()->mkNode(kind::GT, mp, mpo); |
145 |
|
d_pattern = d_pattern.negate(); |
146 |
|
} |
147 |
|
else |
148 |
|
{ |
149 |
16 |
d_pattern = NodeManager::currentNM()->mkNode( |
150 |
8 |
d_match_pattern.getKind(), mp, mpo); |
151 |
|
} |
152 |
|
} |
153 |
2183 |
d_eq_class_rel = mpo; |
154 |
2183 |
d_match_pattern = mp; |
155 |
|
// we won't find a term in the other direction |
156 |
2183 |
break; |
157 |
|
} |
158 |
|
} |
159 |
|
} |
160 |
35688 |
d_match_pattern_type = d_match_pattern.getType(); |
161 |
71376 |
Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " |
162 |
35688 |
<< d_match_pattern << std::endl; |
163 |
35688 |
quantifiers::TermDb* tdb = d_treg.getTermDatabase(); |
164 |
35688 |
d_match_pattern_op = tdb->getMatchOperator(d_match_pattern); |
165 |
|
|
166 |
|
// now, collect children of d_match_pattern |
167 |
35688 |
Kind mpk = d_match_pattern.getKind(); |
168 |
35688 |
if (mpk == INST_CONSTANT) |
169 |
|
{ |
170 |
150 |
d_children_types.push_back( |
171 |
150 |
d_match_pattern.getAttribute(InstVarNumAttribute())); |
172 |
|
} |
173 |
|
else |
174 |
|
{ |
175 |
100934 |
for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++) |
176 |
|
{ |
177 |
130642 |
Node pat = d_match_pattern[i]; |
178 |
130642 |
Node qa = quantifiers::TermUtil::getInstConstAttr(pat); |
179 |
65321 |
if (!qa.isNull()) |
180 |
|
{ |
181 |
58473 |
if (pat.getKind() == INST_CONSTANT && qa == q) |
182 |
|
{ |
183 |
33990 |
d_children_types.push_back(pat.getAttribute(InstVarNumAttribute())); |
184 |
|
} |
185 |
|
else |
186 |
|
{ |
187 |
24483 |
InstMatchGenerator* cimg = getInstMatchGenerator(d_tparent, q, pat); |
188 |
24483 |
if (cimg) |
189 |
|
{ |
190 |
24483 |
d_children.push_back(cimg); |
191 |
24483 |
d_children_index.push_back(i); |
192 |
24483 |
d_children_types.push_back(-2); |
193 |
|
} |
194 |
|
else |
195 |
|
{ |
196 |
|
d_children_types.push_back(-1); |
197 |
|
} |
198 |
|
} |
199 |
|
} |
200 |
|
else |
201 |
|
{ |
202 |
6848 |
d_children_types.push_back(-1); |
203 |
|
} |
204 |
|
} |
205 |
|
} |
206 |
|
|
207 |
|
// create candidate generator |
208 |
35688 |
if (mpk == APPLY_SELECTOR) |
209 |
|
{ |
210 |
|
// candidates for apply selector are a union of correctly and incorrectly |
211 |
|
// applied selectors |
212 |
626 |
d_cg = |
213 |
313 |
new inst::CandidateGeneratorSelector(d_qstate, d_treg, d_match_pattern); |
214 |
|
} |
215 |
35375 |
else if (TriggerTermInfo::isAtomicTriggerKind(mpk)) |
216 |
|
{ |
217 |
35293 |
if (mpk == APPLY_CONSTRUCTOR) |
218 |
|
{ |
219 |
|
// 1-constructors have a trivial way of generating candidates in a |
220 |
|
// given equivalence class |
221 |
4994 |
const DType& dt = d_match_pattern.getType().getDType(); |
222 |
4994 |
if (dt.getNumConstructors() == 1) |
223 |
|
{ |
224 |
6034 |
d_cg = new inst::CandidateGeneratorConsExpand( |
225 |
3017 |
d_qstate, d_treg, d_match_pattern); |
226 |
|
} |
227 |
|
} |
228 |
35293 |
if (d_cg == nullptr) |
229 |
|
{ |
230 |
|
CandidateGeneratorQE* cg = |
231 |
32276 |
new CandidateGeneratorQE(d_qstate, d_treg, d_match_pattern); |
232 |
|
// we will be scanning lists trying to find ground terms whose operator |
233 |
|
// is the same as d_match_operator's. |
234 |
32276 |
d_cg = cg; |
235 |
|
// if matching on disequality, inform the candidate generator not to |
236 |
|
// match on eqc |
237 |
32276 |
if (d_pattern.getKind() == NOT && d_pattern[0].getKind() == EQUAL) |
238 |
|
{ |
239 |
2112 |
cg->excludeEqc(d_eq_class_rel); |
240 |
2112 |
d_eq_class_rel = Node::null(); |
241 |
|
} |
242 |
|
} |
243 |
|
} |
244 |
82 |
else if (mpk == INST_CONSTANT) |
245 |
|
{ |
246 |
75 |
if (d_pattern.getKind() == APPLY_SELECTOR_TOTAL) |
247 |
|
{ |
248 |
|
Node selectorExpr = tdb->getMatchOperator(d_pattern); |
249 |
|
size_t selectorIndex = datatypes::utils::cindexOf(selectorExpr); |
250 |
|
const DType& dt = datatypes::utils::datatypeOf(selectorExpr); |
251 |
|
const DTypeConstructor& c = dt[selectorIndex]; |
252 |
|
Node cOp = c.getConstructor(); |
253 |
|
Trace("inst-match-gen") |
254 |
|
<< "Purify dt trigger " << d_pattern << ", will match terms of op " |
255 |
|
<< cOp << std::endl; |
256 |
|
d_cg = new inst::CandidateGeneratorQE(d_qstate, d_treg, cOp); |
257 |
|
}else{ |
258 |
75 |
d_cg = new CandidateGeneratorQEAll(d_qstate, d_treg, d_match_pattern); |
259 |
|
} |
260 |
|
} |
261 |
7 |
else if (mpk == EQUAL) |
262 |
|
{ |
263 |
|
// we will be producing candidates via literal matching heuristics |
264 |
7 |
if (d_pattern.getKind() == NOT) |
265 |
|
{ |
266 |
|
// candidates will be all disequalities |
267 |
14 |
d_cg = new inst::CandidateGeneratorQELitDeq( |
268 |
7 |
d_qstate, d_treg, d_match_pattern); |
269 |
|
} |
270 |
|
} |
271 |
|
else |
272 |
|
{ |
273 |
|
Trace("inst-match-gen-warn") |
274 |
|
<< "(?) Unknown matching pattern is " << d_match_pattern << std::endl; |
275 |
|
} |
276 |
71376 |
Trace("inst-match-gen") << "Candidate generator is " |
277 |
71376 |
<< (d_cg != nullptr ? d_cg->identify() : "null") |
278 |
35688 |
<< std::endl; |
279 |
35688 |
gens.insert( gens.end(), d_children.begin(), d_children.end() ); |
280 |
|
} |
281 |
|
|
282 |
|
/** get match (not modulo equality) */ |
283 |
2454448 |
int InstMatchGenerator::getMatch(Node f, Node t, InstMatch& m) |
284 |
|
{ |
285 |
4908896 |
Trace("matching") << "Matching " << t << " against pattern " << d_match_pattern << " (" |
286 |
2454448 |
<< m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl; |
287 |
2454448 |
Assert(!d_match_pattern.isNull()); |
288 |
2454448 |
if (d_cg == nullptr) |
289 |
|
{ |
290 |
|
Trace("matching-fail") << "Internal error for match generator." << std::endl; |
291 |
|
return -2; |
292 |
|
} |
293 |
2454448 |
bool success = true; |
294 |
4908896 |
std::vector<int> prev; |
295 |
|
// if t is null |
296 |
2454448 |
Assert(!t.isNull()); |
297 |
2454448 |
Assert(!quantifiers::TermUtil::hasInstConstAttr(t)); |
298 |
|
// notice that t may have a different kind or operator from our match |
299 |
|
// pattern, e.g. for APPLY_SELECTOR triggers. |
300 |
|
// first, check if ground arguments are not equal, or a match is in conflict |
301 |
2454448 |
Trace("matching-debug2") << "Setting immediate matches..." << std::endl; |
302 |
3522901 |
for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++) |
303 |
|
{ |
304 |
3118693 |
int64_t ct = d_children_types[i]; |
305 |
3118693 |
if (ct >= 0) |
306 |
|
{ |
307 |
3993232 |
Trace("matching-debug2") |
308 |
1996616 |
<< "Setting " << ct << " to " << t[i] << "..." << std::endl; |
309 |
1996616 |
bool addToPrev = m.get(ct).isNull(); |
310 |
1996616 |
if (!m.set(d_qstate, ct, t[i])) |
311 |
|
{ |
312 |
|
// match is in conflict |
313 |
2622680 |
Trace("matching-fail") |
314 |
1311340 |
<< "Match fail: " << m.get(ct) << " and " << t[i] << std::endl; |
315 |
1311340 |
success = false; |
316 |
3361580 |
break; |
317 |
|
} |
318 |
685276 |
else if (addToPrev) |
319 |
|
{ |
320 |
638102 |
Trace("matching-debug2") << "Success." << std::endl; |
321 |
638102 |
prev.push_back(ct); |
322 |
|
} |
323 |
|
} |
324 |
1122077 |
else if (ct == -1) |
325 |
|
{ |
326 |
763696 |
if (!d_qstate.areEqual(d_match_pattern[i], t[i])) |
327 |
|
{ |
328 |
1477800 |
Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i] |
329 |
738900 |
<< " and " << t[i] << std::endl; |
330 |
|
// ground arguments are not equal |
331 |
738900 |
success = false; |
332 |
738900 |
break; |
333 |
|
} |
334 |
|
} |
335 |
|
} |
336 |
4908896 |
Trace("matching-debug2") << "Done setting immediate matches, success = " |
337 |
2454448 |
<< success << "." << std::endl; |
338 |
|
// for variable matching |
339 |
2454448 |
if (d_match_pattern.getKind() == INST_CONSTANT) |
340 |
|
{ |
341 |
110 |
bool addToPrev = m.get(d_children_types[0]).isNull(); |
342 |
110 |
if (!m.set(d_qstate, d_children_types[0], t)) |
343 |
|
{ |
344 |
|
success = false; |
345 |
|
} |
346 |
|
else |
347 |
|
{ |
348 |
110 |
if (addToPrev) |
349 |
|
{ |
350 |
110 |
prev.push_back(d_children_types[0]); |
351 |
|
} |
352 |
|
} |
353 |
|
} |
354 |
|
// for relational matching |
355 |
2454448 |
if (!d_eq_class_rel.isNull() && d_eq_class_rel.getKind() == INST_CONSTANT) |
356 |
|
{ |
357 |
28 |
NodeManager* nm = NodeManager::currentNM(); |
358 |
28 |
int v = d_eq_class_rel.getAttribute(InstVarNumAttribute()); |
359 |
|
// also must fit match to equivalence class |
360 |
28 |
bool pol = d_pattern.getKind() != NOT; |
361 |
56 |
Node pat = d_pattern.getKind() == NOT ? d_pattern[0] : d_pattern; |
362 |
56 |
Node t_match; |
363 |
28 |
if (pol) |
364 |
|
{ |
365 |
28 |
if (pat.getKind() == GT) |
366 |
|
{ |
367 |
|
t_match = nm->mkNode(MINUS, t, nm->mkConst(Rational(1))); |
368 |
|
}else{ |
369 |
28 |
t_match = t; |
370 |
|
} |
371 |
|
} |
372 |
|
else |
373 |
|
{ |
374 |
|
if (pat.getKind() == EQUAL) |
375 |
|
{ |
376 |
|
if (t.getType().isBoolean()) |
377 |
|
{ |
378 |
|
t_match = nm->mkConst(!d_qstate.areEqual(nm->mkConst(true), t)); |
379 |
|
} |
380 |
|
else |
381 |
|
{ |
382 |
|
Assert(t.getType().isReal()); |
383 |
|
t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1))); |
384 |
|
} |
385 |
|
} |
386 |
|
else if (pat.getKind() == GEQ) |
387 |
|
{ |
388 |
|
t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1))); |
389 |
|
} |
390 |
|
else if (pat.getKind() == GT) |
391 |
|
{ |
392 |
|
t_match = t; |
393 |
|
} |
394 |
|
} |
395 |
28 |
if (!t_match.isNull()) |
396 |
|
{ |
397 |
28 |
bool addToPrev = m.get(v).isNull(); |
398 |
28 |
if (!m.set(d_qstate, v, t_match)) |
399 |
|
{ |
400 |
|
success = false; |
401 |
|
} |
402 |
28 |
else if (addToPrev) |
403 |
|
{ |
404 |
28 |
prev.push_back(v); |
405 |
|
} |
406 |
|
} |
407 |
|
} |
408 |
2454448 |
int ret_val = -1; |
409 |
2454448 |
if (success) |
410 |
|
{ |
411 |
404208 |
Trace("matching-debug2") << "Reset children..." << std::endl; |
412 |
|
// now, fit children into match |
413 |
|
// we will be requesting candidates for matching terms for each child |
414 |
502029 |
for (size_t i = 0, size = d_children.size(); i < size; i++) |
415 |
|
{ |
416 |
310441 |
if (!d_children[i]->reset(t[d_children_index[i]])) |
417 |
|
{ |
418 |
212620 |
success = false; |
419 |
212620 |
break; |
420 |
|
} |
421 |
|
} |
422 |
404208 |
if (success) |
423 |
|
{ |
424 |
191588 |
Trace("matching-debug2") << "Continue next " << d_next << std::endl; |
425 |
191588 |
ret_val = |
426 |
383176 |
continueNextMatch(f, m, InferenceId::QUANTIFIERS_INST_E_MATCHING); |
427 |
|
} |
428 |
|
} |
429 |
2454448 |
if (ret_val < 0) |
430 |
|
{ |
431 |
3027774 |
for (int& pv : prev) |
432 |
|
{ |
433 |
602450 |
m.d_vals[pv] = Node::null(); |
434 |
|
} |
435 |
|
} |
436 |
2454448 |
return ret_val; |
437 |
|
} |
438 |
|
|
439 |
196203 |
int InstMatchGenerator::continueNextMatch(Node q, |
440 |
|
InstMatch& m, |
441 |
|
InferenceId id) |
442 |
|
{ |
443 |
196203 |
if( d_next!=NULL ){ |
444 |
129484 |
return d_next->getNextMatch(q, m); |
445 |
|
} |
446 |
66719 |
if (d_active_add) |
447 |
|
{ |
448 |
65751 |
return sendInstantiation(m, id) ? 1 : -1; |
449 |
|
} |
450 |
968 |
return 1; |
451 |
|
} |
452 |
|
|
453 |
|
/** reset instantiation round */ |
454 |
262148 |
void InstMatchGenerator::resetInstantiationRound() |
455 |
|
{ |
456 |
262148 |
if( !d_match_pattern.isNull() ){ |
457 |
251177 |
Trace("matching-debug2") << this << " reset instantiation round." << std::endl; |
458 |
251177 |
d_needsReset = true; |
459 |
251177 |
if( d_cg ){ |
460 |
251177 |
d_cg->resetInstantiationRound(); |
461 |
|
} |
462 |
|
} |
463 |
262148 |
if( d_next ){ |
464 |
187826 |
d_next->resetInstantiationRound(); |
465 |
|
} |
466 |
262148 |
d_curr_exclude_match.clear(); |
467 |
262148 |
} |
468 |
|
|
469 |
515051 |
bool InstMatchGenerator::reset(Node eqc) |
470 |
|
{ |
471 |
515051 |
if (d_cg == nullptr) |
472 |
|
{ |
473 |
|
// we did not properly initialize the candidate generator, thus we fail |
474 |
|
return false; |
475 |
|
} |
476 |
515051 |
eqc = d_qstate.getRepresentative(eqc); |
477 |
515051 |
Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl; |
478 |
515051 |
if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){ |
479 |
120 |
d_eq_class = d_eq_class_rel; |
480 |
514931 |
}else if( !eqc.isNull() ){ |
481 |
392438 |
d_eq_class = eqc; |
482 |
|
} |
483 |
|
//we have a specific equivalence class in mind |
484 |
|
//we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term |
485 |
|
//just look in equivalence class of the RHS |
486 |
515051 |
d_cg->reset( d_eq_class ); |
487 |
515051 |
d_needsReset = false; |
488 |
|
|
489 |
|
//generate the first candidate preemptively |
490 |
515051 |
d_curr_first_candidate = Node::null(); |
491 |
1030102 |
Node t; |
492 |
148060 |
do { |
493 |
663111 |
t = d_cg->getNextCandidate(); |
494 |
663111 |
if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){ |
495 |
515051 |
d_curr_first_candidate = t; |
496 |
|
} |
497 |
663111 |
}while( !t.isNull() && d_curr_first_candidate.isNull() ); |
498 |
515051 |
Trace("matching-summary") << "Reset " << d_match_pattern << " in " << eqc << " returns " << !d_curr_first_candidate.isNull() << "." << std::endl; |
499 |
|
|
500 |
515051 |
return !d_curr_first_candidate.isNull(); |
501 |
|
} |
502 |
|
|
503 |
157379 |
int InstMatchGenerator::getNextMatch(Node f, InstMatch& m) |
504 |
|
{ |
505 |
157379 |
if( d_needsReset ){ |
506 |
|
Trace("matching") << "Reset not done yet, must do the reset..." << std::endl; |
507 |
|
reset(d_eq_class); |
508 |
|
} |
509 |
157379 |
d_curr_matched = Node::null(); |
510 |
157379 |
Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl; |
511 |
157379 |
int success = -1; |
512 |
314758 |
Node t = d_curr_first_candidate; |
513 |
2401876 |
do{ |
514 |
2559255 |
Trace("matching-debug2") << "Matching candidate : " << t << std::endl; |
515 |
2559255 |
Assert(!d_qstate.isInConflict()); |
516 |
|
//if t not null, try to fit it into match m |
517 |
2559255 |
if( !t.isNull() ){ |
518 |
2547074 |
if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){ |
519 |
2454448 |
Assert(t.getType().isComparableTo(d_match_pattern_type)); |
520 |
2454448 |
Trace("matching-summary") << "Try " << d_match_pattern << " : " << t << std::endl; |
521 |
2454448 |
success = getMatch(f, t, m); |
522 |
2454448 |
if( d_independent_gen && success<0 ){ |
523 |
26577 |
Assert(d_eq_class.isNull() || !d_eq_class_rel.isNull()); |
524 |
26577 |
d_curr_exclude_match[t] = true; |
525 |
|
} |
526 |
|
} |
527 |
|
//get the next candidate term t |
528 |
2547074 |
if( success<0 ){ |
529 |
2517950 |
t = d_qstate.isInConflict() ? Node::null() : d_cg->getNextCandidate(); |
530 |
|
}else{ |
531 |
29124 |
d_curr_first_candidate = d_cg->getNextCandidate(); |
532 |
|
} |
533 |
|
} |
534 |
2559255 |
}while( success<0 && !t.isNull() ); |
535 |
157379 |
d_curr_matched = t; |
536 |
157379 |
if( success<0 ){ |
537 |
128255 |
Trace("matching-summary") << "..." << d_match_pattern << " failed, reset." << std::endl; |
538 |
128255 |
Trace("matching") << this << " failed, reset " << d_eq_class << std::endl; |
539 |
|
//we failed, must reset |
540 |
128255 |
reset(d_eq_class); |
541 |
|
}else{ |
542 |
29124 |
Trace("matching-summary") << "..." << d_match_pattern << " success." << std::endl; |
543 |
|
} |
544 |
314758 |
return success; |
545 |
|
} |
546 |
|
|
547 |
23389 |
uint64_t InstMatchGenerator::addInstantiations(Node f) |
548 |
|
{ |
549 |
|
//try to add instantiation for each match produced |
550 |
23389 |
uint64_t addedLemmas = 0; |
551 |
46778 |
InstMatch m( f ); |
552 |
45299 |
while (getNextMatch(f, m) > 0) |
553 |
|
{ |
554 |
10955 |
if( !d_active_add ){ |
555 |
|
if (sendInstantiation(m, InferenceId::UNKNOWN)) |
556 |
|
{ |
557 |
|
addedLemmas++; |
558 |
|
if (d_qstate.isInConflict()) |
559 |
|
{ |
560 |
|
break; |
561 |
|
} |
562 |
|
} |
563 |
|
}else{ |
564 |
10955 |
addedLemmas++; |
565 |
10955 |
if (d_qstate.isInConflict()) |
566 |
|
{ |
567 |
|
break; |
568 |
|
} |
569 |
|
} |
570 |
10955 |
m.clear(); |
571 |
|
} |
572 |
|
//return number of lemmas added |
573 |
46778 |
return addedLemmas; |
574 |
|
} |
575 |
|
|
576 |
8255 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(Trigger* tparent, |
577 |
|
Node q, |
578 |
|
Node pat) |
579 |
|
{ |
580 |
16510 |
std::vector< Node > pats; |
581 |
8255 |
pats.push_back( pat ); |
582 |
16510 |
std::map< Node, InstMatchGenerator * > pat_map_init; |
583 |
16510 |
return mkInstMatchGenerator(tparent, q, pats, pat_map_init); |
584 |
|
} |
585 |
|
|
586 |
1330 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGeneratorMulti( |
587 |
|
Trigger* tparent, Node q, std::vector<Node>& pats) |
588 |
|
{ |
589 |
1330 |
Assert(pats.size() > 1); |
590 |
|
InstMatchGeneratorMultiLinear* imgm = |
591 |
1330 |
new InstMatchGeneratorMultiLinear(tparent, q, pats); |
592 |
2660 |
std::vector< InstMatchGenerator* > gens; |
593 |
1330 |
imgm->initialize(q, gens); |
594 |
1330 |
Assert(gens.size() == pats.size()); |
595 |
2660 |
std::vector< Node > patsn; |
596 |
2660 |
std::map< Node, InstMatchGenerator * > pat_map_init; |
597 |
4298 |
for (InstMatchGenerator* g : gens) |
598 |
|
{ |
599 |
5936 |
Node pn = g->d_match_pattern; |
600 |
2968 |
patsn.push_back( pn ); |
601 |
2968 |
pat_map_init[pn] = g; |
602 |
|
} |
603 |
1330 |
imgm->d_next = mkInstMatchGenerator(tparent, q, patsn, pat_map_init); |
604 |
2660 |
return imgm; |
605 |
|
} |
606 |
|
|
607 |
9585 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( |
608 |
|
Trigger* tparent, |
609 |
|
Node q, |
610 |
|
std::vector<Node>& pats, |
611 |
|
std::map<Node, InstMatchGenerator*>& pat_map_init) |
612 |
|
{ |
613 |
9585 |
size_t pCounter = 0; |
614 |
9585 |
InstMatchGenerator* prev = NULL; |
615 |
9585 |
InstMatchGenerator* oinit = NULL; |
616 |
32031 |
while( pCounter<pats.size() ){ |
617 |
11223 |
size_t counter = 0; |
618 |
22446 |
std::vector< InstMatchGenerator* > gens; |
619 |
|
InstMatchGenerator* init; |
620 |
11223 |
std::map< Node, InstMatchGenerator * >::iterator iti = pat_map_init.find( pats[pCounter] ); |
621 |
11223 |
if( iti==pat_map_init.end() ){ |
622 |
8255 |
init = getInstMatchGenerator(tparent, q, pats[pCounter]); |
623 |
|
}else{ |
624 |
2968 |
init = iti->second; |
625 |
|
} |
626 |
11223 |
if(pCounter==0){ |
627 |
9585 |
oinit = init; |
628 |
|
} |
629 |
11223 |
gens.push_back(init); |
630 |
|
//chain the resulting match generators together |
631 |
82635 |
while (counter<gens.size()) { |
632 |
35706 |
InstMatchGenerator* curr = gens[counter]; |
633 |
35706 |
if( prev ){ |
634 |
26121 |
prev->d_next = curr; |
635 |
|
} |
636 |
35706 |
curr->initialize(q, gens); |
637 |
35706 |
prev = curr; |
638 |
35706 |
counter++; |
639 |
|
} |
640 |
11223 |
pCounter++; |
641 |
|
} |
642 |
9585 |
return oinit; |
643 |
|
} |
644 |
|
|
645 |
35706 |
InstMatchGenerator* InstMatchGenerator::getInstMatchGenerator(Trigger* tparent, |
646 |
|
Node q, |
647 |
|
Node n) |
648 |
|
{ |
649 |
|
// maybe variable match generator |
650 |
35706 |
if (n.getKind() != INST_CONSTANT) |
651 |
|
{ |
652 |
71388 |
Trace("var-trigger-debug") |
653 |
35694 |
<< "Is " << n << " a variable trigger?" << std::endl; |
654 |
71380 |
Node x; |
655 |
35694 |
if (options::purifyTriggers()) |
656 |
|
{ |
657 |
314 |
Node xi = PatternTermSelector::getInversionVariable(n); |
658 |
157 |
if (!xi.isNull()) |
659 |
|
{ |
660 |
16 |
Node qa = quantifiers::TermUtil::getInstConstAttr(xi); |
661 |
8 |
if (qa == q) |
662 |
|
{ |
663 |
8 |
x = xi; |
664 |
|
} |
665 |
|
} |
666 |
|
} |
667 |
35694 |
if (!x.isNull()) |
668 |
|
{ |
669 |
16 |
Node s = PatternTermSelector::getInversion(n, x); |
670 |
|
VarMatchGeneratorTermSubs* vmg = |
671 |
8 |
new VarMatchGeneratorTermSubs(tparent, x, s); |
672 |
16 |
Trace("var-trigger") << "Term substitution trigger : " << n |
673 |
8 |
<< ", var = " << x << ", subs = " << s << std::endl; |
674 |
8 |
return vmg; |
675 |
|
} |
676 |
|
} |
677 |
71396 |
Trace("relational-trigger") |
678 |
35698 |
<< "Is " << n << " a relational trigger?" << std::endl; |
679 |
|
// relational triggers |
680 |
|
bool hasPol, pol; |
681 |
71396 |
Node lit; |
682 |
35698 |
if (TriggerTermInfo::isUsableRelationTrigger(n, hasPol, pol, lit)) |
683 |
|
{ |
684 |
10 |
Trace("relational-trigger") << "...yes, for literal " << lit << std::endl; |
685 |
10 |
return new RelationalMatchGenerator(tparent, lit, hasPol, pol); |
686 |
|
} |
687 |
35688 |
return new InstMatchGenerator(tparent, n); |
688 |
|
} |
689 |
|
|
690 |
|
} // namespace inst |
691 |
|
} // namespace quantifiers |
692 |
|
} // namespace theory |
693 |
31125 |
} // namespace cvc5 |