1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, 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 term database class. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/term_database.h" |
17 |
|
|
18 |
|
#include "expr/skolem_manager.h" |
19 |
|
#include "options/base_options.h" |
20 |
|
#include "options/quantifiers_options.h" |
21 |
|
#include "options/smt_options.h" |
22 |
|
#include "options/theory_options.h" |
23 |
|
#include "options/uf_options.h" |
24 |
|
#include "theory/quantifiers/ematching/trigger_term_info.h" |
25 |
|
#include "theory/quantifiers/quantifiers_attributes.h" |
26 |
|
#include "theory/quantifiers/quantifiers_inference_manager.h" |
27 |
|
#include "theory/quantifiers/quantifiers_registry.h" |
28 |
|
#include "theory/quantifiers/quantifiers_state.h" |
29 |
|
#include "theory/quantifiers/term_util.h" |
30 |
|
#include "theory/rewriter.h" |
31 |
|
#include "theory/uf/equality_engine.h" |
32 |
|
|
33 |
|
using namespace cvc5::kind; |
34 |
|
using namespace cvc5::context; |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
namespace theory { |
38 |
|
namespace quantifiers { |
39 |
|
|
40 |
15273 |
TermDb::TermDb(Env& env, QuantifiersState& qs, QuantifiersRegistry& qr) |
41 |
|
: QuantifiersUtil(env), |
42 |
|
d_qstate(qs), |
43 |
|
d_qim(nullptr), |
44 |
|
d_qreg(qr), |
45 |
|
d_termsContext(), |
46 |
15273 |
d_termsContextUse(options::termDbCd() ? context() : &d_termsContext), |
47 |
|
d_processed(d_termsContextUse), |
48 |
|
d_typeMap(d_termsContextUse), |
49 |
|
d_ops(d_termsContextUse), |
50 |
|
d_opMap(d_termsContextUse), |
51 |
30546 |
d_inactive_map(context()) |
52 |
|
{ |
53 |
15273 |
d_consistent_ee = true; |
54 |
15273 |
d_true = NodeManager::currentNM()->mkConst(true); |
55 |
15273 |
d_false = NodeManager::currentNM()->mkConst(false); |
56 |
15273 |
if (!options::termDbCd()) |
57 |
|
{ |
58 |
|
// when not maintaining terms in a context-dependent manner, we clear during |
59 |
|
// each presolve, which requires maintaining a single outermost level |
60 |
|
d_termsContext.push(); |
61 |
|
} |
62 |
15273 |
} |
63 |
|
|
64 |
30300 |
TermDb::~TermDb(){ |
65 |
|
|
66 |
30300 |
} |
67 |
|
|
68 |
15273 |
void TermDb::finishInit(QuantifiersInferenceManager* qim) { d_qim = qim; } |
69 |
|
|
70 |
26099 |
void TermDb::registerQuantifier( Node q ) { |
71 |
26099 |
Assert(q[0].getNumChildren() == d_qreg.getNumInstantiationConstants(q)); |
72 |
87502 |
for (size_t i = 0, nvars = q[0].getNumChildren(); i < nvars; i++) |
73 |
|
{ |
74 |
122806 |
Node ic = d_qreg.getInstantiationConstant(q, i); |
75 |
61403 |
setTermInactive( ic ); |
76 |
|
} |
77 |
26099 |
} |
78 |
|
|
79 |
1022 |
size_t TermDb::getNumOperators() const { return d_ops.size(); } |
80 |
|
|
81 |
2212 |
Node TermDb::getOperator(size_t i) const |
82 |
|
{ |
83 |
2212 |
Assert(i < d_ops.size()); |
84 |
2212 |
return d_ops[i]; |
85 |
|
} |
86 |
|
|
87 |
|
/** ground terms */ |
88 |
516093 |
size_t TermDb::getNumGroundTerms(Node f) const |
89 |
|
{ |
90 |
516093 |
NodeDbListMap::const_iterator it = d_opMap.find(f); |
91 |
516093 |
if (it != d_opMap.end()) |
92 |
|
{ |
93 |
498544 |
return it->second->d_list.size(); |
94 |
|
} |
95 |
17549 |
return 0; |
96 |
|
} |
97 |
|
|
98 |
3036110 |
Node TermDb::getGroundTerm(Node f, size_t i) const |
99 |
|
{ |
100 |
3036110 |
NodeDbListMap::const_iterator it = d_opMap.find(f); |
101 |
3036110 |
if (it != d_opMap.end()) |
102 |
|
{ |
103 |
3036110 |
Assert(i < it->second->d_list.size()); |
104 |
3036110 |
return it->second->d_list[i]; |
105 |
|
} |
106 |
|
Assert(false); |
107 |
|
return Node::null(); |
108 |
|
} |
109 |
|
|
110 |
426 |
size_t TermDb::getNumTypeGroundTerms(TypeNode tn) const |
111 |
|
{ |
112 |
426 |
TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn); |
113 |
426 |
if (it != d_typeMap.end()) |
114 |
|
{ |
115 |
416 |
return it->second->d_list.size(); |
116 |
|
} |
117 |
10 |
return 0; |
118 |
|
} |
119 |
|
|
120 |
21929 |
Node TermDb::getTypeGroundTerm(TypeNode tn, size_t i) const |
121 |
|
{ |
122 |
21929 |
TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn); |
123 |
21929 |
if (it != d_typeMap.end()) |
124 |
|
{ |
125 |
21929 |
Assert(i < it->second->d_list.size()); |
126 |
21929 |
return it->second->d_list[i]; |
127 |
|
} |
128 |
|
Assert(false); |
129 |
|
return Node::null(); |
130 |
|
} |
131 |
|
|
132 |
2637 |
Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar) |
133 |
|
{ |
134 |
2637 |
TypeNodeDbListMap::const_iterator it = d_typeMap.find(tn); |
135 |
2637 |
if (it != d_typeMap.end()) |
136 |
|
{ |
137 |
651 |
Assert(!it->second->d_list.empty()); |
138 |
651 |
if (!reqVar) |
139 |
|
{ |
140 |
323 |
return it->second->d_list[0]; |
141 |
|
} |
142 |
525 |
for (const Node& v : it->second->d_list) |
143 |
|
{ |
144 |
468 |
if (v.isVar()) |
145 |
|
{ |
146 |
271 |
return v; |
147 |
|
} |
148 |
|
} |
149 |
|
} |
150 |
2043 |
return getOrMakeTypeFreshVariable(tn); |
151 |
|
} |
152 |
|
|
153 |
2043 |
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn) |
154 |
|
{ |
155 |
2043 |
std::unordered_map<TypeNode, Node>::iterator it = d_type_fv.find(tn); |
156 |
2043 |
if (it == d_type_fv.end()) |
157 |
|
{ |
158 |
255 |
SkolemManager* sm = NodeManager::currentNM()->getSkolemManager(); |
159 |
510 |
std::stringstream ss; |
160 |
255 |
ss << language::SetLanguage(options::outputLanguage()); |
161 |
255 |
ss << "e_" << tn; |
162 |
510 |
Node k = sm->mkDummySkolem(ss.str(), tn, "is a termDb fresh variable"); |
163 |
510 |
Trace("mkVar") << "TermDb:: Make variable " << k << " : " << tn |
164 |
255 |
<< std::endl; |
165 |
255 |
if (options::instMaxLevel() != -1) |
166 |
|
{ |
167 |
|
QuantAttributes::setInstantiationLevelAttr(k, 0); |
168 |
|
} |
169 |
255 |
d_type_fv[tn] = k; |
170 |
255 |
return k; |
171 |
|
} |
172 |
1788 |
return it->second; |
173 |
|
} |
174 |
|
|
175 |
5378520 |
Node TermDb::getMatchOperator( Node n ) { |
176 |
5378520 |
Kind k = n.getKind(); |
177 |
|
//datatype operators may be parametric, always assume they are |
178 |
5378520 |
if (k == SELECT || k == STORE || k == UNION || k == INTERSECTION |
179 |
5279172 |
|| k == SUBSET || k == SETMINUS || k == MEMBER || k == SINGLETON |
180 |
5245736 |
|| k == APPLY_SELECTOR_TOTAL || k == APPLY_SELECTOR || k == APPLY_TESTER |
181 |
5093792 |
|| k == SEP_PTO || k == HO_APPLY || k == SEQ_NTH || k == STRING_LENGTH) |
182 |
|
{ |
183 |
|
//since it is parametric, use a particular one as op |
184 |
680310 |
TypeNode tn = n[0].getType(); |
185 |
680310 |
Node op = n.getOperator(); |
186 |
340155 |
std::map< Node, std::map< TypeNode, Node > >::iterator ito = d_par_op_map.find( op ); |
187 |
340155 |
if( ito!=d_par_op_map.end() ){ |
188 |
328045 |
std::map< TypeNode, Node >::iterator it = ito->second.find( tn ); |
189 |
328045 |
if( it!=ito->second.end() ){ |
190 |
327306 |
return it->second; |
191 |
|
} |
192 |
|
} |
193 |
12849 |
Trace("par-op") << "Parametric operator : " << k << ", " << n.getOperator() << ", " << tn << " : " << n << std::endl; |
194 |
12849 |
d_par_op_map[op][tn] = n; |
195 |
12849 |
return n; |
196 |
|
} |
197 |
5038365 |
else if (inst::TriggerTermInfo::isAtomicTriggerKind(k)) |
198 |
|
{ |
199 |
4730741 |
return n.getOperator(); |
200 |
|
}else{ |
201 |
307624 |
return Node::null(); |
202 |
|
} |
203 |
|
} |
204 |
|
|
205 |
3099227 |
void TermDb::addTerm(Node n) |
206 |
|
{ |
207 |
3099227 |
if (d_processed.find(n) != d_processed.end()) |
208 |
|
{ |
209 |
1835147 |
return; |
210 |
|
} |
211 |
1264080 |
d_processed.insert(n); |
212 |
1264080 |
if (!TermUtil::hasInstConstAttr(n)) |
213 |
|
{ |
214 |
1224572 |
Trace("term-db-debug") << "register term : " << n << std::endl; |
215 |
1224572 |
DbList* dlt = getOrMkDbListForType(n.getType()); |
216 |
1224572 |
dlt->d_list.push_back(n); |
217 |
|
// if this is an atomic trigger, consider adding it |
218 |
1224572 |
if (inst::TriggerTermInfo::isAtomicTrigger(n)) |
219 |
|
{ |
220 |
497916 |
Trace("term-db") << "register term in db " << n << std::endl; |
221 |
|
|
222 |
995832 |
Node op = getMatchOperator(n); |
223 |
497916 |
Trace("term-db-debug") << " match operator is : " << op << std::endl; |
224 |
497916 |
DbList* dlo = getOrMkDbListForOp(op); |
225 |
497916 |
dlo->d_list.push_back(n); |
226 |
|
// If we are higher-order, we may need to register more terms. |
227 |
497916 |
addTermInternal(n); |
228 |
|
} |
229 |
|
} |
230 |
|
else |
231 |
|
{ |
232 |
39508 |
setTermInactive(n); |
233 |
|
} |
234 |
1264080 |
if (!n.isClosure()) |
235 |
|
{ |
236 |
3274016 |
for (const Node& nc : n) |
237 |
|
{ |
238 |
2009958 |
addTerm(nc); |
239 |
|
} |
240 |
|
} |
241 |
|
} |
242 |
|
|
243 |
1224572 |
DbList* TermDb::getOrMkDbListForType(TypeNode tn) |
244 |
|
{ |
245 |
1224572 |
TypeNodeDbListMap::iterator it = d_typeMap.find(tn); |
246 |
1224572 |
if (it != d_typeMap.end()) |
247 |
|
{ |
248 |
1196467 |
return it->second.get(); |
249 |
|
} |
250 |
56210 |
std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse); |
251 |
28105 |
d_typeMap.insert(tn, dl); |
252 |
28105 |
return dl.get(); |
253 |
|
} |
254 |
|
|
255 |
558277 |
DbList* TermDb::getOrMkDbListForOp(TNode op) |
256 |
|
{ |
257 |
558277 |
NodeDbListMap::iterator it = d_opMap.find(op); |
258 |
558277 |
if (it != d_opMap.end()) |
259 |
|
{ |
260 |
404773 |
return it->second.get(); |
261 |
|
} |
262 |
307008 |
std::shared_ptr<DbList> dl = std::make_shared<DbList>(d_termsContextUse); |
263 |
153504 |
d_opMap.insert(op, dl); |
264 |
153504 |
Assert(op.getKind() != BOUND_VARIABLE); |
265 |
153504 |
d_ops.push_back(op); |
266 |
153504 |
return dl.get(); |
267 |
|
} |
268 |
|
|
269 |
636905 |
void TermDb::computeArgReps( TNode n ) { |
270 |
636905 |
if (d_arg_reps.find(n) == d_arg_reps.end()) |
271 |
|
{ |
272 |
377495 |
eq::EqualityEngine* ee = d_qstate.getEqualityEngine(); |
273 |
1185135 |
for (const TNode& nc : n) |
274 |
|
{ |
275 |
1615280 |
TNode r = ee->hasTerm(nc) ? ee->getRepresentative(nc) : nc; |
276 |
807640 |
d_arg_reps[n].push_back( r ); |
277 |
|
} |
278 |
|
} |
279 |
636905 |
} |
280 |
|
|
281 |
1895920 |
void TermDb::computeUfEqcTerms( TNode f ) { |
282 |
1895920 |
Assert(f == getOperatorRepresentative(f)); |
283 |
1895920 |
if (d_func_map_eqc_trie.find(f) != d_func_map_eqc_trie.end()) |
284 |
|
{ |
285 |
1848961 |
return; |
286 |
|
} |
287 |
46959 |
d_func_map_eqc_trie[f].clear(); |
288 |
|
// get the matchable operators in the equivalence class of f |
289 |
93918 |
std::vector<TNode> ops; |
290 |
46959 |
getOperatorsFor(f, ops); |
291 |
46959 |
eq::EqualityEngine* ee = d_qstate.getEqualityEngine(); |
292 |
94015 |
for (TNode ff : ops) |
293 |
|
{ |
294 |
47056 |
DbList* dbl = getOrMkDbListForOp(ff); |
295 |
370187 |
for (const Node& n : dbl->d_list) |
296 |
|
{ |
297 |
323131 |
if (hasTermCurrent(n) && isTermActive(n)) |
298 |
|
{ |
299 |
302637 |
computeArgReps(n); |
300 |
605274 |
TNode r = ee->hasTerm(n) ? ee->getRepresentative(n) : TNode(n); |
301 |
302637 |
d_func_map_eqc_trie[f].d_data[r].addTerm(n, d_arg_reps[n]); |
302 |
|
} |
303 |
|
} |
304 |
|
} |
305 |
|
} |
306 |
|
|
307 |
3770341 |
void TermDb::computeUfTerms( TNode f ) { |
308 |
3770341 |
if (d_op_nonred_count.find(f) != d_op_nonred_count.end()) |
309 |
|
{ |
310 |
|
// already computed |
311 |
7457267 |
return; |
312 |
|
} |
313 |
41713 |
Assert(f == getOperatorRepresentative(f)); |
314 |
41713 |
d_op_nonred_count[f] = 0; |
315 |
|
// get the matchable operators in the equivalence class of f |
316 |
83415 |
std::vector<TNode> ops; |
317 |
41713 |
getOperatorsFor(f, ops); |
318 |
41713 |
Trace("term-db-debug") << "computeUfTerms for " << f << std::endl; |
319 |
41713 |
unsigned congruentCount = 0; |
320 |
41713 |
unsigned nonCongruentCount = 0; |
321 |
41713 |
unsigned alreadyCongruentCount = 0; |
322 |
41713 |
unsigned relevantCount = 0; |
323 |
41713 |
NodeManager* nm = NodeManager::currentNM(); |
324 |
78382 |
for (TNode ff : ops) |
325 |
|
{ |
326 |
41799 |
NodeDbListMap::iterator it = d_opMap.find(ff); |
327 |
41799 |
if (it == d_opMap.end()) |
328 |
|
{ |
329 |
|
// no terms for this operator |
330 |
5119 |
continue; |
331 |
|
} |
332 |
36680 |
Trace("term-db-debug") << "Adding terms for operator " << ff << std::endl; |
333 |
391095 |
for (const Node& n : it->second->d_list) |
334 |
|
{ |
335 |
|
// to be added to term index, term must be relevant, and exist in EE |
336 |
354426 |
if (!hasTermCurrent(n) || !d_qstate.hasTerm(n)) |
337 |
|
{ |
338 |
|
Trace("term-db-debug") << n << " is not relevant." << std::endl; |
339 |
95867 |
continue; |
340 |
|
} |
341 |
|
|
342 |
354426 |
relevantCount++; |
343 |
374584 |
if (!isTermActive(n)) |
344 |
|
{ |
345 |
20158 |
Trace("term-db-debug") << n << " is already redundant." << std::endl; |
346 |
20158 |
alreadyCongruentCount++; |
347 |
20158 |
continue; |
348 |
|
} |
349 |
|
|
350 |
334268 |
computeArgReps(n); |
351 |
334268 |
Trace("term-db-debug") << "Adding term " << n << " with arg reps : "; |
352 |
1048731 |
for (unsigned i = 0, size = d_arg_reps[n].size(); i < size; i++) |
353 |
|
{ |
354 |
714463 |
Trace("term-db-debug") << d_arg_reps[n][i] << " "; |
355 |
2857852 |
if (std::find(d_func_map_rel_dom[f][i].begin(), |
356 |
1428926 |
d_func_map_rel_dom[f][i].end(), |
357 |
2857852 |
d_arg_reps[n][i]) |
358 |
2143389 |
== d_func_map_rel_dom[f][i].end()) |
359 |
|
{ |
360 |
248924 |
d_func_map_rel_dom[f][i].push_back(d_arg_reps[n][i]); |
361 |
|
} |
362 |
|
} |
363 |
334268 |
Trace("term-db-debug") << std::endl; |
364 |
334268 |
Assert(d_qstate.hasTerm(n)); |
365 |
668536 |
Trace("term-db-debug") |
366 |
334268 |
<< " and value : " << d_qstate.getRepresentative(n) << std::endl; |
367 |
592816 |
Node at = d_func_map_trie[f].addOrGetTerm(n, d_arg_reps[n]); |
368 |
334268 |
Assert(d_qstate.hasTerm(at)); |
369 |
334268 |
Trace("term-db-debug2") << "...add term returned " << at << std::endl; |
370 |
409977 |
if (at != n && d_qstate.areEqual(at, n)) |
371 |
|
{ |
372 |
75709 |
setTermInactive(n); |
373 |
75709 |
Trace("term-db-debug") << n << " is redundant." << std::endl; |
374 |
75709 |
congruentCount++; |
375 |
75709 |
continue; |
376 |
|
} |
377 |
517107 |
std::vector<Node> lits; |
378 |
258559 |
if (checkCongruentDisequal(at, n, lits)) |
379 |
|
{ |
380 |
11 |
Assert(at.getNumChildren() == n.getNumChildren()); |
381 |
41 |
for (size_t k = 0, size = at.getNumChildren(); k < size; k++) |
382 |
|
{ |
383 |
30 |
if (at[k] != n[k]) |
384 |
|
{ |
385 |
18 |
lits.push_back(nm->mkNode(EQUAL, at[k], n[k]).negate()); |
386 |
|
} |
387 |
|
} |
388 |
22 |
Node lem = nm->mkOr(lits); |
389 |
11 |
if (Trace.isOn("term-db-lemma")) |
390 |
|
{ |
391 |
|
Trace("term-db-lemma") << "Disequal congruent terms : " << at << " " |
392 |
|
<< n << "!!!!" << std::endl; |
393 |
|
if (!d_qstate.getValuation().needCheck()) |
394 |
|
{ |
395 |
|
Trace("term-db-lemma") |
396 |
|
<< " all theories passed with no lemmas." << std::endl; |
397 |
|
// we should be a full effort check, prior to theory combination |
398 |
|
} |
399 |
|
Trace("term-db-lemma") << " add lemma : " << lem << std::endl; |
400 |
|
} |
401 |
11 |
d_qim->addPendingLemma(lem, InferenceId::QUANTIFIERS_TDB_DEQ_CONG); |
402 |
11 |
d_qstate.notifyInConflict(); |
403 |
11 |
d_consistent_ee = false; |
404 |
11 |
return; |
405 |
|
} |
406 |
258548 |
nonCongruentCount++; |
407 |
258548 |
d_op_nonred_count[f]++; |
408 |
|
} |
409 |
36669 |
if (Trace.isOn("tdb")) |
410 |
|
{ |
411 |
|
Trace("tdb") << "Term db size [" << f << "] : " << nonCongruentCount |
412 |
|
<< " / "; |
413 |
|
Trace("tdb") << (nonCongruentCount + congruentCount) << " / " |
414 |
|
<< (nonCongruentCount + congruentCount |
415 |
|
+ alreadyCongruentCount) |
416 |
|
<< " / "; |
417 |
|
Trace("tdb") << relevantCount << " / " << it->second->d_list.size() |
418 |
|
<< std::endl; |
419 |
|
} |
420 |
|
} |
421 |
|
} |
422 |
|
|
423 |
6676137 |
Node TermDb::getOperatorRepresentative(TNode op) const { return op; } |
424 |
|
|
425 |
236985 |
bool TermDb::checkCongruentDisequal(TNode a, TNode b, std::vector<Node>& exp) |
426 |
|
{ |
427 |
236985 |
if (d_qstate.areDisequal(a, b)) |
428 |
|
{ |
429 |
11 |
exp.push_back(a.eqNode(b)); |
430 |
11 |
return true; |
431 |
|
} |
432 |
236974 |
return false; |
433 |
|
} |
434 |
|
|
435 |
2221328 |
bool TermDb::inRelevantDomain( TNode f, unsigned i, TNode r ) { |
436 |
|
// notice if we are not higher-order, getOperatorRepresentative is a no-op |
437 |
2221328 |
f = getOperatorRepresentative(f); |
438 |
2221328 |
computeUfTerms( f ); |
439 |
2221328 |
Assert(!d_qstate.getEqualityEngine()->hasTerm(r) |
440 |
|
|| d_qstate.getEqualityEngine()->getRepresentative(r) == r); |
441 |
2221328 |
std::map< Node, std::map< unsigned, std::vector< Node > > >::iterator it = d_func_map_rel_dom.find( f ); |
442 |
2221328 |
if( it != d_func_map_rel_dom.end() ){ |
443 |
2197271 |
std::map< unsigned, std::vector< Node > >::iterator it2 = it->second.find( i ); |
444 |
2197271 |
if( it2!=it->second.end() ){ |
445 |
2197271 |
return std::find( it2->second.begin(), it2->second.end(), r )!=it2->second.end(); |
446 |
|
}else{ |
447 |
|
return false; |
448 |
|
} |
449 |
|
}else{ |
450 |
24057 |
return false; |
451 |
|
} |
452 |
|
} |
453 |
|
|
454 |
4201600 |
bool TermDb::isTermActive( Node n ) { |
455 |
4201600 |
return d_inactive_map.find( n )==d_inactive_map.end(); |
456 |
|
//return !n.getAttribute(NoMatchAttribute()); |
457 |
|
} |
458 |
|
|
459 |
176620 |
void TermDb::setTermInactive( Node n ) { |
460 |
176620 |
d_inactive_map[n] = true; |
461 |
|
//Trace("term-db-debug2") << "set no match attribute" << std::endl; |
462 |
|
//NoMatchAttribute nma; |
463 |
|
//n.setAttribute(nma,true); |
464 |
176620 |
} |
465 |
|
|
466 |
4475010 |
bool TermDb::hasTermCurrent( Node n, bool useMode ) { |
467 |
4475010 |
if( !useMode ){ |
468 |
|
return d_has_map.find( n )!=d_has_map.end(); |
469 |
|
} |
470 |
|
//some assertions are not sent to EE |
471 |
4475010 |
if (options::termDbMode() == options::TermDbMode::ALL) |
472 |
|
{ |
473 |
4475010 |
return true; |
474 |
|
} |
475 |
|
else if (options::termDbMode() == options::TermDbMode::RELEVANT) |
476 |
|
{ |
477 |
|
return d_has_map.find( n )!=d_has_map.end(); |
478 |
|
} |
479 |
|
Assert(false) << "TermDb::hasTermCurrent: Unknown termDbMode : " << options::termDbMode(); |
480 |
|
return false; |
481 |
|
} |
482 |
|
|
483 |
1158 |
bool TermDb::isTermEligibleForInstantiation(TNode n, TNode f) |
484 |
|
{ |
485 |
1158 |
if( options::instMaxLevel()!=-1 ){ |
486 |
970 |
if( n.hasAttribute(InstLevelAttribute()) ){ |
487 |
|
int64_t fml = |
488 |
970 |
f.isNull() ? -1 : d_qreg.getQuantAttributes().getQuantInstLevel(f); |
489 |
970 |
unsigned ml = fml>=0 ? fml : options::instMaxLevel(); |
490 |
|
|
491 |
970 |
if( n.getAttribute(InstLevelAttribute())>ml ){ |
492 |
|
Trace("inst-add-debug") << "Term " << n << " has instantiation level " << n.getAttribute(InstLevelAttribute()); |
493 |
|
Trace("inst-add-debug") << ", which is more than maximum allowed level " << ml << " for this quantified formula." << std::endl; |
494 |
|
return false; |
495 |
|
} |
496 |
|
}else{ |
497 |
|
if( options::instLevelInputOnly() ){ |
498 |
|
Trace("inst-add-debug") << "Term " << n << " does not have an instantiation level." << std::endl; |
499 |
|
return false; |
500 |
|
} |
501 |
|
} |
502 |
|
} |
503 |
|
// it cannot have instantiation constants, which originate from |
504 |
|
// counterexample-guided instantiation strategies. |
505 |
1158 |
return !TermUtil::hasInstConstAttr(n); |
506 |
|
} |
507 |
|
|
508 |
188 |
Node TermDb::getEligibleTermInEqc( TNode r ) { |
509 |
188 |
if( isTermEligibleForInstantiation( r, TNode::null() ) ){ |
510 |
188 |
return r; |
511 |
|
}else{ |
512 |
|
std::map< Node, Node >::iterator it = d_term_elig_eqc.find( r ); |
513 |
|
if( it==d_term_elig_eqc.end() ){ |
514 |
|
Node h; |
515 |
|
eq::EqualityEngine* ee = d_qstate.getEqualityEngine(); |
516 |
|
eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee); |
517 |
|
while (!eqc_i.isFinished()) |
518 |
|
{ |
519 |
|
TNode n = (*eqc_i); |
520 |
|
++eqc_i; |
521 |
|
if (isTermEligibleForInstantiation(n, TNode::null())) |
522 |
|
{ |
523 |
|
h = n; |
524 |
|
break; |
525 |
|
} |
526 |
|
} |
527 |
|
d_term_elig_eqc[r] = h; |
528 |
|
return h; |
529 |
|
}else{ |
530 |
|
return it->second; |
531 |
|
} |
532 |
|
} |
533 |
|
} |
534 |
|
|
535 |
34025 |
bool TermDb::resetInternal(Theory::Effort e) |
536 |
|
{ |
537 |
|
// do nothing |
538 |
34025 |
return true; |
539 |
|
} |
540 |
|
|
541 |
34025 |
bool TermDb::finishResetInternal(Theory::Effort e) |
542 |
|
{ |
543 |
|
// do nothing |
544 |
34025 |
return true; |
545 |
|
} |
546 |
|
|
547 |
467145 |
void TermDb::addTermInternal(Node n) |
548 |
|
{ |
549 |
|
// do nothing |
550 |
467145 |
} |
551 |
|
|
552 |
85946 |
void TermDb::getOperatorsFor(TNode f, std::vector<TNode>& ops) |
553 |
|
{ |
554 |
85946 |
ops.push_back(f); |
555 |
85946 |
} |
556 |
|
|
557 |
|
void TermDb::setHasTerm( Node n ) { |
558 |
|
Trace("term-db-debug2") << "hasTerm : " << n << std::endl; |
559 |
|
if( d_has_map.find( n )==d_has_map.end() ){ |
560 |
|
d_has_map[n] = true; |
561 |
|
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
562 |
|
setHasTerm( n[i] ); |
563 |
|
} |
564 |
|
} |
565 |
|
} |
566 |
|
|
567 |
13467 |
void TermDb::presolve() { |
568 |
13467 |
if (options::incrementalSolving() && !options::termDbCd()) |
569 |
|
{ |
570 |
|
d_termsContext.pop(); |
571 |
|
d_termsContext.push(); |
572 |
|
} |
573 |
13467 |
} |
574 |
|
|
575 |
34975 |
bool TermDb::reset( Theory::Effort effort ){ |
576 |
34975 |
d_op_nonred_count.clear(); |
577 |
34975 |
d_arg_reps.clear(); |
578 |
34975 |
d_func_map_trie.clear(); |
579 |
34975 |
d_func_map_eqc_trie.clear(); |
580 |
34975 |
d_func_map_rel_dom.clear(); |
581 |
34975 |
d_consistent_ee = true; |
582 |
|
|
583 |
34975 |
eq::EqualityEngine* ee = d_qstate.getEqualityEngine(); |
584 |
|
|
585 |
34975 |
Assert(ee->consistent()); |
586 |
|
// if higher-order, add equalities for the purification terms now |
587 |
34975 |
if (!resetInternal(effort)) |
588 |
|
{ |
589 |
|
return false; |
590 |
|
} |
591 |
|
|
592 |
|
//compute has map |
593 |
34975 |
if (options::termDbMode() == options::TermDbMode::RELEVANT) |
594 |
|
{ |
595 |
|
d_has_map.clear(); |
596 |
|
d_term_elig_eqc.clear(); |
597 |
|
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee ); |
598 |
|
while( !eqcs_i.isFinished() ){ |
599 |
|
TNode r = (*eqcs_i); |
600 |
|
bool addedFirst = false; |
601 |
|
Node first; |
602 |
|
//TODO: ignoring singleton eqc isn't enough, need to ensure eqc are relevant |
603 |
|
eq::EqClassIterator eqc_i = eq::EqClassIterator(r, ee); |
604 |
|
while( !eqc_i.isFinished() ){ |
605 |
|
TNode n = (*eqc_i); |
606 |
|
if( first.isNull() ){ |
607 |
|
first = n; |
608 |
|
}else{ |
609 |
|
if( !addedFirst ){ |
610 |
|
addedFirst = true; |
611 |
|
setHasTerm( first ); |
612 |
|
} |
613 |
|
setHasTerm( n ); |
614 |
|
} |
615 |
|
++eqc_i; |
616 |
|
} |
617 |
|
++eqcs_i; |
618 |
|
} |
619 |
|
const LogicInfo& logicInfo = d_qstate.getLogicInfo(); |
620 |
|
for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId) |
621 |
|
{ |
622 |
|
if (!logicInfo.isTheoryEnabled(theoryId)) |
623 |
|
{ |
624 |
|
continue; |
625 |
|
} |
626 |
|
for (context::CDList<Assertion>::const_iterator |
627 |
|
it = d_qstate.factsBegin(theoryId), |
628 |
|
it_end = d_qstate.factsEnd(theoryId); |
629 |
|
it != it_end; |
630 |
|
++it) |
631 |
|
{ |
632 |
|
setHasTerm((*it).d_assertion); |
633 |
|
} |
634 |
|
} |
635 |
|
} |
636 |
|
// finish reset |
637 |
34975 |
return finishResetInternal(effort); |
638 |
|
} |
639 |
|
|
640 |
22018 |
TNodeTrie* TermDb::getTermArgTrie(Node f) |
641 |
|
{ |
642 |
22018 |
f = getOperatorRepresentative(f); |
643 |
22018 |
computeUfTerms( f ); |
644 |
22018 |
std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f); |
645 |
22018 |
if( itut!=d_func_map_trie.end() ){ |
646 |
13963 |
return &itut->second; |
647 |
|
}else{ |
648 |
8055 |
return NULL; |
649 |
|
} |
650 |
|
} |
651 |
|
|
652 |
1895920 |
TNodeTrie* TermDb::getTermArgTrie(Node eqc, Node f) |
653 |
|
{ |
654 |
1895920 |
f = getOperatorRepresentative(f); |
655 |
1895920 |
computeUfEqcTerms( f ); |
656 |
1895920 |
std::map<Node, TNodeTrie>::iterator itut = d_func_map_eqc_trie.find(f); |
657 |
1895920 |
if( itut==d_func_map_eqc_trie.end() ){ |
658 |
|
return NULL; |
659 |
|
}else{ |
660 |
1895920 |
if( eqc.isNull() ){ |
661 |
986298 |
return &itut->second; |
662 |
|
}else{ |
663 |
|
std::map<TNode, TNodeTrie>::iterator itute = |
664 |
909622 |
itut->second.d_data.find(eqc); |
665 |
909622 |
if( itute!=itut->second.d_data.end() ){ |
666 |
544691 |
return &itute->second; |
667 |
|
}else{ |
668 |
364931 |
return NULL; |
669 |
|
} |
670 |
|
} |
671 |
|
} |
672 |
|
} |
673 |
|
|
674 |
|
TNode TermDb::getCongruentTerm( Node f, Node n ) { |
675 |
|
f = getOperatorRepresentative(f); |
676 |
|
computeUfTerms( f ); |
677 |
|
std::map<Node, TNodeTrie>::iterator itut = d_func_map_trie.find(f); |
678 |
|
if( itut!=d_func_map_trie.end() ){ |
679 |
|
computeArgReps( n ); |
680 |
|
return itut->second.existsTerm( d_arg_reps[n] ); |
681 |
|
}else{ |
682 |
|
return TNode::null(); |
683 |
|
} |
684 |
|
} |
685 |
|
|
686 |
1526995 |
TNode TermDb::getCongruentTerm( Node f, std::vector< TNode >& args ) { |
687 |
1526995 |
f = getOperatorRepresentative(f); |
688 |
1526995 |
computeUfTerms( f ); |
689 |
1526995 |
return d_func_map_trie[f].existsTerm( args ); |
690 |
|
} |
691 |
|
|
692 |
|
} // namespace quantifiers |
693 |
|
} // namespace theory |
694 |
31137 |
} // namespace cvc5 |