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