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