SatLiteral BVMinisatSatSolver::toSatLiteral(BVMinisat::Lit lit) { if (lit == BVMinisat::lit_Undef) { return undefSatLiteral; } return SatLiteral(SatVariable(BVMinisat::var(lit)), BVMinisat::sign(lit)); }
SatValue DecisionEngine::getPolarity(SatVariable var) { Debug("decision") << "getPolarity(" << var <<")" << std::endl; if(d_relevancyStrategy != NULL) { Assert(isRelevant(var)); return d_relevancyStrategy->getPolarity( d_cnfStream->getNode(SatLiteral(var)) ); } else { return SAT_VALUE_UNKNOWN; } }
bool DecisionEngine::isRelevant(SatVariable var) { Debug("decision") << "isRelevant(" << var <<")" << std::endl; if(d_relevancyStrategy != NULL) { //Assert(d_cnfStream->hasNode(var)); return d_relevancyStrategy->isRelevant( d_cnfStream->getNode(SatLiteral(var)) ); } else { return true; } }
bool JustificationHeuristic::findSplitterRec(TNode node, SatValue desiredVal, SatLiteral* litDecision) { /** * Main idea * * Given a boolean formula "node", the goal is to try to make it * evaluate to "desiredVal" (true/false). for instance if "node" is a AND * formula we want to make it evaluate to true, we'd like one of the * children to be true. this is done recursively. */ Trace("jh-findSplitterRec") << "findSplitterRec(" << node << ", " << desiredVal << ", .. )" << std::endl; /* Handle NOT as a special case */ while (node.getKind() == kind::NOT) { desiredVal = invertValue(desiredVal); node = node[0]; } if(Debug.isOn("decision")) { if(checkJustified(node)) Debug("decision") << " justified, returning" << std::endl; } /* Base case */ if (checkJustified(node)) { return false; } #if defined CVC4_ASSERTIONS || defined CVC4_DEBUG // We don't always have a sat literal, so remember that. Will need // it for some assertions we make. bool litPresent = d_decisionEngine->hasSatLiteral(node); if(Debug.isOn("decision")) { if(!litPresent) { Debug("decision") << "no sat literal for this node" << std::endl; } } //Assert(litPresent); -- fails #endif // Get value of sat literal for the node, if there is one SatValue litVal = tryGetSatValue(node); /* You'd better know what you want */ Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value"); /* Good luck, hope you can get what you want */ // if(not (litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN)) { // Warning() << "WARNING: IMPORTANT: Please look into this. Sat solver is asking for a decision" << std::endl // << "when the assertion we are trying to justify is already unsat. OR there is a bug" << std::endl; // GiveUpException(); // } Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN, "invariant violated"); /* What type of node is this */ Kind k = node.getKind(); theory::TheoryId tId = theory::kindToTheoryId(k); /* Some debugging stuff */ Debug("jh-findSplitterRec") << "kind = " << k << std::endl; Debug("jh-findSplitterRec") << "theoryId = " << tId << std::endl; Debug("jh-findSplitterRec") << "node = " << node << std::endl; Debug("jh-findSplitterRec") << "litVal = " << litVal << std::endl; /** * If not in theory of booleans, and not a "boolean" EQUAL (IFF), * then check if this is something to split-on. */ if(tId != theory::THEORY_BOOL // && !(k == kind::EQUAL && node[0].getType().isBoolean()) ) { // if node has embedded ites -- which currently happens iff it got // replaced during ite removal -- then try to resolve that first const IteList& l = getITEs(node); Trace("jh-ite") << " ite size = " << l.size() << std::endl; /*d_visited.insert(node);*/ for(IteList::const_iterator i = l.begin(); i != l.end(); ++i) { if(d_visited.find(i->first) == d_visited.end()) { d_visited.insert(i->first); Debug("jh-ite") << "jh-ite: adding visited " << i->first << std::endl; if(findSplitterRec(i->second, SAT_VALUE_TRUE, litDecision)) return true; Debug("jh-ite") << "jh-ite: removing visited " << i->first << std::endl; d_visited.erase(i->first); } else { Debug("jh-ite") << "jh-ite: already visited " << i->first << std::endl; } } if(litVal != SAT_VALUE_UNKNOWN) { setJustified(node); return false; } else { Assert(d_decisionEngine->hasSatLiteral(node)); /* if(not d_decisionEngine->hasSatLiteral(node)) throw GiveUpException(); */ Assert(d_decisionEngine->hasSatLiteral(node)); SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable(); *litDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE ); Trace("decision") << "decision " << *litDecision << std::endl; Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl; return true; } } SatValue valHard = SAT_VALUE_FALSE; switch (k) { case kind::CONST_BOOLEAN: Assert(node.getConst<bool>() == false || desiredVal == SAT_VALUE_TRUE); Assert(node.getConst<bool>() == true || desiredVal == SAT_VALUE_FALSE); setJustified(node); return false; case kind::AND: valHard = SAT_VALUE_TRUE; case kind::OR: if (desiredVal == valHard) { int n = node.getNumChildren(); for(int i = 0; i < n; ++i) { if (findSplitterRec(node[i], valHard, litDecision)) { return true; } } Assert(litPresent == false || litVal == valHard, "Output should be justified"); setJustified(node); return false; } else { SatValue valEasy = invertValue(valHard); int n = node.getNumChildren(); for(int i = 0; i < n; ++i) { Debug("jh-findSplitterRec") << " node[i] = " << node[i] << " " << tryGetSatValue(node[i]) << std::endl; if ( tryGetSatValue(node[i]) != valHard) { Debug("jh-findSplitterRec") << "hi"<< std::endl; if (findSplitterRec(node[i], valEasy, litDecision)) { return true; } Assert(litPresent == false || litVal == valEasy, "Output should be justified"); setJustified(node); return false; } } if(Debug.isOn("jh-findSplitterRec")) { Debug("jh-findSplitterRec") << " * ** " << std::endl; Debug("jh-findSplitterRec") << node.getKind() << " " << node << std::endl; for(unsigned i = 0; i < node.getNumChildren(); ++i) Debug("jh-findSplitterRec") << "child: " << tryGetSatValue(node[i]) << std::endl; Debug("jh-findSplitterRec") << "node: " << tryGetSatValue(node) << std::endl; } Assert(false, "No controlling input found (2)"); } break; case kind::IMPLIES: //throw GiveUpException(); Assert(node.getNumChildren() == 2, "Expected 2 fanins"); if (desiredVal == SAT_VALUE_FALSE) { if (findSplitterRec(node[0], SAT_VALUE_TRUE, litDecision)) { return true; } if (findSplitterRec(node[1], SAT_VALUE_FALSE, litDecision)) { return true; } Assert(litPresent == false || litVal == SAT_VALUE_FALSE, "Output should be justified"); setJustified(node); return false; } else { if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) { if (findSplitterRec(node[0], SAT_VALUE_FALSE, litDecision)) { return true; } Assert(litPresent == false || litVal == SAT_VALUE_TRUE, "Output should be justified"); setJustified(node); return false; } if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) { if (findSplitterRec(node[1], SAT_VALUE_TRUE, litDecision)) { return true; } Assert(litPresent == false || litVal == SAT_VALUE_TRUE, "Output should be justified"); setJustified(node); return false; } Assert(false, "No controlling input found (3)"); } break; case kind::IFF: //throw GiveUpException(); { SatValue val = tryGetSatValue(node[0]); if (val != SAT_VALUE_UNKNOWN) { if (findSplitterRec(node[0], val, litDecision)) { return true; } if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val); if (findSplitterRec(node[1], val, litDecision)) { return true; } Assert(litPresent == false || litVal == desiredVal, "Output should be justified"); setJustified(node); return false; } else { val = tryGetSatValue(node[1]); if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE; if (desiredVal == SAT_VALUE_FALSE) val = invertValue(val); if (findSplitterRec(node[0], val, litDecision)) { return true; } Assert(false, "Unable to find controlling input (4)"); } break; } case kind::XOR: //throw GiveUpException(); { SatValue val = tryGetSatValue(node[0]); if (val != SAT_VALUE_UNKNOWN) { if (findSplitterRec(node[0], val, litDecision)) { return true; } if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val); if (findSplitterRec(node[1], val, litDecision)) { return true; } Assert(litPresent == false || litVal == desiredVal, "Output should be justified"); setJustified(node); return false; } else { SatValue val = tryGetSatValue(node[1]); if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE; if (desiredVal == SAT_VALUE_TRUE) val = invertValue(val); if (findSplitterRec(node[0], val, litDecision)) { return true; } Assert(false, "Unable to find controlling input (5)"); } break; } case kind::ITE: { //[0]: if, [1]: then, [2]: else SatValue ifVal = tryGetSatValue(node[0]); if (ifVal == SAT_VALUE_UNKNOWN) { // are we better off trying false? if not, try true SatValue ifDesiredVal = (tryGetSatValue(node[2]) == desiredVal || tryGetSatValue(node[1]) == invertValue(desiredVal)) ? SAT_VALUE_FALSE : SAT_VALUE_TRUE; if(findSplitterRec(node[0], ifDesiredVal, litDecision)) { return true; } Assert(false, "No controlling input found (6)"); } else { // Try to justify 'if' if (findSplitterRec(node[0], ifVal, litDecision)) { return true; } // If that was successful, we need to go into only one of 'then' // or 'else' int ch = (ifVal == SAT_VALUE_TRUE) ? 1 : 2; int chVal = tryGetSatValue(node[ch]); if( (chVal == SAT_VALUE_UNKNOWN || chVal == desiredVal) && findSplitterRec(node[ch], desiredVal, litDecision) ) { return true; } } Assert(litPresent == false || litVal == desiredVal, "Output should be justified"); setJustified(node); return false; } default: Assert(false, "Unexpected Boolean operator"); break; }//end of switch(k) Unreachable(); }/* findRecSplit method */
void TheoryProxy::variableNotify(SatVariable var) { d_theoryEngine->preRegister(getNode(SatLiteral(var))); }
bool Relevancy::findSplitterRec(TNode node, SatValue desiredVal) { Trace("decision") << "findSplitterRec([" << node.getId() << "]" << node << ", " << desiredVal << ", .. )" << std::endl; ++d_expense; /* Handle NOT as a special case */ while (node.getKind() == kind::NOT) { desiredVal = invertValue(desiredVal); node = node[0]; } /* Avoid infinite loops */ if(d_visited.find(node) != d_visited.end()) { Debug("decision") << " node repeated. kind was " << node.getKind() << std::endl; Assert(false); Assert(node.getKind() == kind::ITE); return false; } /* Base case */ if(checkJustified(node)) { return false; } /** * If we have already explored the subtree for some desiredVal, we * skip this and continue exploring the rest */ if(d_polarityCache.find(node) == d_polarityCache.end()) { d_polarityCache[node] = desiredVal; } else { Assert(d_multipleBacktrace || options::decisionComputeRelevancy()); return true; } d_visited.insert(node); #if defined CVC4_ASSERTIONS || defined CVC4_TRACING // We don't always have a sat literal, so remember that. Will need // it for some assertions we make. bool litPresent = d_decisionEngine->hasSatLiteral(node); if(Trace.isOn("decision")) { if(!litPresent) { Trace("decision") << "no sat literal for this node" << std::endl; } } //Assert(litPresent); -- fails #endif // Get value of sat literal for the node, if there is one SatValue litVal = tryGetSatValue(node); /* You'd better know what you want */ Assert(desiredVal != SAT_VALUE_UNKNOWN, "expected known value"); /* Good luck, hope you can get what you want */ Assert(litVal == desiredVal || litVal == SAT_VALUE_UNKNOWN, "invariant violated"); /* What type of node is this */ Kind k = node.getKind(); theory::TheoryId tId = theory::kindToTheoryId(k); /* Some debugging stuff */ Trace("jh-findSplitterRec") << "kind = " << k << std::endl; Trace("jh-findSplitterRec") << "theoryId = " << tId << std::endl; Trace("jh-findSplitterRec") << "node = " << node << std::endl; Trace("jh-findSplitterRec") << "litVal = " << litVal << std::endl; /** * If not in theory of booleans, and not a "boolean" EQUAL (IFF), * then check if this is something to split-on. */ if(tId != theory::THEORY_BOOL // && !(k == kind::EQUAL && node[0].getType().isBoolean()) ) { // if node has embedded ites -- which currently happens iff it got // replaced during ite removal -- then try to resolve that first const IteList& l = getITEs(node); Debug("jh-ite") << " ite size = " << l.size() << std::endl; for(unsigned i = 0; i < l.size(); ++i) { Assert(l[i].getKind() == kind::ITE, "Expected ITE"); Debug("jh-ite") << " i = " << i << " l[i] = " << l[i] << std::endl; if(d_visited.find(node) != d_visited.end() ) continue; if(findSplitterRec(l[i], SAT_VALUE_TRUE)) { d_visited.erase(node); return true; } } Debug("jh-ite") << " ite done " << l.size() << std::endl; if(litVal != SAT_VALUE_UNKNOWN) { d_visited.erase(node); setJustified(node); return false; } else { /* if(not d_decisionEngine->hasSatLiteral(node)) throw GiveUpException(); */ Assert(d_decisionEngine->hasSatLiteral(node)); SatVariable v = d_decisionEngine->getSatLiteral(node).getSatVariable(); *d_curDecision = SatLiteral(v, desiredVal != SAT_VALUE_TRUE ); Trace("decision") << "decision " << *d_curDecision << std::endl; Trace("decision") << "Found something to split. Glad to be able to serve you." << std::endl; d_visited.erase(node); return true; } } bool ret = false; SatValue flipCaseVal = SAT_VALUE_FALSE; switch (k) { case kind::CONST_BOOLEAN: Assert(node.getConst<bool>() == false || desiredVal == SAT_VALUE_TRUE); Assert(node.getConst<bool>() == true || desiredVal == SAT_VALUE_FALSE); break; case kind::AND: if (desiredVal == SAT_VALUE_FALSE) ret = handleOrTrue(node, SAT_VALUE_FALSE); else ret = handleOrFalse(node, SAT_VALUE_TRUE); break; case kind::OR: if (desiredVal == SAT_VALUE_FALSE) ret = handleOrFalse(node, SAT_VALUE_FALSE); else ret = handleOrTrue(node, SAT_VALUE_TRUE); break; case kind::IMPLIES: Assert(node.getNumChildren() == 2, "Expected 2 fanins"); if (desiredVal == SAT_VALUE_FALSE) { ret = findSplitterRec(node[0], SAT_VALUE_TRUE); if(ret) break; ret = findSplitterRec(node[1], SAT_VALUE_FALSE); break; } else { if (tryGetSatValue(node[0]) != SAT_VALUE_TRUE) { ret = findSplitterRec(node[0], SAT_VALUE_FALSE); //if(!ret || !d_multipleBacktrace) break; } if (tryGetSatValue(node[1]) != SAT_VALUE_FALSE) { ret = findSplitterRec(node[1], SAT_VALUE_TRUE); break; } Assert(d_multipleBacktrace, "No controlling input found (3)"); } break; case kind::XOR: flipCaseVal = SAT_VALUE_TRUE; case kind::IFF: { SatValue val = tryGetSatValue(node[0]); if (val != SAT_VALUE_UNKNOWN) { ret = findSplitterRec(node[0], val); if (ret) break; if (desiredVal == flipCaseVal) val = invertValue(val); ret = findSplitterRec(node[1], val); } else { val = tryGetSatValue(node[1]); if (val == SAT_VALUE_UNKNOWN) val = SAT_VALUE_FALSE; if (desiredVal == flipCaseVal) val = invertValue(val); ret = findSplitterRec(node[0], val); if(ret) break; Assert(false, "Unable to find controlling input (4)"); } break; } case kind::ITE: ret = handleITE(node, desiredVal); break; default: Assert(false, "Unexpected Boolean operator"); break; }//end of switch(k) d_visited.erase(node); if(ret == false) { Assert(litPresent == false || litVal == desiredVal, "Output should be justified"); setJustified(node); } return ret; Unreachable(); }/* findRecSplit method */