clause[0] = a;
assertClause(clause);
}
+
void CnfStream::assertClause(SatLiteral a, SatLiteral b) {
SatClause clause(2);
clause[0] = a;
clause[1] = b;
assertClause(clause);
}
+
void CnfStream::assertClause(SatLiteral a, SatLiteral b, SatLiteral c) {
SatClause clause(3);
clause[0] = a;
return literal;
}
+const CnfStream::NodeCache& CnfStream::getNodeCache() const {
+ return d_nodeCache;
+}
+
+const CnfStream::TranslationCache& CnfStream::getTranslationCache() const {
+ return d_translationCache;
+}
+
SatLiteral TseitinCnfStream::handleAtom(TNode node) {
Assert(node.isAtomic(), "handleAtom(n) expects n to be an atom");
Assert(!isCached(node), "atom already mapped!");
Assert(iteNode.getKind() == ITE);
Assert(iteNode.getNumChildren() == 3);
+ Debug("cnf") << "handlIte(" << iteNode[0] << " " << iteNode[1] << " " << iteNode[2] << ")" << endl;
+
SatLiteral condLit = toCNF(iteNode[0]);
SatLiteral thenLit = toCNF(iteNode[1]);
SatLiteral elseLit = toCNF(iteNode[2]);
// If ITE is true then one of the branches is true and the condition
// implies which one
+ // lit -> (ite b t e)
+ // lit -> (t | e) & (b -> t) & (!b -> e)
+ // lit -> (t | e) & (!b | t) & (b | e)
+ // (!lit | t | e) & (!lit | !b | t) & (!lit | b | e)
+ assertClause(~iteLit, thenLit, elseLit);
assertClause(~iteLit, ~condLit, thenLit);
assertClause(~iteLit, condLit, elseLit);
- assertClause(~iteLit, elseLit, thenLit);
// If ITE is false then one of the branches is false and the condition
// implies which one
+ // !lit -> !(ite b t e)
+ // !lit -> (!t | !e) & (b -> !t) & (!b -> !e)
+ // !lit -> (!t | !e) & (!b | !t) & (b | !e)
+ // (lit | !t | !e) & (lit | !b | !t) & (lit | b | !e)
+ assertClause(iteLit, ~thenLit, ~elseLit);
assertClause(iteLit, ~condLit, ~thenLit);
assertClause(iteLit, condLit, ~elseLit);
- assertClause(iteLit, ~thenLit, ~elseLit);
return iteLit;
}
Node TseitinCnfStream::handleNonAtomicNode(TNode node) {
+ Debug("cnf") << "handleNonAtomicNode(" << node << ")" << endl;
+
/* Our main goal here is to tease out any ITE's sitting under a theory operator. */
Node rewrite;
NodeManager *nodeManager = NodeManager::currentNM();
}
SatLiteral TseitinCnfStream::toCNF(TNode node) {
+ Debug("cnf") << "toCNF(" << node << ")" << endl;
// If the node has already been translated, return the previous translation
if(isCached(node)) {
* @author Tim King <taking@cs.nyu.edu>
*/
class CnfStream {
+public:
+ /** Cache of what nodes have been registered to a literal. */
+ typedef __gnu_cxx::hash_map<SatLiteral, Node, SatSolver::SatLiteralHashFunction> NodeCache;
+
+ /** Cache of what literals have been registered to a node. */
+ typedef __gnu_cxx::hash_map<Node, SatLiteral, NodeHashFunction> TranslationCache;
private:
/** The SAT solver we will be using */
SatInputInterface *d_satSolver;
- /** Cache of what literals have been registered to a node. */
- typedef __gnu_cxx::hash_map<Node, SatLiteral, NodeHashFunction> TranslationCache;
TranslationCache d_translationCache;
-
- /** Cache of what nodes have been registered to a literal. */
- typedef __gnu_cxx::hash_map<SatLiteral, Node, SatSolver::SatLiteralHashFunction> NodeCache;
NodeCache d_nodeCache;
protected:
*/
SatLiteral getLiteral(TNode node);
+ const TranslationCache& getTranslationCache() const;
+ const NodeCache& getNodeCache() const;
}; /* class CnfStream */
/**
#include <utility>
#include <map>
+#include <iomanip>
using namespace std;
using namespace CVC4::context;
d_cnfStream->convertAndAssert(node);
}
+
+void PropEngine::printSatisfyingAssignment(){
+ const CnfStream::TranslationCache& transCache = d_cnfStream->getTranslationCache();
+ Debug("prop-value") << "Literal | Value | Expr" << endl
+ << "---------------------------------------------------------" << endl;
+ for(CnfStream::TranslationCache::const_iterator i = transCache.begin(),
+ end = transCache.end();
+ i != end;
+ ++i) {
+ pair<Node, SatLiteral> curr = *i;
+ SatLiteral l = curr.second;
+ if(!sign(l)) {
+ Node n = curr.first;
+ SatLiteralValue value = d_satSolver->value(l);
+ Debug("prop-value") << /*setw(4) << */ "'" << l << "' " /*<< setw(4)*/ << value << " " << n
+ << endl;
+ }
+ }
+}
+
Result PropEngine::checkSat() {
Assert(!d_inCheckSat, "Sat solver in solve()!");
Debug("prop") << "PropEngine::checkSat()" << endl;
bool result = d_satSolver->solve();
// Not in checkSat any more
d_inCheckSat = false;
+
+ if( result && debugTagIsOn("prop") ) {
+ printSatisfyingAssignment();
+ }
+
Debug("prop") << "PropEngine::checkSat() => " << (result ? "true" : "false") << endl;
return Result(result ? Result::SAT : Result::UNSAT);
}
/** The CNF converter in use */
CnfStream* d_cnfStream;
+ void printSatisfyingAssignment();
+
public:
/**
void SatSolver::enqueueTheoryLiteral(const SatLiteral& l) {
Node literalNode = d_cnfStream->getNode(l);
+ Debug("prop") << "enqueueing theory literal " << l << " " << literalNode << std::endl;
// We can get null from the prop engine if the literal is useless (i.e.)
// the expression is not in context anyomore
if(!literalNode.isNull()) {
/** Type of the SAT clauses */
typedef minisat::vec<SatLiteral> SatClause;
+typedef minisat::lbool SatLiteralValue;
+
/**
* Returns the variable of the literal.
* @param lit the literal
return (size_t) minisat::toInt(literal);
}
+inline std::string stringOfLiteralValue(SatLiteralValue val) {
+ if( val == minisat::l_False ) {
+ return "0";
+ } else if (val == minisat::l_True ) {
+ return "1";
+ } else { // unknown
+ return "_";
+ }
+}
#endif /* __CVC4_USE_MINISAT */
/** Interface encapsulating the "input" to the solver, e.g., from the
void enqueueTheoryLiteral(const SatLiteral& l);
void setCnfStream(CnfStream* cnfStream);
+
+ SatLiteralValue value(SatLiteral l);
};
/* Functions that delegate to the concrete SAT solver. */
return d_minisat->newVar(true, true, theoryAtom);
}
+inline SatLiteralValue SatSolver::value(SatLiteral l) {
+ return d_minisat->modelValue(l);
+}
+
#endif /* __CVC4_USE_MINISAT */
inline size_t
return out;
}
+inline std::ostream& operator <<(std::ostream& out, const SatLiteralValue& val) {
+ out << stringOfLiteralValue(val);
+ return out;
+}
+
}/* CVC4::prop namespace */
}/* CVC4 namespace */