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 |
36399 |
InstMatchGenerator::InstMatchGenerator(Trigger* tparent, Node pat) |
41 |
36399 |
: IMGenerator(tparent) |
42 |
|
{ |
43 |
36399 |
d_cg = nullptr; |
44 |
36399 |
d_needsReset = true; |
45 |
36399 |
d_active_add = true; |
46 |
36399 |
Assert(pat.isNull() || quantifiers::TermUtil::hasInstConstAttr(pat)); |
47 |
36399 |
d_pattern = pat; |
48 |
36399 |
d_match_pattern = pat; |
49 |
36399 |
if (!pat.isNull()) |
50 |
|
{ |
51 |
35091 |
d_match_pattern_type = pat.getType(); |
52 |
|
} |
53 |
36399 |
d_next = nullptr; |
54 |
36399 |
d_independent_gen = false; |
55 |
36399 |
} |
56 |
|
|
57 |
107889 |
InstMatchGenerator::~InstMatchGenerator() |
58 |
|
{ |
59 |
63469 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
60 |
27070 |
delete d_children[i]; |
61 |
|
} |
62 |
36399 |
delete d_cg; |
63 |
71490 |
} |
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 |
36399 |
void InstMatchGenerator::initialize(Node q, |
95 |
|
std::vector<InstMatchGenerator*>& gens) |
96 |
|
{ |
97 |
36399 |
if (d_pattern.isNull()) |
98 |
|
{ |
99 |
1308 |
gens.insert(gens.end(), d_children.begin(), d_children.end()); |
100 |
1308 |
return; |
101 |
|
} |
102 |
70182 |
Trace("inst-match-gen") << "Initialize, pattern term is " << d_pattern |
103 |
35091 |
<< std::endl; |
104 |
35091 |
if (d_match_pattern.getKind() == NOT) |
105 |
|
{ |
106 |
2128 |
Assert(d_pattern.getKind() == NOT); |
107 |
|
// we want to add the children of the NOT |
108 |
2128 |
d_match_pattern = d_match_pattern[0]; |
109 |
|
} |
110 |
|
|
111 |
72310 |
if (d_pattern.getKind() == NOT && d_match_pattern.getKind() == EQUAL |
112 |
37219 |
&& d_match_pattern[0].getKind() == INST_CONSTANT |
113 |
70234 |
&& d_match_pattern[1].getKind() == INST_CONSTANT) |
114 |
|
{ |
115 |
|
// special case: disequalities between variables x != y will match ground |
116 |
|
// disequalities. |
117 |
|
} |
118 |
70168 |
else if (d_match_pattern.getKind() == EQUAL |
119 |
35084 |
|| 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 |
2151 |
for (size_t i = 0; i < 2; i++) |
128 |
|
{ |
129 |
2159 |
Node mp = d_match_pattern[i]; |
130 |
2159 |
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 |
6453 |
if (quantifiers::TermUtil::hasInstConstAttr(mp) |
135 |
8596 |
&& (!quantifiers::TermUtil::hasInstConstAttr(mpo) |
136 |
19 |
|| mpo.getKind() == INST_CONSTANT)) |
137 |
|
{ |
138 |
2143 |
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 |
2143 |
d_eq_class_rel = mpo; |
152 |
2143 |
d_match_pattern = mp; |
153 |
|
// we won't find a term in the other direction |
154 |
2143 |
break; |
155 |
|
} |
156 |
|
} |
157 |
|
} |
158 |
35091 |
d_match_pattern_type = d_match_pattern.getType(); |
159 |
70182 |
Trace("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " |
160 |
35091 |
<< d_match_pattern << std::endl; |
161 |
35091 |
quantifiers::TermDb* tdb = d_treg.getTermDatabase(); |
162 |
35091 |
d_match_pattern_op = tdb->getMatchOperator(d_match_pattern); |
163 |
|
|
164 |
|
// now, collect children of d_match_pattern |
165 |
35091 |
Kind mpk = d_match_pattern.getKind(); |
166 |
35091 |
if (mpk == INST_CONSTANT) |
167 |
|
{ |
168 |
142 |
d_children_types.push_back( |
169 |
142 |
d_match_pattern.getAttribute(InstVarNumAttribute())); |
170 |
|
} |
171 |
|
else |
172 |
|
{ |
173 |
99122 |
for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++) |
174 |
|
{ |
175 |
128204 |
Node pat = d_match_pattern[i]; |
176 |
128204 |
Node qa = quantifiers::TermUtil::getInstConstAttr(pat); |
177 |
64102 |
if (!qa.isNull()) |
178 |
|
{ |
179 |
57260 |
if (pat.getKind() == INST_CONSTANT && qa == q) |
180 |
|
{ |
181 |
33068 |
d_children_types.push_back(pat.getAttribute(InstVarNumAttribute())); |
182 |
|
} |
183 |
|
else |
184 |
|
{ |
185 |
24192 |
InstMatchGenerator* cimg = getInstMatchGenerator(d_tparent, q, pat); |
186 |
24192 |
if (cimg) |
187 |
|
{ |
188 |
24192 |
d_children.push_back(cimg); |
189 |
24192 |
d_children_index.push_back(i); |
190 |
24192 |
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 |
35091 |
if (mpk == APPLY_SELECTOR) |
207 |
|
{ |
208 |
|
// candidates for apply selector are a union of correctly and incorrectly |
209 |
|
// applied selectors |
210 |
516 |
d_cg = |
211 |
258 |
new inst::CandidateGeneratorSelector(d_qstate, d_treg, d_match_pattern); |
212 |
|
} |
213 |
34833 |
else if (TriggerTermInfo::isAtomicTriggerKind(mpk)) |
214 |
|
{ |
215 |
34755 |
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 |
34755 |
if (d_cg == nullptr) |
227 |
|
{ |
228 |
|
CandidateGeneratorQE* cg = |
229 |
31738 |
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 |
31738 |
d_cg = cg; |
233 |
|
// if matching on disequality, inform the candidate generator not to |
234 |
|
// match on eqc |
235 |
31738 |
if (d_pattern.getKind() == NOT && d_pattern[0].getKind() == EQUAL) |
236 |
|
{ |
237 |
2076 |
cg->excludeEqc(d_eq_class_rel); |
238 |
2076 |
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 |
70182 |
Trace("inst-match-gen") << "Candidate generator is " |
275 |
70182 |
<< (d_cg != nullptr ? d_cg->identify() : "null") |
276 |
35091 |
<< std::endl; |
277 |
35091 |
gens.insert( gens.end(), d_children.begin(), d_children.end() ); |
278 |
|
} |
279 |
|
|
280 |
|
/** get match (not modulo equality) */ |
281 |
2398026 |
int InstMatchGenerator::getMatch(Node f, Node t, InstMatch& m) |
282 |
|
{ |
283 |
4796052 |
Trace("matching") << "Matching " << t << " against pattern " << d_match_pattern << " (" |
284 |
2398026 |
<< m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl; |
285 |
2398026 |
Assert(!d_match_pattern.isNull()); |
286 |
2398026 |
if (d_cg == nullptr) |
287 |
|
{ |
288 |
|
Trace("matching-fail") << "Internal error for match generator." << std::endl; |
289 |
|
return -2; |
290 |
|
} |
291 |
2398026 |
bool success = true; |
292 |
4796052 |
std::vector<int> prev; |
293 |
|
// if t is null |
294 |
2398026 |
Assert(!t.isNull()); |
295 |
2398026 |
Assert(!quantifiers::TermUtil::hasInstConstAttr(t)); |
296 |
|
// notice that t may have a different kind or operator from our match |
297 |
|
// pattern, e.g. for APPLY_SELECTOR triggers. |
298 |
|
// first, check if ground arguments are not equal, or a match is in conflict |
299 |
2398026 |
Trace("matching-debug2") << "Setting immediate matches..." << std::endl; |
300 |
3414243 |
for (size_t i = 0, size = d_match_pattern.getNumChildren(); i < size; i++) |
301 |
|
{ |
302 |
3035801 |
int64_t ct = d_children_types[i]; |
303 |
3035801 |
if (ct >= 0) |
304 |
|
{ |
305 |
3926158 |
Trace("matching-debug2") |
306 |
1963079 |
<< "Setting " << ct << " to " << t[i] << "..." << std::endl; |
307 |
1963079 |
bool addToPrev = m.get(ct).isNull(); |
308 |
1963079 |
if (!m.set(d_qstate, ct, t[i])) |
309 |
|
{ |
310 |
|
// match is in conflict |
311 |
2609538 |
Trace("matching-fail") |
312 |
1304769 |
<< "Match fail: " << m.get(ct) << " and " << t[i] << std::endl; |
313 |
1304769 |
success = false; |
314 |
3324353 |
break; |
315 |
|
} |
316 |
658310 |
else if (addToPrev) |
317 |
|
{ |
318 |
611380 |
Trace("matching-debug2") << "Success." << std::endl; |
319 |
611380 |
prev.push_back(ct); |
320 |
|
} |
321 |
|
} |
322 |
1072722 |
else if (ct == -1) |
323 |
|
{ |
324 |
737547 |
if (!d_qstate.areEqual(d_match_pattern[i], t[i])) |
325 |
|
{ |
326 |
1429630 |
Trace("matching-fail") << "Match fail arg: " << d_match_pattern[i] |
327 |
714815 |
<< " and " << t[i] << std::endl; |
328 |
|
// ground arguments are not equal |
329 |
714815 |
success = false; |
330 |
714815 |
break; |
331 |
|
} |
332 |
|
} |
333 |
|
} |
334 |
4796052 |
Trace("matching-debug2") << "Done setting immediate matches, success = " |
335 |
2398026 |
<< success << "." << std::endl; |
336 |
|
// for variable matching |
337 |
2398026 |
if (d_match_pattern.getKind() == INST_CONSTANT) |
338 |
|
{ |
339 |
102 |
bool addToPrev = m.get(d_children_types[0]).isNull(); |
340 |
102 |
if (!m.set(d_qstate, d_children_types[0], t)) |
341 |
|
{ |
342 |
|
success = false; |
343 |
|
} |
344 |
|
else |
345 |
|
{ |
346 |
102 |
if (addToPrev) |
347 |
|
{ |
348 |
102 |
prev.push_back(d_children_types[0]); |
349 |
|
} |
350 |
|
} |
351 |
|
} |
352 |
|
// for relational matching |
353 |
2398026 |
if (!d_eq_class_rel.isNull() && d_eq_class_rel.getKind() == INST_CONSTANT) |
354 |
|
{ |
355 |
28 |
NodeManager* nm = NodeManager::currentNM(); |
356 |
28 |
int v = d_eq_class_rel.getAttribute(InstVarNumAttribute()); |
357 |
|
// also must fit match to equivalence class |
358 |
28 |
bool pol = d_pattern.getKind() != NOT; |
359 |
56 |
Node pat = d_pattern.getKind() == NOT ? d_pattern[0] : d_pattern; |
360 |
56 |
Node t_match; |
361 |
28 |
if (pol) |
362 |
|
{ |
363 |
28 |
if (pat.getKind() == GT) |
364 |
|
{ |
365 |
|
t_match = nm->mkNode(MINUS, t, nm->mkConst(Rational(1))); |
366 |
|
}else{ |
367 |
28 |
t_match = t; |
368 |
|
} |
369 |
|
} |
370 |
|
else |
371 |
|
{ |
372 |
|
if (pat.getKind() == EQUAL) |
373 |
|
{ |
374 |
|
if (t.getType().isBoolean()) |
375 |
|
{ |
376 |
|
t_match = nm->mkConst(!d_qstate.areEqual(nm->mkConst(true), t)); |
377 |
|
} |
378 |
|
else |
379 |
|
{ |
380 |
|
Assert(t.getType().isReal()); |
381 |
|
t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1))); |
382 |
|
} |
383 |
|
} |
384 |
|
else if (pat.getKind() == GEQ) |
385 |
|
{ |
386 |
|
t_match = nm->mkNode(PLUS, t, nm->mkConst(Rational(1))); |
387 |
|
} |
388 |
|
else if (pat.getKind() == GT) |
389 |
|
{ |
390 |
|
t_match = t; |
391 |
|
} |
392 |
|
} |
393 |
28 |
if (!t_match.isNull()) |
394 |
|
{ |
395 |
28 |
bool addToPrev = m.get(v).isNull(); |
396 |
28 |
if (!m.set(d_qstate, v, t_match)) |
397 |
|
{ |
398 |
|
success = false; |
399 |
|
} |
400 |
28 |
else if (addToPrev) |
401 |
|
{ |
402 |
28 |
prev.push_back(v); |
403 |
|
} |
404 |
|
} |
405 |
|
} |
406 |
2398026 |
int ret_val = -1; |
407 |
2398026 |
if (success) |
408 |
|
{ |
409 |
378442 |
Trace("matching-debug2") << "Reset children..." << std::endl; |
410 |
|
// now, fit children into match |
411 |
|
// we will be requesting candidates for matching terms for each child |
412 |
467157 |
for (size_t i = 0, size = d_children.size(); i < size; i++) |
413 |
|
{ |
414 |
287235 |
if (!d_children[i]->reset(t[d_children_index[i]])) |
415 |
|
{ |
416 |
198520 |
success = false; |
417 |
198520 |
break; |
418 |
|
} |
419 |
|
} |
420 |
378442 |
if (success) |
421 |
|
{ |
422 |
179922 |
Trace("matching-debug2") << "Continue next " << d_next << std::endl; |
423 |
179922 |
ret_val = |
424 |
359844 |
continueNextMatch(f, m, InferenceId::QUANTIFIERS_INST_E_MATCHING); |
425 |
|
} |
426 |
|
} |
427 |
2398026 |
if (ret_val < 0) |
428 |
|
{ |
429 |
2945944 |
for (int& pv : prev) |
430 |
|
{ |
431 |
576536 |
m.d_vals[pv] = Node::null(); |
432 |
|
} |
433 |
|
} |
434 |
2398026 |
return ret_val; |
435 |
|
} |
436 |
|
|
437 |
184466 |
int InstMatchGenerator::continueNextMatch(Node q, |
438 |
|
InstMatch& m, |
439 |
|
InferenceId id) |
440 |
|
{ |
441 |
184466 |
if( d_next!=NULL ){ |
442 |
120059 |
return d_next->getNextMatch(q, m); |
443 |
|
} |
444 |
64407 |
if (d_active_add) |
445 |
|
{ |
446 |
63439 |
return sendInstantiation(m, id) ? 1 : -1; |
447 |
|
} |
448 |
968 |
return 1; |
449 |
|
} |
450 |
|
|
451 |
|
/** reset instantiation round */ |
452 |
259193 |
void InstMatchGenerator::resetInstantiationRound() |
453 |
|
{ |
454 |
259193 |
if( !d_match_pattern.isNull() ){ |
455 |
248323 |
Trace("matching-debug2") << this << " reset instantiation round." << std::endl; |
456 |
248323 |
d_needsReset = true; |
457 |
248323 |
if( d_cg ){ |
458 |
248323 |
d_cg->resetInstantiationRound(); |
459 |
|
} |
460 |
|
} |
461 |
259193 |
if( d_next ){ |
462 |
186038 |
d_next->resetInstantiationRound(); |
463 |
|
} |
464 |
259193 |
d_curr_exclude_match.clear(); |
465 |
259193 |
} |
466 |
|
|
467 |
480888 |
bool InstMatchGenerator::reset(Node eqc) |
468 |
|
{ |
469 |
480888 |
if (d_cg == nullptr) |
470 |
|
{ |
471 |
|
// we did not properly initialize the candidate generator, thus we fail |
472 |
|
return false; |
473 |
|
} |
474 |
480888 |
eqc = d_qstate.getRepresentative(eqc); |
475 |
480888 |
Trace("matching-debug2") << this << " reset " << eqc << "." << std::endl; |
476 |
480888 |
if( !d_eq_class_rel.isNull() && d_eq_class_rel.getKind()!=INST_CONSTANT ){ |
477 |
112 |
d_eq_class = d_eq_class_rel; |
478 |
480776 |
}else if( !eqc.isNull() ){ |
479 |
360356 |
d_eq_class = eqc; |
480 |
|
} |
481 |
|
//we have a specific equivalence class in mind |
482 |
|
//we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term |
483 |
|
//just look in equivalence class of the RHS |
484 |
480888 |
d_cg->reset( d_eq_class ); |
485 |
480888 |
d_needsReset = false; |
486 |
|
|
487 |
|
//generate the first candidate preemptively |
488 |
480888 |
d_curr_first_candidate = Node::null(); |
489 |
961776 |
Node t; |
490 |
146950 |
do { |
491 |
627838 |
t = d_cg->getNextCandidate(); |
492 |
627838 |
if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){ |
493 |
480888 |
d_curr_first_candidate = t; |
494 |
|
} |
495 |
627838 |
}while( !t.isNull() && d_curr_first_candidate.isNull() ); |
496 |
480888 |
Trace("matching-summary") << "Reset " << d_match_pattern << " in " << eqc << " returns " << !d_curr_first_candidate.isNull() << "." << std::endl; |
497 |
|
|
498 |
480888 |
return !d_curr_first_candidate.isNull(); |
499 |
|
} |
500 |
|
|
501 |
147158 |
int InstMatchGenerator::getNextMatch(Node f, InstMatch& m) |
502 |
|
{ |
503 |
147158 |
if( d_needsReset ){ |
504 |
|
Trace("matching") << "Reset not done yet, must do the reset..." << std::endl; |
505 |
|
reset(d_eq_class); |
506 |
|
} |
507 |
147158 |
d_curr_matched = Node::null(); |
508 |
147158 |
Trace("matching") << this << " " << d_match_pattern << " get next match " << m << " in eq class " << d_eq_class << std::endl; |
509 |
147158 |
int success = -1; |
510 |
294316 |
Node t = d_curr_first_candidate; |
511 |
2354755 |
do{ |
512 |
2501913 |
Trace("matching-debug2") << "Matching candidate : " << t << std::endl; |
513 |
2501913 |
Assert(!d_qstate.isInConflict()); |
514 |
|
//if t not null, try to fit it into match m |
515 |
2501913 |
if( !t.isNull() ){ |
516 |
2490075 |
if( d_curr_exclude_match.find( t )==d_curr_exclude_match.end() ){ |
517 |
2398026 |
Assert(t.getType().isComparableTo(d_match_pattern_type)); |
518 |
2398026 |
Trace("matching-summary") << "Try " << d_match_pattern << " : " << t << std::endl; |
519 |
2398026 |
success = getMatch(f, t, m); |
520 |
2398026 |
if( d_independent_gen && success<0 ){ |
521 |
26300 |
Assert(d_eq_class.isNull() || !d_eq_class_rel.isNull()); |
522 |
26300 |
d_curr_exclude_match[t] = true; |
523 |
|
} |
524 |
|
} |
525 |
|
//get the next candidate term t |
526 |
2490075 |
if( success<0 ){ |
527 |
2461457 |
t = d_qstate.isInConflict() ? Node::null() : d_cg->getNextCandidate(); |
528 |
|
}else{ |
529 |
28618 |
d_curr_first_candidate = d_cg->getNextCandidate(); |
530 |
|
} |
531 |
|
} |
532 |
2501913 |
}while( success<0 && !t.isNull() ); |
533 |
147158 |
d_curr_matched = t; |
534 |
147158 |
if( success<0 ){ |
535 |
118540 |
Trace("matching-summary") << "..." << d_match_pattern << " failed, reset." << std::endl; |
536 |
118540 |
Trace("matching") << this << " failed, reset " << d_eq_class << std::endl; |
537 |
|
//we failed, must reset |
538 |
118540 |
reset(d_eq_class); |
539 |
|
}else{ |
540 |
28618 |
Trace("matching-summary") << "..." << d_match_pattern << " success." << std::endl; |
541 |
|
} |
542 |
294316 |
return success; |
543 |
|
} |
544 |
|
|
545 |
22691 |
uint64_t InstMatchGenerator::addInstantiations(Node f) |
546 |
|
{ |
547 |
|
//try to add instantiation for each match produced |
548 |
22691 |
uint64_t addedLemmas = 0; |
549 |
45382 |
InstMatch m( f ); |
550 |
44125 |
while (getNextMatch(f, m) > 0) |
551 |
|
{ |
552 |
10717 |
if( !d_active_add ){ |
553 |
|
if (sendInstantiation(m, InferenceId::UNKNOWN)) |
554 |
|
{ |
555 |
|
addedLemmas++; |
556 |
|
if (d_qstate.isInConflict()) |
557 |
|
{ |
558 |
|
break; |
559 |
|
} |
560 |
|
} |
561 |
|
}else{ |
562 |
10717 |
addedLemmas++; |
563 |
10717 |
if (d_qstate.isInConflict()) |
564 |
|
{ |
565 |
|
break; |
566 |
|
} |
567 |
|
} |
568 |
10717 |
m.clear(); |
569 |
|
} |
570 |
|
//return number of lemmas added |
571 |
45382 |
return addedLemmas; |
572 |
|
} |
573 |
|
|
574 |
8029 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator(Trigger* tparent, |
575 |
|
Node q, |
576 |
|
Node pat) |
577 |
|
{ |
578 |
16058 |
std::vector< Node > pats; |
579 |
8029 |
pats.push_back( pat ); |
580 |
16058 |
std::map< Node, InstMatchGenerator * > pat_map_init; |
581 |
16058 |
return mkInstMatchGenerator(tparent, q, pats, pat_map_init); |
582 |
|
} |
583 |
|
|
584 |
1300 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGeneratorMulti( |
585 |
|
Trigger* tparent, Node q, std::vector<Node>& pats) |
586 |
|
{ |
587 |
1300 |
Assert(pats.size() > 1); |
588 |
|
InstMatchGeneratorMultiLinear* imgm = |
589 |
1300 |
new InstMatchGeneratorMultiLinear(tparent, q, pats); |
590 |
2600 |
std::vector< InstMatchGenerator* > gens; |
591 |
1300 |
imgm->initialize(q, gens); |
592 |
1300 |
Assert(gens.size() == pats.size()); |
593 |
2600 |
std::vector< Node > patsn; |
594 |
2600 |
std::map< Node, InstMatchGenerator * > pat_map_init; |
595 |
4178 |
for (InstMatchGenerator* g : gens) |
596 |
|
{ |
597 |
5756 |
Node pn = g->d_match_pattern; |
598 |
2878 |
patsn.push_back( pn ); |
599 |
2878 |
pat_map_init[pn] = g; |
600 |
|
} |
601 |
1300 |
imgm->d_next = mkInstMatchGenerator(tparent, q, patsn, pat_map_init); |
602 |
2600 |
return imgm; |
603 |
|
} |
604 |
|
|
605 |
9329 |
InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( |
606 |
|
Trigger* tparent, |
607 |
|
Node q, |
608 |
|
std::vector<Node>& pats, |
609 |
|
std::map<Node, InstMatchGenerator*>& pat_map_init) |
610 |
|
{ |
611 |
9329 |
size_t pCounter = 0; |
612 |
9329 |
InstMatchGenerator* prev = NULL; |
613 |
9329 |
InstMatchGenerator* oinit = NULL; |
614 |
31143 |
while( pCounter<pats.size() ){ |
615 |
10907 |
size_t counter = 0; |
616 |
21814 |
std::vector< InstMatchGenerator* > gens; |
617 |
|
InstMatchGenerator* init; |
618 |
10907 |
std::map< Node, InstMatchGenerator * >::iterator iti = pat_map_init.find( pats[pCounter] ); |
619 |
10907 |
if( iti==pat_map_init.end() ){ |
620 |
8029 |
init = new InstMatchGenerator(tparent, pats[pCounter]); |
621 |
|
}else{ |
622 |
2878 |
init = iti->second; |
623 |
|
} |
624 |
10907 |
if(pCounter==0){ |
625 |
9329 |
oinit = init; |
626 |
|
} |
627 |
10907 |
gens.push_back(init); |
628 |
|
//chain the resulting match generators together |
629 |
81105 |
while (counter<gens.size()) { |
630 |
35099 |
InstMatchGenerator* curr = gens[counter]; |
631 |
35099 |
if( prev ){ |
632 |
25770 |
prev->d_next = curr; |
633 |
|
} |
634 |
35099 |
curr->initialize(q, gens); |
635 |
35099 |
prev = curr; |
636 |
35099 |
counter++; |
637 |
|
} |
638 |
10907 |
pCounter++; |
639 |
|
} |
640 |
9329 |
return oinit; |
641 |
|
} |
642 |
|
|
643 |
27070 |
InstMatchGenerator* InstMatchGenerator::getInstMatchGenerator(Trigger* tparent, |
644 |
|
Node q, |
645 |
|
Node n) |
646 |
|
{ |
647 |
27070 |
if (n.getKind() != INST_CONSTANT) |
648 |
|
{ |
649 |
54132 |
Trace("var-trigger-debug") |
650 |
27066 |
<< "Is " << n << " a variable trigger?" << std::endl; |
651 |
54124 |
Node x; |
652 |
27066 |
if (options::purifyTriggers()) |
653 |
|
{ |
654 |
170 |
Node xi = PatternTermSelector::getInversionVariable(n); |
655 |
85 |
if (!xi.isNull()) |
656 |
|
{ |
657 |
16 |
Node qa = quantifiers::TermUtil::getInstConstAttr(xi); |
658 |
8 |
if (qa == q) |
659 |
|
{ |
660 |
8 |
x = xi; |
661 |
|
} |
662 |
|
} |
663 |
|
} |
664 |
27066 |
if (!x.isNull()) |
665 |
|
{ |
666 |
16 |
Node s = PatternTermSelector::getInversion(n, x); |
667 |
|
VarMatchGeneratorTermSubs* vmg = |
668 |
8 |
new VarMatchGeneratorTermSubs(tparent, x, s); |
669 |
16 |
Trace("var-trigger") << "Term substitution trigger : " << n |
670 |
8 |
<< ", var = " << x << ", subs = " << s << std::endl; |
671 |
8 |
return vmg; |
672 |
|
} |
673 |
|
} |
674 |
27062 |
return new InstMatchGenerator(tparent, n); |
675 |
|
} |
676 |
|
|
677 |
|
} // namespace inst |
678 |
|
} // namespace quantifiers |
679 |
|
} // namespace theory |
680 |
29577 |
} // namespace cvc5 |