1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Liana Hadarean, Aina Niemetz, Mathias Preiner |
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 |
|
* [[ Add lengthier description here ]] |
14 |
|
* \todo document this file |
15 |
|
*/ |
16 |
|
#include "theory/bv/abstraction.h" |
17 |
|
|
18 |
|
#include "expr/skolem_manager.h" |
19 |
|
#include "options/bv_options.h" |
20 |
|
#include "printer/printer.h" |
21 |
|
#include "smt/dump.h" |
22 |
|
#include "smt/smt_engine.h" |
23 |
|
#include "smt/smt_engine_scope.h" |
24 |
|
#include "smt/smt_statistics_registry.h" |
25 |
|
#include "theory/bv/theory_bv_utils.h" |
26 |
|
#include "theory/rewriter.h" |
27 |
|
|
28 |
|
using namespace cvc5; |
29 |
|
using namespace cvc5::theory; |
30 |
|
using namespace cvc5::theory::bv; |
31 |
|
using namespace cvc5::context; |
32 |
|
|
33 |
|
using namespace std; |
34 |
|
using namespace cvc5::theory::bv::utils; |
35 |
|
|
36 |
4 |
bool AbstractionModule::applyAbstraction(const std::vector<Node>& assertions, |
37 |
|
std::vector<Node>& new_assertions) |
38 |
|
{ |
39 |
4 |
Debug("bv-abstraction") << "AbstractionModule::applyAbstraction\n"; |
40 |
|
|
41 |
8 |
TimerStat::CodeTimer abstractionTimer(d_statistics.d_abstractionTime); |
42 |
|
|
43 |
8 |
TNodeSet seen; |
44 |
14 |
for (unsigned i = 0; i < assertions.size(); ++i) |
45 |
|
{ |
46 |
10 |
if (assertions[i].getKind() == kind::OR) |
47 |
|
{ |
48 |
22 |
for (unsigned j = 0; j < assertions[i].getNumChildren(); ++j) |
49 |
|
{ |
50 |
16 |
if (!isConjunctionOfAtoms(assertions[i][j], seen)) |
51 |
|
{ |
52 |
4 |
continue; |
53 |
|
} |
54 |
24 |
Node signature = computeSignature(assertions[i][j]); |
55 |
12 |
storeSignature(signature, assertions[i][j]); |
56 |
12 |
Debug("bv-abstraction") << " assertion: " << assertions[i][j] << "\n"; |
57 |
12 |
Debug("bv-abstraction") << " signature: " << signature << "\n"; |
58 |
|
} |
59 |
|
} |
60 |
|
} |
61 |
4 |
finalizeSignatures(); |
62 |
|
|
63 |
14 |
for (unsigned i = 0; i < assertions.size(); ++i) |
64 |
|
{ |
65 |
20 |
if (assertions[i].getKind() == kind::OR |
66 |
20 |
&& assertions[i][0].getKind() == kind::AND) |
67 |
|
{ |
68 |
4 |
std::vector<Node> new_children; |
69 |
6 |
for (unsigned j = 0; j < assertions[i].getNumChildren(); ++j) |
70 |
|
{ |
71 |
4 |
if (hasSignature(assertions[i][j])) |
72 |
|
{ |
73 |
|
new_children.push_back(abstractSignatures(assertions[i][j])); |
74 |
|
} |
75 |
|
else |
76 |
|
{ |
77 |
4 |
new_children.push_back(assertions[i][j]); |
78 |
|
} |
79 |
|
} |
80 |
2 |
new_assertions.push_back(utils::mkOr(new_children)); |
81 |
|
} |
82 |
|
else |
83 |
|
{ |
84 |
|
// assertions that are not changed |
85 |
8 |
new_assertions.push_back(assertions[i]); |
86 |
|
} |
87 |
|
} |
88 |
|
|
89 |
8 |
if (options::skolemizeArguments()) |
90 |
|
{ |
91 |
|
skolemizeArguments(new_assertions); |
92 |
|
} |
93 |
|
|
94 |
|
// if we are using the eager solver reverse the abstraction |
95 |
4 |
if (options::bitblastMode() == options::BitblastMode::EAGER) |
96 |
|
{ |
97 |
2 |
if (d_funcToSignature.size() == 0) |
98 |
|
{ |
99 |
|
// we did not change anything |
100 |
2 |
return false; |
101 |
|
} |
102 |
|
NodeNodeMap seen_rev; |
103 |
|
for (unsigned i = 0; i < new_assertions.size(); ++i) |
104 |
|
{ |
105 |
|
new_assertions[i] = reverseAbstraction(new_assertions[i], seen_rev); |
106 |
|
} |
107 |
|
// we undo the abstraction functions so the logic is QF_BV still |
108 |
|
return true; |
109 |
|
} |
110 |
|
|
111 |
|
// return true if we have created new function symbols for the problem |
112 |
2 |
return d_funcToSignature.size() != 0; |
113 |
|
} |
114 |
|
|
115 |
20 |
bool AbstractionModule::isConjunctionOfAtoms(TNode node, TNodeSet& seen) |
116 |
|
{ |
117 |
20 |
if (seen.find(node)!= seen.end()) |
118 |
|
return true; |
119 |
|
|
120 |
20 |
if (!node.getType().isBitVector() && node.getKind() != kind::AND) |
121 |
|
{ |
122 |
16 |
return utils::isBVPredicate(node); |
123 |
|
} |
124 |
|
|
125 |
4 |
if (node.getNumChildren() == 0) |
126 |
|
return true; |
127 |
|
|
128 |
4 |
for (unsigned i = 0; i < node.getNumChildren(); ++i) { |
129 |
4 |
if (!isConjunctionOfAtoms(node[i], seen)) |
130 |
|
{ |
131 |
4 |
return false; |
132 |
|
} |
133 |
|
} |
134 |
|
seen.insert(node); |
135 |
|
return true; |
136 |
|
} |
137 |
|
|
138 |
|
|
139 |
|
Node AbstractionModule::reverseAbstraction(Node assertion, NodeNodeMap& seen) { |
140 |
|
|
141 |
|
if (seen.find(assertion) != seen.end()) |
142 |
|
return seen[assertion]; |
143 |
|
|
144 |
|
if (isAbstraction(assertion)) { |
145 |
|
Node interp = getInterpretation(assertion); |
146 |
|
seen[assertion] = interp; |
147 |
|
Assert(interp.getType() == assertion.getType()); |
148 |
|
return interp; |
149 |
|
} |
150 |
|
|
151 |
|
if (assertion.getNumChildren() == 0) { |
152 |
|
seen[assertion] = assertion; |
153 |
|
return assertion; |
154 |
|
} |
155 |
|
|
156 |
|
NodeBuilder result(assertion.getKind()); |
157 |
|
if (assertion.getMetaKind() == kind::metakind::PARAMETERIZED) { |
158 |
|
result << assertion.getOperator(); |
159 |
|
} |
160 |
|
|
161 |
|
for (unsigned i = 0; i < assertion.getNumChildren(); ++i) { |
162 |
|
result << reverseAbstraction(assertion[i], seen); |
163 |
|
} |
164 |
|
Node res = result; |
165 |
|
seen[assertion] = res; |
166 |
|
return res; |
167 |
|
} |
168 |
|
|
169 |
|
void AbstractionModule::skolemizeArguments(std::vector<Node>& assertions) |
170 |
|
{ |
171 |
|
NodeManager* nm = NodeManager::currentNM(); |
172 |
|
for (unsigned i = 0; i < assertions.size(); ++i) |
173 |
|
{ |
174 |
|
TNode assertion = assertions[i]; |
175 |
|
if (assertion.getKind() != kind::OR) continue; |
176 |
|
|
177 |
|
bool is_skolemizable = true; |
178 |
|
for (unsigned k = 0; k < assertion.getNumChildren(); ++k) |
179 |
|
{ |
180 |
|
if (assertion[k].getKind() != kind::EQUAL |
181 |
|
|| assertion[k][0].getKind() != kind::APPLY_UF |
182 |
|
|| assertion[k][1].getKind() != kind::CONST_BITVECTOR |
183 |
|
|| assertion[k][1].getConst<BitVector>() != BitVector(1, 1u)) |
184 |
|
{ |
185 |
|
is_skolemizable = false; |
186 |
|
break; |
187 |
|
} |
188 |
|
} |
189 |
|
|
190 |
|
if (!is_skolemizable) continue; |
191 |
|
|
192 |
|
ArgsTable assertion_table; |
193 |
|
|
194 |
|
// collect function symbols and their arguments |
195 |
|
for (unsigned j = 0; j < assertion.getNumChildren(); ++j) |
196 |
|
{ |
197 |
|
TNode current = assertion[j]; |
198 |
|
Assert(current.getKind() == kind::EQUAL |
199 |
|
&& current[0].getKind() == kind::APPLY_UF); |
200 |
|
TNode func = current[0]; |
201 |
|
ArgsVec args; |
202 |
|
for (unsigned k = 0; k < func.getNumChildren(); ++k) |
203 |
|
{ |
204 |
|
args.push_back(func[k]); |
205 |
|
} |
206 |
|
assertion_table.addEntry(func.getOperator(), args); |
207 |
|
} |
208 |
|
|
209 |
|
NodeBuilder assertion_builder(kind::OR); |
210 |
|
// construct skolemized assertion |
211 |
|
for (ArgsTable::iterator it = assertion_table.begin(); |
212 |
|
it != assertion_table.end(); |
213 |
|
++it) |
214 |
|
{ |
215 |
|
// for each function symbol |
216 |
|
++(d_statistics.d_numArgsSkolemized); |
217 |
|
TNode func = it->first; |
218 |
|
ArgsTableEntry& args = it->second; |
219 |
|
NodeBuilder skolem_func(kind::APPLY_UF); |
220 |
|
skolem_func << func; |
221 |
|
std::vector<Node> skolem_args; |
222 |
|
|
223 |
|
for (unsigned j = 0; j < args.getArity(); ++j) |
224 |
|
{ |
225 |
|
bool all_same = true; |
226 |
|
for (unsigned k = 1; k < args.getNumEntries(); ++k) |
227 |
|
{ |
228 |
|
if (args.getEntry(k)[j] != args.getEntry(0)[j]) all_same = false; |
229 |
|
} |
230 |
|
Node new_arg = all_same |
231 |
|
? (Node)args.getEntry(0)[j] |
232 |
|
: utils::mkVar(utils::getSize(args.getEntry(0)[j])); |
233 |
|
skolem_args.push_back(new_arg); |
234 |
|
skolem_func << new_arg; |
235 |
|
} |
236 |
|
|
237 |
|
Node skolem_func_eq1 = |
238 |
|
nm->mkNode(kind::EQUAL, (Node)skolem_func, utils::mkConst(1, 1u)); |
239 |
|
|
240 |
|
// enumerate arguments assignments |
241 |
|
std::vector<Node> or_assignments; |
242 |
|
for (const ArgsVec& av : args) |
243 |
|
// for (ArgsTableEntry::iterator it = args.begin(); it != args.end(); |
244 |
|
// ++it) |
245 |
|
{ |
246 |
|
NodeBuilder arg_assignment(kind::AND); |
247 |
|
// ArgsVec& args = *it; |
248 |
|
for (unsigned k = 0; k < av.size(); ++k) |
249 |
|
{ |
250 |
|
Node eq = nm->mkNode(kind::EQUAL, av[k], skolem_args[k]); |
251 |
|
arg_assignment << eq; |
252 |
|
} |
253 |
|
or_assignments.push_back(arg_assignment); |
254 |
|
} |
255 |
|
|
256 |
|
Node new_func_def = |
257 |
|
utils::mkAnd(skolem_func_eq1, utils::mkOr(or_assignments)); |
258 |
|
assertion_builder << new_func_def; |
259 |
|
} |
260 |
|
Node new_assertion = assertion_builder; |
261 |
|
Debug("bv-abstraction-dbg") << "AbstractionModule::skolemizeArguments " |
262 |
|
<< assertions[i] << " => \n"; |
263 |
|
Debug("bv-abstraction-dbg") << " " << new_assertion; |
264 |
|
assertions[i] = new_assertion; |
265 |
|
} |
266 |
|
} |
267 |
|
|
268 |
12 |
void AbstractionModule::storeSignature(Node signature, TNode assertion) { |
269 |
12 |
if(d_signatures.find(signature) == d_signatures.end()) { |
270 |
4 |
d_signatures[signature] = 0; |
271 |
|
} |
272 |
12 |
d_signatures[signature] = d_signatures[signature] + 1; |
273 |
12 |
d_assertionToSignature[assertion] = signature; |
274 |
12 |
} |
275 |
|
|
276 |
12 |
Node AbstractionModule::computeSignature(TNode node) { |
277 |
12 |
resetSignatureIndex(); |
278 |
24 |
NodeNodeMap cache; |
279 |
12 |
Node sig = computeSignatureRec(node, cache); |
280 |
24 |
return sig; |
281 |
|
} |
282 |
|
|
283 |
36 |
Node AbstractionModule::getSignatureSkolem(TNode node) |
284 |
|
{ |
285 |
36 |
Assert(node.getMetaKind() == kind::metakind::VARIABLE); |
286 |
36 |
NodeManager* nm = NodeManager::currentNM(); |
287 |
36 |
SkolemManager* sm = nm->getSkolemManager(); |
288 |
36 |
unsigned bitwidth = utils::getSize(node); |
289 |
36 |
if (d_signatureSkolems.find(bitwidth) == d_signatureSkolems.end()) |
290 |
|
{ |
291 |
2 |
d_signatureSkolems[bitwidth] = vector<Node>(); |
292 |
|
} |
293 |
|
|
294 |
36 |
vector<Node>& skolems = d_signatureSkolems[bitwidth]; |
295 |
|
// get the index of bv variables of this size |
296 |
36 |
unsigned index = getBitwidthIndex(bitwidth); |
297 |
36 |
Assert(skolems.size() + 1 >= index); |
298 |
36 |
if (skolems.size() == index) |
299 |
|
{ |
300 |
12 |
ostringstream os; |
301 |
6 |
os << "sig_" << bitwidth << "_" << index; |
302 |
18 |
skolems.push_back(sm->mkDummySkolem(os.str(), |
303 |
12 |
nm->mkBitVectorType(bitwidth), |
304 |
|
"skolem for computing signatures")); |
305 |
|
} |
306 |
36 |
++(d_signatureIndices[bitwidth]); |
307 |
36 |
return skolems[index]; |
308 |
|
} |
309 |
|
|
310 |
36 |
unsigned AbstractionModule::getBitwidthIndex(unsigned bitwidth) { |
311 |
36 |
if (d_signatureIndices.find(bitwidth) == d_signatureIndices.end()) { |
312 |
2 |
d_signatureIndices[bitwidth] = 0; |
313 |
|
} |
314 |
36 |
return d_signatureIndices[bitwidth]; |
315 |
|
} |
316 |
|
|
317 |
12 |
void AbstractionModule::resetSignatureIndex() { |
318 |
22 |
for (IndexMap::iterator it = d_signatureIndices.begin(); it != d_signatureIndices.end(); ++it) { |
319 |
10 |
it->second = 0; |
320 |
|
} |
321 |
12 |
} |
322 |
|
|
323 |
4 |
bool AbstractionModule::hasSignature(Node node) { |
324 |
4 |
return d_assertionToSignature.find(node) != d_assertionToSignature.end(); |
325 |
|
} |
326 |
|
|
327 |
|
Node AbstractionModule::getGeneralizedSignature(Node node) { |
328 |
|
NodeNodeMap::const_iterator it = d_assertionToSignature.find(node); |
329 |
|
Assert(it != d_assertionToSignature.end()); |
330 |
|
Node generalized_signature = getGeneralization(it->second); |
331 |
|
return generalized_signature; |
332 |
|
} |
333 |
|
|
334 |
114 |
Node AbstractionModule::computeSignatureRec(TNode node, NodeNodeMap& cache) { |
335 |
114 |
if (cache.find(node) != cache.end()) { |
336 |
|
return cache.find(node)->second; |
337 |
|
} |
338 |
|
|
339 |
114 |
if (node.getNumChildren() == 0) { |
340 |
60 |
if (node.getKind() == kind::CONST_BITVECTOR) |
341 |
24 |
return node; |
342 |
|
|
343 |
72 |
Node sig = getSignatureSkolem(node); |
344 |
36 |
cache[node] = sig; |
345 |
36 |
return sig; |
346 |
|
} |
347 |
|
|
348 |
108 |
NodeBuilder builder(node.getKind()); |
349 |
54 |
if (node.getMetaKind() == kind::metakind::PARAMETERIZED) { |
350 |
12 |
builder << node.getOperator(); |
351 |
|
} |
352 |
156 |
for (unsigned i = 0; i < node.getNumChildren(); ++i) { |
353 |
204 |
Node converted = computeSignatureRec(node[i], cache); |
354 |
102 |
builder << converted; |
355 |
|
} |
356 |
108 |
Node result = builder; |
357 |
54 |
cache[node] = result; |
358 |
54 |
return result; |
359 |
|
} |
360 |
|
|
361 |
|
/** |
362 |
|
* Returns 0, if the two are equal, |
363 |
|
* 1 if s is a generalization of t |
364 |
|
* 2 if t is a generalization of s |
365 |
|
* -1 if the two cannot be unified |
366 |
|
* |
367 |
|
* @param s |
368 |
|
* @param t |
369 |
|
* |
370 |
|
* @return |
371 |
|
*/ |
372 |
4 |
int AbstractionModule::comparePatterns(TNode s, TNode t) { |
373 |
4 |
if (s.getKind() == kind::SKOLEM && |
374 |
|
t.getKind() == kind::SKOLEM) { |
375 |
|
return 0; |
376 |
|
} |
377 |
|
|
378 |
4 |
if (s.getKind() == kind::CONST_BITVECTOR && |
379 |
|
t.getKind() == kind::CONST_BITVECTOR) { |
380 |
|
if (s == t) { |
381 |
|
return 0; |
382 |
|
} else { |
383 |
|
return -1; |
384 |
|
} |
385 |
|
} |
386 |
|
|
387 |
4 |
if (s.getKind() == kind::SKOLEM && |
388 |
|
t.getKind() == kind::CONST_BITVECTOR) { |
389 |
|
return 1; |
390 |
|
} |
391 |
|
|
392 |
4 |
if (s.getKind() == kind::CONST_BITVECTOR && |
393 |
|
t.getKind() == kind::SKOLEM) { |
394 |
|
return 2; |
395 |
|
} |
396 |
|
|
397 |
6 |
if (s.getNumChildren() != t.getNumChildren() || |
398 |
2 |
s.getKind() != t.getKind()) |
399 |
2 |
return -1; |
400 |
|
|
401 |
2 |
int unify = 0; |
402 |
2 |
for (unsigned i = 0; i < s.getNumChildren(); ++i) { |
403 |
2 |
int unify_i = comparePatterns(s[i], t[i]); |
404 |
2 |
if (unify_i < 0) |
405 |
2 |
return -1; |
406 |
|
if (unify == 0) { |
407 |
|
unify = unify_i; |
408 |
|
} else if (unify != unify_i && unify_i != 0) { |
409 |
|
return -1; |
410 |
|
} |
411 |
|
} |
412 |
|
return unify; |
413 |
|
} |
414 |
|
|
415 |
16 |
TNode AbstractionModule::getGeneralization(TNode term) { |
416 |
16 |
NodeNodeMap::iterator it = d_sigToGeneralization.find(term); |
417 |
|
// if not in the map we add it |
418 |
16 |
if (it == d_sigToGeneralization.end()) { |
419 |
4 |
d_sigToGeneralization[term] = term; |
420 |
4 |
return term; |
421 |
|
} |
422 |
|
// doesn't have a generalization |
423 |
12 |
if (it->second == term) |
424 |
12 |
return term; |
425 |
|
|
426 |
|
TNode generalization = getGeneralization(it->second); |
427 |
|
Assert(generalization != term); |
428 |
|
d_sigToGeneralization[term] = generalization; |
429 |
|
return generalization; |
430 |
|
} |
431 |
|
|
432 |
|
void AbstractionModule::storeGeneralization(TNode s, TNode t) { |
433 |
|
Assert(s == getGeneralization(s)); |
434 |
|
Assert(t == getGeneralization(t)); |
435 |
|
d_sigToGeneralization[s] = t; |
436 |
|
} |
437 |
|
|
438 |
4 |
void AbstractionModule::finalizeSignatures() |
439 |
|
{ |
440 |
4 |
NodeManager* nm = NodeManager::currentNM(); |
441 |
4 |
SkolemManager* sm = nm->getSkolemManager(); |
442 |
8 |
Debug("bv-abstraction") |
443 |
4 |
<< "AbstractionModule::finalizeSignatures num signatures = " |
444 |
4 |
<< d_signatures.size() << "\n"; |
445 |
8 |
TNodeSet new_signatures; |
446 |
|
|
447 |
|
// "unify" signatures |
448 |
8 |
for (SignatureMap::const_iterator ss = d_signatures.begin(); |
449 |
8 |
ss != d_signatures.end(); |
450 |
|
++ss) |
451 |
|
{ |
452 |
10 |
for (SignatureMap::const_iterator tt = ss; tt != d_signatures.end(); ++tt) |
453 |
|
{ |
454 |
10 |
TNode t = getGeneralization(tt->first); |
455 |
10 |
TNode s = getGeneralization(ss->first); |
456 |
|
|
457 |
6 |
if (t != s) |
458 |
|
{ |
459 |
2 |
int status = comparePatterns(s, t); |
460 |
2 |
Assert(status); |
461 |
2 |
if (status < 0) continue; |
462 |
|
if (status == 1) |
463 |
|
{ |
464 |
|
storeGeneralization(t, s); |
465 |
|
} |
466 |
|
else |
467 |
|
{ |
468 |
|
storeGeneralization(s, t); |
469 |
|
} |
470 |
|
} |
471 |
|
} |
472 |
|
} |
473 |
|
// keep only most general signatures |
474 |
8 |
for (SignatureMap::iterator it = d_signatures.begin(); |
475 |
8 |
it != d_signatures.end();) |
476 |
|
{ |
477 |
8 |
TNode sig = it->first; |
478 |
8 |
TNode gen = getGeneralization(sig); |
479 |
4 |
if (sig != gen) |
480 |
|
{ |
481 |
|
Assert(d_signatures.find(gen) != d_signatures.end()); |
482 |
|
// update the count |
483 |
|
d_signatures[gen] += d_signatures[sig]; |
484 |
|
d_signatures.erase(it++); |
485 |
|
} |
486 |
|
else |
487 |
|
{ |
488 |
4 |
++it; |
489 |
|
} |
490 |
|
} |
491 |
|
|
492 |
|
// remove signatures that are not frequent enough |
493 |
8 |
for (SignatureMap::iterator it = d_signatures.begin(); |
494 |
8 |
it != d_signatures.end();) |
495 |
|
{ |
496 |
4 |
if (it->second <= 7) |
497 |
|
{ |
498 |
4 |
d_signatures.erase(it++); |
499 |
|
} |
500 |
|
else |
501 |
|
{ |
502 |
|
++it; |
503 |
|
} |
504 |
|
} |
505 |
|
|
506 |
4 |
for (SignatureMap::const_iterator it = d_signatures.begin(); |
507 |
4 |
it != d_signatures.end(); |
508 |
|
++it) |
509 |
|
{ |
510 |
|
TNode signature = it->first; |
511 |
|
// we already processed this signature |
512 |
|
Assert(d_signatureToFunc.find(signature) == d_signatureToFunc.end()); |
513 |
|
|
514 |
|
Debug("bv-abstraction") << "Processing signature " << signature << " count " |
515 |
|
<< it->second << "\n"; |
516 |
|
std::vector<TypeNode> arg_types; |
517 |
|
TNodeSet seen; |
518 |
|
collectArgumentTypes(signature, arg_types, seen); |
519 |
|
Assert(signature.getType().isBoolean()); |
520 |
|
// make function return a bitvector of size 1 |
521 |
|
// Node bv_function = nm->mkNode(kind::ITE, signature, utils::mkConst(1, |
522 |
|
// 1u), utils::mkConst(1, 0u)); |
523 |
|
TypeNode range = nm->mkBitVectorType(1); |
524 |
|
|
525 |
|
TypeNode abs_type = nm->mkFunctionType(arg_types, range); |
526 |
|
Node abs_func = sm->mkDummySkolem( |
527 |
|
"abs_$$", abs_type, "abstraction function for bv theory"); |
528 |
|
Debug("bv-abstraction") << " abstracted by function " << abs_func << "\n"; |
529 |
|
|
530 |
|
// NOTE: signature expression type is BOOLEAN |
531 |
|
d_signatureToFunc[signature] = abs_func; |
532 |
|
d_funcToSignature[abs_func] = signature; |
533 |
|
} |
534 |
|
|
535 |
8 |
Debug("bv-abstraction") << "AbstractionModule::finalizeSignatures abstracted " |
536 |
4 |
<< d_signatureToFunc.size() << " signatures. \n"; |
537 |
4 |
} |
538 |
|
|
539 |
|
void AbstractionModule::collectArgumentTypes(TNode sig, std::vector<TypeNode>& types, TNodeSet& seen) { |
540 |
|
if (seen.find(sig) != seen.end()) |
541 |
|
return; |
542 |
|
|
543 |
|
if (sig.getKind() == kind::SKOLEM) { |
544 |
|
types.push_back(sig.getType()); |
545 |
|
seen.insert(sig); |
546 |
|
return; |
547 |
|
} |
548 |
|
|
549 |
|
for (unsigned i = 0; i < sig.getNumChildren(); ++i) { |
550 |
|
collectArgumentTypes(sig[i], types, seen); |
551 |
|
seen.insert(sig); |
552 |
|
} |
553 |
|
} |
554 |
|
|
555 |
|
void AbstractionModule::collectArguments(TNode node, TNode signature, std::vector<Node>& args, TNodeSet& seen) { |
556 |
|
if (seen.find(node)!= seen.end()) |
557 |
|
return; |
558 |
|
|
559 |
|
if (node.getMetaKind() == kind::metakind::VARIABLE |
560 |
|
|| node.getKind() == kind::CONST_BITVECTOR) |
561 |
|
{ |
562 |
|
// a constant in the node can either map to an argument of the abstraction |
563 |
|
// or can be hard-coded and part of the abstraction |
564 |
|
if (signature.getKind() == kind::SKOLEM) { |
565 |
|
args.push_back(node); |
566 |
|
seen.insert(node); |
567 |
|
} else { |
568 |
|
Assert(signature.getKind() == kind::CONST_BITVECTOR); |
569 |
|
} |
570 |
|
// |
571 |
|
return; |
572 |
|
} |
573 |
|
Assert(node.getKind() == signature.getKind() |
574 |
|
&& node.getNumChildren() == signature.getNumChildren()); |
575 |
|
|
576 |
|
for (unsigned i = 0; i < node.getNumChildren(); ++i) { |
577 |
|
collectArguments(node[i], signature[i], args, seen); |
578 |
|
seen.insert(node); |
579 |
|
} |
580 |
|
} |
581 |
|
|
582 |
|
Node AbstractionModule::abstractSignatures(TNode assertion) |
583 |
|
{ |
584 |
|
Debug("bv-abstraction") << "AbstractionModule::abstractSignatures " |
585 |
|
<< assertion << "\n"; |
586 |
|
NodeManager* nm = NodeManager::currentNM(); |
587 |
|
// assume the assertion has been fully abstracted |
588 |
|
Node signature = getGeneralizedSignature(assertion); |
589 |
|
|
590 |
|
Debug("bv-abstraction") << " with sig " << signature << "\n"; |
591 |
|
NodeNodeMap::iterator it = d_signatureToFunc.find(signature); |
592 |
|
if (it != d_signatureToFunc.end()) |
593 |
|
{ |
594 |
|
std::vector<Node> args; |
595 |
|
TNode func = it->second; |
596 |
|
// pushing the function symbol |
597 |
|
args.push_back(func); |
598 |
|
TNodeSet seen; |
599 |
|
collectArguments(assertion, signature, args, seen); |
600 |
|
std::vector<TNode> real_args; |
601 |
|
for (unsigned i = 1; i < args.size(); ++i) |
602 |
|
{ |
603 |
|
real_args.push_back(args[i]); |
604 |
|
} |
605 |
|
d_argsTable.addEntry(func, real_args); |
606 |
|
Node result = nm->mkNode( |
607 |
|
kind::EQUAL, |
608 |
|
nm->mkNode(kind::APPLY_UF, args), utils::mkConst(1, 1u)); |
609 |
|
Debug("bv-abstraction") << "=> " << result << "\n"; |
610 |
|
Assert(result.getType() == assertion.getType()); |
611 |
|
return result; |
612 |
|
} |
613 |
|
return assertion; |
614 |
|
} |
615 |
|
|
616 |
12 |
bool AbstractionModule::isAbstraction(TNode node) { |
617 |
12 |
if (node.getKind() != kind::EQUAL) |
618 |
|
return false; |
619 |
36 |
if ((node[0].getKind() != kind::CONST_BITVECTOR || |
620 |
84 |
node[1].getKind() != kind::APPLY_UF) && |
621 |
36 |
(node[1].getKind() != kind::CONST_BITVECTOR || |
622 |
12 |
node[0].getKind() != kind::APPLY_UF)) |
623 |
12 |
return false; |
624 |
|
|
625 |
|
TNode constant = node[0].getKind() == kind::CONST_BITVECTOR ? node[0] : node[1]; |
626 |
|
TNode func = node[0].getKind() == kind::APPLY_UF ? node[0] : node[1]; |
627 |
|
Assert(constant.getKind() == kind::CONST_BITVECTOR |
628 |
|
&& func.getKind() == kind::APPLY_UF); |
629 |
|
if (utils::getSize(constant) != 1) |
630 |
|
return false; |
631 |
|
if (constant != utils::mkConst(1, 1u)) |
632 |
|
return false; |
633 |
|
|
634 |
|
TNode func_symbol = func.getOperator(); |
635 |
|
if (d_funcToSignature.find(func_symbol) == d_funcToSignature.end()) |
636 |
|
return false; |
637 |
|
|
638 |
|
return true; |
639 |
|
} |
640 |
|
|
641 |
|
Node AbstractionModule::getInterpretation(TNode node) { |
642 |
|
Assert(isAbstraction(node)); |
643 |
|
TNode constant = node[0].getKind() == kind::CONST_BITVECTOR ? node[0] : node[1]; |
644 |
|
TNode apply = node[0].getKind() == kind::APPLY_UF ? node[0] : node[1]; |
645 |
|
Assert(constant.getKind() == kind::CONST_BITVECTOR |
646 |
|
&& apply.getKind() == kind::APPLY_UF); |
647 |
|
|
648 |
|
Node func = apply.getOperator(); |
649 |
|
Assert(d_funcToSignature.find(func) != d_funcToSignature.end()); |
650 |
|
|
651 |
|
Node sig = d_funcToSignature[func]; |
652 |
|
|
653 |
|
// substitute arguments in signature |
654 |
|
TNodeTNodeMap seen; |
655 |
|
unsigned index = 0; |
656 |
|
Node result = substituteArguments(sig, apply, index, seen); |
657 |
|
Assert(result.getType().isBoolean()); |
658 |
|
Assert(index == apply.getNumChildren()); |
659 |
|
// Debug("bv-abstraction") << "AbstractionModule::getInterpretation " << node << "\n"; |
660 |
|
// Debug("bv-abstraction") << " => " << result << "\n"; |
661 |
|
return result; |
662 |
|
} |
663 |
|
|
664 |
|
Node AbstractionModule::substituteArguments(TNode signature, TNode apply, unsigned& index, TNodeTNodeMap& seen) { |
665 |
|
if (seen.find(signature) != seen.end()) { |
666 |
|
return seen[signature]; |
667 |
|
} |
668 |
|
|
669 |
|
if (signature.getKind() == kind::SKOLEM) { |
670 |
|
// return corresponding argument and increment counter |
671 |
|
seen[signature] = apply[index]; |
672 |
|
return apply[index++]; |
673 |
|
} |
674 |
|
|
675 |
|
if (signature.getNumChildren() == 0) { |
676 |
|
Assert(signature.getMetaKind() != kind::metakind::VARIABLE); |
677 |
|
seen[signature] = signature; |
678 |
|
return signature; |
679 |
|
} |
680 |
|
|
681 |
|
NodeBuilder builder(signature.getKind()); |
682 |
|
if (signature.getMetaKind() == kind::metakind::PARAMETERIZED) { |
683 |
|
builder << signature.getOperator(); |
684 |
|
} |
685 |
|
|
686 |
|
for (unsigned i = 0; i < signature.getNumChildren(); ++i) { |
687 |
|
Node child = substituteArguments(signature[i], apply, index, seen); |
688 |
|
builder << child; |
689 |
|
} |
690 |
|
|
691 |
|
Node result = builder; |
692 |
|
seen[signature]= result; |
693 |
|
|
694 |
|
return result; |
695 |
|
} |
696 |
|
|
697 |
|
Node AbstractionModule::simplifyConflict(TNode conflict) { |
698 |
|
Debug("bv-abstraction-dbg") << "AbstractionModule::simplifyConflict " << conflict << "\n"; |
699 |
|
if (conflict.getKind() != kind::AND) |
700 |
|
return conflict; |
701 |
|
|
702 |
|
std::vector<Node> conjuncts; |
703 |
|
for (unsigned i = 0; i < conflict.getNumChildren(); ++i) |
704 |
|
conjuncts.push_back(conflict[i]); |
705 |
|
|
706 |
|
theory::SubstitutionMap subst(new context::Context()); |
707 |
|
for (unsigned i = 0; i < conjuncts.size(); ++i) { |
708 |
|
TNode conjunct = conjuncts[i]; |
709 |
|
// substitute s -> t |
710 |
|
Node s, t; |
711 |
|
|
712 |
|
if (conjunct.getKind() == kind::EQUAL) { |
713 |
|
if (conjunct[0].getMetaKind() == kind::metakind::VARIABLE && |
714 |
|
conjunct[1].getKind() == kind::CONST_BITVECTOR) { |
715 |
|
s = conjunct[0]; |
716 |
|
t = conjunct[1]; |
717 |
|
} |
718 |
|
else if (conjunct[1].getMetaKind() == kind::metakind::VARIABLE && |
719 |
|
conjunct[0].getKind() == kind::CONST_BITVECTOR) { |
720 |
|
s = conjunct[1]; |
721 |
|
t = conjunct[0]; |
722 |
|
} else { |
723 |
|
continue; |
724 |
|
} |
725 |
|
|
726 |
|
Assert(!subst.hasSubstitution(s)); |
727 |
|
Assert(!t.isNull() && !s.isNull() && s != t); |
728 |
|
subst.addSubstitution(s, t); |
729 |
|
|
730 |
|
for (unsigned k = 0; k < conjuncts.size(); k++) { |
731 |
|
conjuncts[k] = subst.apply(conjuncts[k]); |
732 |
|
} |
733 |
|
} |
734 |
|
} |
735 |
|
Node new_conflict = Rewriter::rewrite(utils::mkAnd(conjuncts)); |
736 |
|
|
737 |
|
Debug("bv-abstraction") << "AbstractionModule::simplifyConflict conflict " << conflict <<"\n"; |
738 |
|
Debug("bv-abstraction") << " => " << new_conflict <<"\n"; |
739 |
|
|
740 |
|
return new_conflict; |
741 |
|
} |
742 |
|
|
743 |
|
void DebugPrintInstantiations( |
744 |
|
const std::vector<std::vector<ArgsVec> >& instantiations, |
745 |
|
const std::vector<TNode>& functions) |
746 |
|
{ |
747 |
|
// print header |
748 |
|
Debug("bv-abstraction-dbg") <<"[ "; |
749 |
|
for (unsigned i = 0; i < functions.size(); ++i) { |
750 |
|
for (unsigned j = 1; j < functions[i].getNumChildren(); ++j) { |
751 |
|
Debug("bv-abstraction-dgb") << functions[i][j] <<" "; |
752 |
|
} |
753 |
|
Debug("bv-abstraction-dgb") << " || "; |
754 |
|
} |
755 |
|
Debug("bv-abstraction-dbg") <<"]\n"; |
756 |
|
|
757 |
|
for (unsigned i = 0; i < instantiations.size(); ++i) { |
758 |
|
Debug("bv-abstraction-dbg") <<"["; |
759 |
|
const std::vector<ArgsVec>& inst = instantiations[i]; |
760 |
|
for (unsigned j = 0; j < inst.size(); ++j) { |
761 |
|
for (unsigned k = 0; k < inst[j].size(); ++k) { |
762 |
|
Debug("bv-abstraction-dbg") << inst[j][k] << " "; |
763 |
|
} |
764 |
|
Debug("bv-abstraction-dbg") << " || "; |
765 |
|
} |
766 |
|
Debug("bv-abstraction-dbg") <<"]\n"; |
767 |
|
} |
768 |
|
} |
769 |
|
|
770 |
|
void AbstractionModule::generalizeConflict(TNode conflict, std::vector<Node>& lemmas) { |
771 |
|
Debug("bv-abstraction") << "AbstractionModule::generalizeConflict " << conflict << "\n"; |
772 |
|
std::vector<TNode> functions; |
773 |
|
|
774 |
|
// collect abstract functions |
775 |
|
if (conflict.getKind() != kind::AND) { |
776 |
|
if (isAbstraction(conflict)) { |
777 |
|
Assert(conflict[0].getKind() == kind::APPLY_UF); |
778 |
|
functions.push_back(conflict[0]); |
779 |
|
} |
780 |
|
} else { |
781 |
|
for (unsigned i = 0; i < conflict.getNumChildren(); ++i) { |
782 |
|
TNode conjunct = conflict[i]; |
783 |
|
if (isAbstraction(conjunct)) { |
784 |
|
Assert(conjunct[0].getKind() == kind::APPLY_UF); |
785 |
|
functions.push_back(conjunct[0]); |
786 |
|
} |
787 |
|
} |
788 |
|
} |
789 |
|
|
790 |
|
// if (functions.size() >= 3) { |
791 |
|
// // dump conflict |
792 |
|
// NodeNodeMap seen; |
793 |
|
// Node reversed = reverseAbstraction(conflict, seen); |
794 |
|
// std::cout << "CONFLICT " << reversed << "\n"; |
795 |
|
// } |
796 |
|
|
797 |
|
|
798 |
|
if (functions.size() == 0 || functions.size() > options::bvNumFunc()) { |
799 |
|
return; |
800 |
|
} |
801 |
|
|
802 |
|
|
803 |
|
// Skolemize function arguments to avoid confusion in pattern matching |
804 |
|
SubstitutionMap skolem_subst(new context::Context()); |
805 |
|
SubstitutionMap reverse_skolem(new context::Context()); |
806 |
|
makeFreshSkolems(conflict, skolem_subst, reverse_skolem); |
807 |
|
|
808 |
|
Node skolemized_conflict = skolem_subst.apply(conflict); |
809 |
|
for (unsigned i = 0; i < functions.size(); ++i) { |
810 |
|
functions[i] = skolem_subst.apply(functions[i]); |
811 |
|
} |
812 |
|
|
813 |
|
conflict = skolem_subst.apply(conflict); |
814 |
|
|
815 |
|
LemmaInstantiatior inst(functions, d_argsTable, conflict); |
816 |
|
std::vector<Node> new_lemmas; |
817 |
|
inst.generateInstantiations(new_lemmas); |
818 |
|
for (unsigned i = 0; i < new_lemmas.size(); ++i) { |
819 |
|
TNode lemma = reverse_skolem.apply(new_lemmas[i]); |
820 |
|
if (d_addedLemmas.find(lemma) == d_addedLemmas.end()) { |
821 |
|
lemmas.push_back(lemma); |
822 |
|
Debug("bv-abstraction-gen") << "adding lemma " << lemma << "\n"; |
823 |
|
storeLemma(lemma); |
824 |
|
} |
825 |
|
} |
826 |
|
} |
827 |
|
|
828 |
|
int AbstractionModule::LemmaInstantiatior::next(int val, int index) { |
829 |
|
if (val < d_maxMatch[index] - 1) |
830 |
|
return val + 1; |
831 |
|
return -1; |
832 |
|
} |
833 |
|
|
834 |
|
/** |
835 |
|
* Assumes the stack without top is consistent, and checks that the |
836 |
|
* full stack is consistent |
837 |
|
* |
838 |
|
* @param stack |
839 |
|
* |
840 |
|
* @return |
841 |
|
*/ |
842 |
|
bool AbstractionModule::LemmaInstantiatior::isConsistent(const vector<int>& stack) { |
843 |
|
if (stack.empty()) |
844 |
|
return true; |
845 |
|
|
846 |
|
unsigned current = stack.size() - 1; |
847 |
|
TNode func = d_functions[current]; |
848 |
|
ArgsTableEntry& matches = d_argsTable.getEntry(func.getOperator()); |
849 |
|
ArgsVec& args = matches.getEntry(stack[current]); |
850 |
|
Assert(args.size() == func.getNumChildren()); |
851 |
|
for (unsigned k = 0; k < args.size(); ++k) { |
852 |
|
TNode s = func[k]; |
853 |
|
TNode t = args[k]; |
854 |
|
|
855 |
|
TNode s0 = s; |
856 |
|
while (d_subst.hasSubstitution(s0)) { |
857 |
|
s0 = d_subst.getSubstitution(s0); |
858 |
|
} |
859 |
|
|
860 |
|
TNode t0 = t; |
861 |
|
while (d_subst.hasSubstitution(t0)) { |
862 |
|
t0 = d_subst.getSubstitution(t0); |
863 |
|
} |
864 |
|
|
865 |
|
if (s0.isConst() && t0.isConst()) { |
866 |
|
if (s0 != t0) |
867 |
|
return false; // fail |
868 |
|
else |
869 |
|
continue; |
870 |
|
} |
871 |
|
|
872 |
|
if(s0.getMetaKind() == kind::metakind::VARIABLE && |
873 |
|
t0.isConst()) { |
874 |
|
d_subst.addSubstitution(s0, t0); |
875 |
|
continue; |
876 |
|
} |
877 |
|
|
878 |
|
if (s0.isConst() && |
879 |
|
t0.getMetaKind() == kind::metakind::VARIABLE) { |
880 |
|
d_subst.addSubstitution(t0, s0); |
881 |
|
continue; |
882 |
|
} |
883 |
|
|
884 |
|
Assert(s0.getMetaKind() == kind::metakind::VARIABLE |
885 |
|
&& t0.getMetaKind() == kind::metakind::VARIABLE); |
886 |
|
|
887 |
|
if (s0 != t0) { |
888 |
|
d_subst.addSubstitution(s0, t0); |
889 |
|
} |
890 |
|
} |
891 |
|
return true; |
892 |
|
} |
893 |
|
|
894 |
|
bool AbstractionModule::LemmaInstantiatior::accept(const vector<int>& stack) { |
895 |
|
return stack.size() == d_functions.size(); |
896 |
|
} |
897 |
|
|
898 |
|
void AbstractionModule::LemmaInstantiatior::mkLemma() { |
899 |
|
Node lemma = d_subst.apply(d_conflict); |
900 |
|
// Debug("bv-abstraction-gen") << "AbstractionModule::LemmaInstantiatior::mkLemma " << lemma <<"\n"; |
901 |
|
d_lemmas.push_back(lemma); |
902 |
|
} |
903 |
|
|
904 |
|
void AbstractionModule::LemmaInstantiatior::backtrack(vector<int>& stack) { |
905 |
|
if (!isConsistent(stack)) |
906 |
|
return; |
907 |
|
|
908 |
|
if (accept(stack)) { |
909 |
|
mkLemma(); |
910 |
|
return; |
911 |
|
} |
912 |
|
|
913 |
|
int x = 0; |
914 |
|
while (x != -1) { |
915 |
|
d_ctx->push(); |
916 |
|
stack.push_back(x); |
917 |
|
backtrack(stack); |
918 |
|
|
919 |
|
d_ctx->pop(); |
920 |
|
stack.pop_back(); |
921 |
|
x = next(x, stack.size()); |
922 |
|
} |
923 |
|
} |
924 |
|
|
925 |
|
|
926 |
|
void AbstractionModule::LemmaInstantiatior::generateInstantiations(std::vector<Node>& lemmas) { |
927 |
|
Debug("bv-abstraction-gen") << "AbstractionModule::LemmaInstantiatior::generateInstantiations "; |
928 |
|
|
929 |
|
std::vector<int> stack; |
930 |
|
backtrack(stack); |
931 |
|
Assert(d_ctx->getLevel() == 0); |
932 |
|
Debug("bv-abstraction-gen") << "numLemmas=" << d_lemmas.size() <<"\n"; |
933 |
|
lemmas.swap(d_lemmas); |
934 |
|
} |
935 |
|
|
936 |
|
void AbstractionModule::makeFreshSkolems(TNode node, SubstitutionMap& map, SubstitutionMap& reverse_map) { |
937 |
|
if (map.hasSubstitution(node)) { |
938 |
|
return; |
939 |
|
} |
940 |
|
if (node.getMetaKind() == kind::metakind::VARIABLE) { |
941 |
|
Node skolem = utils::mkVar(utils::getSize(node)); |
942 |
|
map.addSubstitution(node, skolem); |
943 |
|
reverse_map.addSubstitution(skolem, node); |
944 |
|
return; |
945 |
|
} |
946 |
|
if (node.isConst()) |
947 |
|
return; |
948 |
|
|
949 |
|
for (unsigned i = 0; i < node.getNumChildren(); ++i) { |
950 |
|
makeFreshSkolems(node[i], map, reverse_map); |
951 |
|
} |
952 |
|
} |
953 |
|
|
954 |
|
void AbstractionModule::makeFreshArgs(TNode func, std::vector<Node>& fresh_args) { |
955 |
|
Assert(fresh_args.size() == 0); |
956 |
|
Assert(func.getKind() == kind::APPLY_UF); |
957 |
|
TNodeNodeMap d_map; |
958 |
|
for (unsigned i = 0; i < func.getNumChildren(); ++i) { |
959 |
|
TNode arg = func[i]; |
960 |
|
if (arg.isConst()) { |
961 |
|
fresh_args.push_back(arg); |
962 |
|
continue; |
963 |
|
} |
964 |
|
Assert(arg.getMetaKind() == kind::metakind::VARIABLE); |
965 |
|
TNodeNodeMap::iterator it = d_map.find(arg); |
966 |
|
if (it != d_map.end()) { |
967 |
|
fresh_args.push_back(it->second); |
968 |
|
} else { |
969 |
|
Node skolem = utils::mkVar(utils::getSize(arg)); |
970 |
|
d_map[arg] = skolem; |
971 |
|
fresh_args.push_back(skolem); |
972 |
|
} |
973 |
|
} |
974 |
|
Assert(fresh_args.size() == func.getNumChildren()); |
975 |
|
} |
976 |
|
|
977 |
|
Node AbstractionModule::tryMatching(const std::vector<Node>& ss, const std::vector<TNode>& tt, TNode conflict) { |
978 |
|
Assert(ss.size() == tt.size()); |
979 |
|
|
980 |
|
Debug("bv-abstraction-dbg") << "AbstractionModule::tryMatching conflict = " << conflict << "\n"; |
981 |
|
if (Debug.isOn("bv-abstraction-dbg")) { |
982 |
|
Debug("bv-abstraction-dbg") << " Match: "; |
983 |
|
for (unsigned i = 0; i < ss.size(); ++i) { |
984 |
|
Debug("bv-abstraction-dbg") << ss[i] <<" "; |
985 |
|
|
986 |
|
} |
987 |
|
Debug("bv-abstraction-dbg") << "\n To: "; |
988 |
|
for (unsigned i = 0; i < tt.size(); ++i) { |
989 |
|
Debug("bv-abstraction-dbg") << tt[i] <<" "; |
990 |
|
} |
991 |
|
Debug("bv-abstraction-dbg") <<"\n"; |
992 |
|
} |
993 |
|
|
994 |
|
|
995 |
|
SubstitutionMap subst(new context::Context()); |
996 |
|
|
997 |
|
for (unsigned i = 0; i < ss.size(); ++i) { |
998 |
|
TNode s = ss[i]; |
999 |
|
TNode t = tt[i]; |
1000 |
|
|
1001 |
|
TNode s0 = subst.hasSubstitution(s) ? subst.getSubstitution(s) : s; |
1002 |
|
TNode t0 = subst.hasSubstitution(t) ? subst.getSubstitution(t) : t; |
1003 |
|
|
1004 |
|
if (s0.isConst() && t0.isConst()) { |
1005 |
|
if (s0 != t0) |
1006 |
|
return Node(); // fail |
1007 |
|
else |
1008 |
|
continue; |
1009 |
|
} |
1010 |
|
|
1011 |
|
if(s0.getMetaKind() == kind::metakind::VARIABLE && |
1012 |
|
t0.isConst()) { |
1013 |
|
subst.addSubstitution(s0, t0); |
1014 |
|
continue; |
1015 |
|
} |
1016 |
|
|
1017 |
|
if (s0.isConst() && |
1018 |
|
t0.getMetaKind() == kind::metakind::VARIABLE) { |
1019 |
|
subst.addSubstitution(t0, s0); |
1020 |
|
continue; |
1021 |
|
} |
1022 |
|
|
1023 |
|
Assert(s0.getMetaKind() == kind::metakind::VARIABLE |
1024 |
|
&& t0.getMetaKind() == kind::metakind::VARIABLE); |
1025 |
|
|
1026 |
|
Assert(s0 != t0); |
1027 |
|
subst.addSubstitution(s0, t0); |
1028 |
|
} |
1029 |
|
|
1030 |
|
Node res = subst.apply(conflict); |
1031 |
|
Debug("bv-abstraction-dbg") << " Lemma: " << res <<"\n"; |
1032 |
|
return res; |
1033 |
|
} |
1034 |
|
|
1035 |
|
void AbstractionModule::storeLemma(TNode lemma) { |
1036 |
|
d_addedLemmas.insert(lemma); |
1037 |
|
if (lemma.getKind() == kind::AND) { |
1038 |
|
for (unsigned i = 0; i < lemma.getNumChildren(); i++) { |
1039 |
|
TNode atom = lemma[i]; |
1040 |
|
atom = atom.getKind() == kind::NOT ? atom[0] : atom; |
1041 |
|
Assert(atom.getKind() != kind::NOT); |
1042 |
|
Assert(utils::isBVPredicate(atom)); |
1043 |
|
d_lemmaAtoms.insert(atom); |
1044 |
|
} |
1045 |
|
} else { |
1046 |
|
lemma = lemma.getKind() == kind::NOT? lemma[0] : lemma; |
1047 |
|
Assert(utils::isBVPredicate(lemma)); |
1048 |
|
d_lemmaAtoms.insert(lemma); |
1049 |
|
} |
1050 |
|
} |
1051 |
|
|
1052 |
|
|
1053 |
16 |
bool AbstractionModule::isLemmaAtom(TNode node) const { |
1054 |
16 |
Assert(node.getType().isBoolean()); |
1055 |
16 |
node = node.getKind() == kind::NOT? node[0] : node; |
1056 |
|
|
1057 |
32 |
return d_inputAtoms.find(node) == d_inputAtoms.end() && |
1058 |
32 |
d_lemmaAtoms.find(node) != d_lemmaAtoms.end(); |
1059 |
|
} |
1060 |
|
|
1061 |
12 |
void AbstractionModule::addInputAtom(TNode atom) { |
1062 |
12 |
if (options::bitblastMode() == options::BitblastMode::LAZY) |
1063 |
|
{ |
1064 |
12 |
d_inputAtoms.insert(atom); |
1065 |
|
} |
1066 |
12 |
} |
1067 |
|
|
1068 |
|
void AbstractionModule::ArgsTableEntry::addArguments(const ArgsVec& args) { |
1069 |
|
Assert(args.size() == d_arity); |
1070 |
|
d_data.push_back(args); |
1071 |
|
} |
1072 |
|
|
1073 |
|
void AbstractionModule::ArgsTable::addEntry(TNode signature, const ArgsVec& args) { |
1074 |
|
if (d_data.find(signature) == d_data.end()) { |
1075 |
|
d_data[signature] = ArgsTableEntry(args.size()); |
1076 |
|
} |
1077 |
|
ArgsTableEntry& entry = d_data[signature]; |
1078 |
|
entry.addArguments(args); |
1079 |
|
} |
1080 |
|
|
1081 |
|
|
1082 |
|
bool AbstractionModule::ArgsTable::hasEntry(TNode signature) const { |
1083 |
|
return d_data.find(signature) != d_data.end(); |
1084 |
|
} |
1085 |
|
|
1086 |
|
AbstractionModule::ArgsTableEntry& AbstractionModule::ArgsTable::getEntry(TNode signature) { |
1087 |
|
Assert(hasEntry(signature)); |
1088 |
|
return d_data.find(signature)->second; |
1089 |
|
} |
1090 |
|
|
1091 |
9444 |
AbstractionModule::Statistics::Statistics( |
1092 |
9444 |
const std::string& name, const NodeNodeMap& functionsAbstracted) |
1093 |
|
: d_numFunctionsAbstracted( |
1094 |
9444 |
smtStatisticsRegistry().registerSize<NodeNodeMap>( |
1095 |
18888 |
name + "NumFunctionsAbstracted", functionsAbstracted)), |
1096 |
|
d_numArgsSkolemized( |
1097 |
18888 |
smtStatisticsRegistry().registerInt(name + "NumArgsSkolemized")), |
1098 |
|
d_abstractionTime( |
1099 |
28332 |
smtStatisticsRegistry().registerTimer(name + "AbstractionTime")) |
1100 |
|
{ |
1101 |
37639 |
} |