Fix model construction for BV with cbqi. Minor change to defaults.
[cvc5.git] / src / theory / bv / bv_subtheory_core.cpp
1 /********************* */
2 /*! \file bv_subtheory_core.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Andrew Reynolds, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2016 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.\endverbatim
11 **
12 ** \brief Algebraic solver.
13 **
14 ** Algebraic solver.
15 **/
16
17 #include "theory/bv/bv_subtheory_core.h"
18
19 #include "options/bv_options.h"
20 #include "options/smt_options.h"
21 #include "smt/smt_statistics_registry.h"
22 #include "theory/bv/slicer.h"
23 #include "theory/bv/theory_bv.h"
24 #include "theory/bv/theory_bv_utils.h"
25 #include "theory/theory_model.h"
26
27 using namespace std;
28 using namespace CVC4;
29 using namespace CVC4::context;
30 using namespace CVC4::theory;
31 using namespace CVC4::theory::bv;
32 using namespace CVC4::theory::bv::utils;
33
34 CoreSolver::CoreSolver(context::Context* c, TheoryBV* bv)
35 : SubtheorySolver(c, bv),
36 d_notify(*this),
37 d_equalityEngine(d_notify, c, "theory::bv::TheoryBV", true),
38 d_slicer(new Slicer()),
39 d_isComplete(c, true),
40 d_lemmaThreshold(16),
41 d_useSlicer(false),
42 d_preregisterCalled(false),
43 d_checkCalled(false),
44 d_reasons(c)
45 {
46 // The kinds we are treating as function application in congruence
47 d_equalityEngine.addFunctionKind(kind::BITVECTOR_CONCAT, true);
48 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_AND);
49 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_OR);
50 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XOR);
51 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOT);
52 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NAND);
53 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NOR);
54 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_XNOR);
55 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_COMP);
56 d_equalityEngine.addFunctionKind(kind::BITVECTOR_MULT, true);
57 d_equalityEngine.addFunctionKind(kind::BITVECTOR_PLUS, true);
58 d_equalityEngine.addFunctionKind(kind::BITVECTOR_EXTRACT, true);
59 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SUB);
60 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_NEG);
61 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UDIV);
62 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UREM);
63 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SDIV);
64 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SREM);
65 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SMOD);
66 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SHL);
67 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_LSHR);
68 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ASHR);
69 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULT);
70 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_ULE);
71 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGT);
72 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_UGE);
73 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLT);
74 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SLE);
75 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGT);
76 // d_equalityEngine.addFunctionKind(kind::BITVECTOR_SGE);
77 d_equalityEngine.addFunctionKind(kind::BITVECTOR_TO_NAT);
78 d_equalityEngine.addFunctionKind(kind::INT_TO_BITVECTOR);
79 }
80
81 CoreSolver::~CoreSolver() {
82 delete d_slicer;
83 }
84 void CoreSolver::setMasterEqualityEngine(eq::EqualityEngine* eq) {
85 d_equalityEngine.setMasterEqualityEngine(eq);
86 }
87
88 void CoreSolver::enableSlicer() {
89 AlwaysAssert (!d_preregisterCalled);
90 d_useSlicer = true;
91 d_statistics.d_slicerEnabled.setData(true);
92 }
93
94 void CoreSolver::preRegister(TNode node) {
95 d_preregisterCalled = true;
96 if (node.getKind() == kind::EQUAL) {
97 d_equalityEngine.addTriggerEquality(node);
98 if (d_useSlicer) {
99 d_slicer->processEquality(node);
100 AlwaysAssert(!d_checkCalled);
101 }
102 } else {
103 d_equalityEngine.addTerm(node);
104 }
105 }
106
107
108 void CoreSolver::explain(TNode literal, std::vector<TNode>& assumptions) {
109 bool polarity = literal.getKind() != kind::NOT;
110 TNode atom = polarity ? literal : literal[0];
111 if (atom.getKind() == kind::EQUAL) {
112 d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions);
113 } else {
114 d_equalityEngine.explainPredicate(atom, polarity, assumptions);
115 }
116 }
117
118 Node CoreSolver::getBaseDecomposition(TNode a) {
119 std::vector<Node> a_decomp;
120 d_slicer->getBaseDecomposition(a, a_decomp);
121 Node new_a = utils::mkConcat(a_decomp);
122 Debug("bv-slicer") << "CoreSolver::getBaseDecomposition " << a <<" => " << new_a << "\n";
123 return new_a;
124 }
125
126 bool CoreSolver::decomposeFact(TNode fact) {
127 Debug("bv-slicer") << "CoreSolver::decomposeFact fact=" << fact << endl;
128 // FIXME: are this the right things to assert?
129 // assert decompositions since the equality engine does not know the semantics of
130 // concat:
131 // a == a_1 concat ... concat a_k
132 // b == b_1 concat ... concat b_k
133 TNode eq = fact.getKind() == kind::NOT? fact[0] : fact;
134
135 TNode a = eq[0];
136 TNode b = eq[1];
137 Node new_a = getBaseDecomposition(a);
138 Node new_b = getBaseDecomposition(b);
139
140 Assert (utils::getSize(new_a) == utils::getSize(new_b) &&
141 utils::getSize(new_a) == utils::getSize(a));
142
143 NodeManager* nm = NodeManager::currentNM();
144 Node a_eq_new_a = nm->mkNode(kind::EQUAL, a, new_a);
145 Node b_eq_new_b = nm->mkNode(kind::EQUAL, b, new_b);
146
147 bool ok = true;
148 ok = assertFactToEqualityEngine(a_eq_new_a, utils::mkTrue());
149 if (!ok) return false;
150 ok = assertFactToEqualityEngine(b_eq_new_b, utils::mkTrue());
151 if (!ok) return false;
152 ok = assertFactToEqualityEngine(fact, fact);
153 if (!ok) return false;
154
155 if (fact.getKind() == kind::EQUAL) {
156 // assert the individual equalities as well
157 // a_i == b_i
158 if (new_a.getKind() == kind::BITVECTOR_CONCAT &&
159 new_b.getKind() == kind::BITVECTOR_CONCAT) {
160
161 Assert (new_a.getNumChildren() == new_b.getNumChildren());
162 for (unsigned i = 0; i < new_a.getNumChildren(); ++i) {
163 Node eq_i = nm->mkNode(kind::EQUAL, new_a[i], new_b[i]);
164 ok = assertFactToEqualityEngine(eq_i, fact);
165 if (!ok) return false;
166 }
167 }
168 }
169 return true;
170 }
171
172 bool CoreSolver::check(Theory::Effort e) {
173 Trace("bitvector::core") << "CoreSolver::check \n";
174
175 d_bv->spendResource(options::theoryCheckStep());
176
177 d_checkCalled = true;
178 Assert (!d_bv->inConflict());
179 ++(d_statistics.d_numCallstoCheck);
180 bool ok = true;
181 std::vector<Node> core_eqs;
182 TNodeBoolMap seen;
183 // slicer does not deal with cardinality constraints yet
184 if (d_useSlicer) {
185 d_isComplete = false;
186 }
187 while (! done()) {
188 TNode fact = get();
189 if (d_isComplete && !isCompleteForTerm(fact, seen)) {
190 d_isComplete = false;
191 }
192
193 // only reason about equalities
194 if (fact.getKind() == kind::EQUAL || (fact.getKind() == kind::NOT && fact[0].getKind() == kind::EQUAL)) {
195 if (d_useSlicer) {
196 ok = decomposeFact(fact);
197 } else {
198 ok = assertFactToEqualityEngine(fact, fact);
199 }
200 } else {
201 ok = assertFactToEqualityEngine(fact, fact);
202 }
203 if (!ok)
204 return false;
205 }
206
207 if (Theory::fullEffort(e) && isComplete()) {
208 buildModel();
209 }
210
211 return true;
212 }
213
214 void CoreSolver::buildModel() {
215 Debug("bv-core") << "CoreSolver::buildModel() \n";
216 d_modelValues.clear();
217 TNodeSet constants;
218 TNodeSet constants_in_eq_engine;
219 // collect constants in equality engine
220 eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(&d_equalityEngine);
221 while (!eqcs_i.isFinished()) {
222 TNode repr = *eqcs_i;
223 if (repr.getKind() == kind::CONST_BITVECTOR) {
224 // must check if it's just the constant
225 eq::EqClassIterator it(repr, &d_equalityEngine);
226 if (!(++it).isFinished() || true) {
227 constants.insert(repr);
228 constants_in_eq_engine.insert(repr);
229 }
230 }
231 ++eqcs_i;
232 }
233
234 // build repr to value map
235
236 eqcs_i = eq::EqClassesIterator(&d_equalityEngine);
237 while (!eqcs_i.isFinished()) {
238 TNode repr = *eqcs_i;
239 ++eqcs_i;
240
241 if (!repr.isVar() &&
242 repr.getKind() != kind::CONST_BITVECTOR &&
243 !d_bv->isSharedTerm(repr)) {
244 continue;
245 }
246
247 TypeNode type = repr.getType();
248 if (type.isBitVector() && repr.getKind()!= kind::CONST_BITVECTOR) {
249 Debug("bv-core-model") << " processing " << repr <<"\n";
250 // we need to assign a value for it
251 TypeEnumerator te(type);
252 Node val;
253 do {
254 val = *te;
255 ++te;
256 // Debug("bv-core-model") << " trying value " << val << "\n";
257 // Debug("bv-core-model") << " is in set? " << constants.count(val) << "\n";
258 // Debug("bv-core-model") << " enumerator done? " << te.isFinished() << "\n";
259 } while (constants.count(val) != 0 && !(te.isFinished()));
260
261 if (te.isFinished() && constants.count(val) != 0) {
262 // if we cannot enumerate anymore values we just return the lemma stating that
263 // at least two of the representatives are equal.
264 std::vector<TNode> representatives;
265 representatives.push_back(repr);
266
267 for (TNodeSet::const_iterator it = constants_in_eq_engine.begin();
268 it != constants_in_eq_engine.end(); ++it) {
269 TNode constant = *it;
270 if (utils::getSize(constant) == utils::getSize(repr)) {
271 representatives.push_back(constant);
272 }
273 }
274 for (ModelValue::const_iterator it = d_modelValues.begin(); it != d_modelValues.end(); ++it) {
275 representatives.push_back(it->first);
276 }
277 std::vector<Node> equalities;
278 for (unsigned i = 0; i < representatives.size(); ++i) {
279 for (unsigned j = i + 1; j < representatives.size(); ++j) {
280 TNode a = representatives[i];
281 TNode b = representatives[j];
282 if (a.getKind() == kind::CONST_BITVECTOR &&
283 b.getKind() == kind::CONST_BITVECTOR) {
284 Assert (a != b);
285 continue;
286 }
287 if (utils::getSize(a) == utils::getSize(b)) {
288 equalities.push_back(utils::mkNode(kind::EQUAL, a, b));
289 }
290 }
291 }
292 // better off letting the SAT solver split on values
293 if (equalities.size() > d_lemmaThreshold) {
294 d_isComplete = false;
295 return;
296 }
297
298 Node lemma = utils::mkOr(equalities);
299 d_bv->lemma(lemma);
300 Debug("bv-core") << " lemma: " << lemma << "\n";
301 return;
302 }
303
304 Debug("bv-core-model") << " " << repr << " => " << val <<"\n" ;
305 constants.insert(val);
306 d_modelValues[repr] = val;
307 }
308 }
309 }
310
311 bool CoreSolver::assertFactToEqualityEngine(TNode fact, TNode reason) {
312 // Notify the equality engine
313 if (!d_bv->inConflict() && (!d_bv->wasPropagatedBySubtheory(fact) || d_bv->getPropagatingSubtheory(fact) != SUB_CORE)) {
314 Debug("bv-slicer-eq") << "CoreSolver::assertFactToEqualityEngine fact=" << fact << endl;
315 // Debug("bv-slicer-eq") << " reason=" << reason << endl;
316 bool negated = fact.getKind() == kind::NOT;
317 TNode predicate = negated ? fact[0] : fact;
318 if (predicate.getKind() == kind::EQUAL) {
319 if (negated) {
320 // dis-equality
321 d_equalityEngine.assertEquality(predicate, false, reason);
322 } else {
323 // equality
324 d_equalityEngine.assertEquality(predicate, true, reason);
325 }
326 } else {
327 // Adding predicate if the congruence over it is turned on
328 if (d_equalityEngine.isFunctionKind(predicate.getKind())) {
329 d_equalityEngine.assertPredicate(predicate, !negated, reason);
330 }
331 }
332 }
333
334 // checking for a conflict
335 if (d_bv->inConflict()) {
336 return false;
337 }
338 return true;
339 }
340
341 bool CoreSolver::NotifyClass::eqNotifyTriggerEquality(TNode equality, bool value) {
342 Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerEquality(" << equality << ", " << (value ? "true" : "false" )<< ")" << std::endl;
343 if (value) {
344 return d_solver.storePropagation(equality);
345 } else {
346 return d_solver.storePropagation(equality.notNode());
347 }
348 }
349
350 bool CoreSolver::NotifyClass::eqNotifyTriggerPredicate(TNode predicate, bool value) {
351 Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", " << (value ? "true" : "false" ) << ")" << std::endl;
352 if (value) {
353 return d_solver.storePropagation(predicate);
354 } else {
355 return d_solver.storePropagation(predicate.notNode());
356 }
357 }
358
359 bool CoreSolver::NotifyClass::eqNotifyTriggerTermEquality(TheoryId tag, TNode t1, TNode t2, bool value) {
360 Debug("bitvector::core") << "NotifyClass::eqNotifyTriggerTermMerge(" << t1 << ", " << t2 << ")" << std::endl;
361 if (value) {
362 return d_solver.storePropagation(t1.eqNode(t2));
363 } else {
364 return d_solver.storePropagation(t1.eqNode(t2).notNode());
365 }
366 }
367
368 void CoreSolver::NotifyClass::eqNotifyConstantTermMerge(TNode t1, TNode t2) {
369 d_solver.conflict(t1, t2);
370 }
371
372 void CoreSolver::NotifyClass::eqNotifyNewClass(TNode t) {
373 d_solver.eqNotifyNewClass( t );
374 }
375
376 bool CoreSolver::storePropagation(TNode literal) {
377 return d_bv->storePropagation(literal, SUB_CORE);
378 }
379
380 void CoreSolver::conflict(TNode a, TNode b) {
381 std::vector<TNode> assumptions;
382 d_equalityEngine.explainEquality(a, b, true, assumptions);
383 Node conflict = flattenAnd(assumptions);
384 d_bv->setConflict(conflict);
385 }
386
387 void CoreSolver::eqNotifyNewClass(TNode t) {
388 Assert( d_bv->getExtTheory()!=NULL );
389 d_bv->getExtTheory()->registerTerm( t );
390 }
391
392 bool CoreSolver::isCompleteForTerm(TNode term, TNodeBoolMap& seen) {
393 if (d_useSlicer)
394 return utils::isCoreTerm(term, seen);
395
396 return utils::isEqualityTerm(term, seen);
397 }
398
399 void CoreSolver::collectModelInfo(TheoryModel* m, bool fullModel) {
400 if (d_useSlicer) {
401 Unreachable();
402 }
403 if (Debug.isOn("bitvector-model")) {
404 context::CDQueue<Node>::const_iterator it = d_assertionQueue.begin();
405 for (; it!= d_assertionQueue.end(); ++it) {
406 Debug("bitvector-model") << "CoreSolver::collectModelInfo (assert "
407 << *it << ")\n";
408 }
409 }
410 set<Node> termSet;
411 d_bv->computeRelevantTerms(termSet);
412 m->assertEqualityEngine(&d_equalityEngine, &termSet);
413 if (isComplete()) {
414 Debug("bitvector-model") << "CoreSolver::collectModelInfo complete.";
415 for (ModelValue::const_iterator it = d_modelValues.begin(); it != d_modelValues.end(); ++it) {
416 Node a = it->first;
417 Node b = it->second;
418 Debug("bitvector-model") << "CoreSolver::collectModelInfo modelValues "
419 << a << " => " << b <<")\n";
420 m->assertEquality(a, b, true);
421 }
422 }
423 }
424
425 Node CoreSolver::getModelValue(TNode var) {
426 // we don't need to evaluate bv expressions and only look at variable values
427 // because this only gets called when the core theory is complete (i.e. no other bv
428 // function symbols are currently asserted)
429 Assert (d_slicer->isCoreTerm(var));
430
431 Debug("bitvector-model") << "CoreSolver::getModelValue (" << var <<")";
432 Assert (isComplete());
433 TNode repr = d_equalityEngine.getRepresentative(var);
434 Node result = Node();
435 if (repr.getKind() == kind::CONST_BITVECTOR) {
436 result = repr;
437 } else if (d_modelValues.find(repr) == d_modelValues.end()) {
438 // it may be a shared term that never gets asserted
439 // result is just Null
440 Assert(d_bv->isSharedTerm(var));
441 } else {
442 result = d_modelValues[repr];
443 }
444 Debug("bitvector-model") << " => " << result <<"\n";
445 return result;
446 }
447
448 CoreSolver::Statistics::Statistics()
449 : d_numCallstoCheck("theory::bv::CoreSolver::NumCallsToCheck", 0)
450 , d_slicerEnabled("theory::bv::CoreSolver::SlicerEnabled", false)
451 {
452 smtStatisticsRegistry()->registerStat(&d_numCallstoCheck);
453 smtStatisticsRegistry()->registerStat(&d_slicerEnabled);
454 }
455 CoreSolver::Statistics::~Statistics() {
456 smtStatisticsRegistry()->unregisterStat(&d_numCallstoCheck);
457 smtStatisticsRegistry()->unregisterStat(&d_slicerEnabled);
458 }