summaryrefslogtreecommitdiff
path: root/src/smt/boolean_terms.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/smt/boolean_terms.cpp')
-rw-r--r--src/smt/boolean_terms.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/src/smt/boolean_terms.cpp b/src/smt/boolean_terms.cpp
new file mode 100644
index 000000000..c332642f1
--- /dev/null
+++ b/src/smt/boolean_terms.cpp
@@ -0,0 +1,254 @@
+/********************* */
+/*! \file boolean_terms.cpp
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
+ ** Courant Institute of Mathematical Sciences
+ ** New York University
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief [[ Add one-line brief description here ]]
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
+ **/
+
+#include "smt/boolean_terms.h"
+#include "smt/smt_engine.h"
+#include "theory/theory_engine.h"
+#include "theory/model.h"
+#include "expr/kind.h"
+#include <string>
+#include <algorithm>
+
+using namespace std;
+using namespace CVC4::theory;
+
+namespace CVC4 {
+namespace smt {
+
+const Datatype& BooleanTermConverter::booleanTermsConvertDatatype(const Datatype& dt) throw() {
+ return dt;
+ // boolean terms not supported in datatypes, yet
+
+ Debug("boolean-terms") << "booleanTermsConvertDatatype: considering " << dt.getName() << endl;
+ for(Datatype::const_iterator c = dt.begin(); c != dt.end(); ++c) {
+ TypeNode t = TypeNode::fromType((*c).getConstructor().getType());
+ for(TypeNode::const_iterator a = t.begin(); a != t.end(); ++a) {
+ if((*a).isBoolean()) {
+ Datatype newDt(dt.getName() + "'");
+ Debug("boolean-terms") << "found a Boolean arg in constructor " << (*c).getName() << endl;
+ for(c = dt.begin(); c != dt.end(); ++c) {
+ DatatypeConstructor ctor((*c).getName() + "'", (*c).getTesterName() + "'");
+ t = TypeNode::fromType((*c).getConstructor().getType());
+ for(DatatypeConstructor::const_iterator a = (*c).begin(); a != (*c).end(); ++a) {
+ if((*a).getType().getRangeType().isBoolean()) {
+ ctor.addArg((*a).getName() + "'", NodeManager::currentNM()->mkBitVectorType(1).toType());
+ } else {
+ Type argType = (*a).getType().getRangeType();
+ if(argType.isDatatype() && DatatypeType(argType).getDatatype() == dt) {
+ ctor.addArg((*a).getName() + "'", DatatypeSelfType());
+ } else {
+ ctor.addArg((*a).getName() + "'", argType);
+ }
+ }
+ }
+ newDt.addConstructor(ctor);
+ }
+ DatatypeType newDtt = NodeManager::currentNM()->toExprManager()->mkDatatypeType(newDt);
+ const Datatype& newD = newDtt.getDatatype();
+ for(c = dt.begin(); c != dt.end(); ++c) {
+ Debug("boolean-terms") << "constructor " << (*c).getConstructor() << ":" << (*c).getConstructor().getType() << " made into " << newD[(*c).getName() + "'"].getConstructor() << ":" << newD[(*c).getName() + "'"].getConstructor().getType() << endl;
+ d_booleanTermCache[make_pair(Node::fromExpr((*c).getConstructor()), false)] = Node::fromExpr(newD[(*c).getName() + "'"].getConstructor());
+ d_booleanTermCache[make_pair(Node::fromExpr((*c).getTester()), false)] = Node::fromExpr(newD[(*c).getName() + "'"].getTester());
+ for(DatatypeConstructor::const_iterator a = (*c).begin(); a != (*c).end(); ++a) {
+ d_booleanTermCache[make_pair(Node::fromExpr((*a).getSelector()), false)] = Node::fromExpr(newD[(*c).getName() + "'"].getSelector((*a).getName() + "'"));
+ }
+ }
+ return newD;
+ }
+ }
+ }
+ return dt;
+}/* BooleanTermConverter::booleanTermsConvertDatatype() */
+
+Node BooleanTermConverter::rewriteBooleanTerms(TNode top, bool boolParent) throw() {
+ Debug("boolean-terms") << "rewriteBooleanTerms: " << top << " - boolParent=" << boolParent << endl;
+
+ BooleanTermCache::iterator i = d_booleanTermCache.find(make_pair<Node, bool>(top, boolParent));
+ if(i != d_booleanTermCache.end()) {
+ return (*i).second.isNull() ? Node(top) : (*i).second;
+ }
+
+ Kind k = top.getKind();
+ kind::MetaKind mk = top.getMetaKind();
+
+ NodeManager* nm = NodeManager::currentNM();
+
+ if(!boolParent && top.getType().isBoolean()) {
+ Node one = nm->mkConst(BitVector(1u, 1u));
+ Node zero = nm->mkConst(BitVector(1u, 0u));
+ // still need to rewrite e.g. function applications over boolean
+ Node topRewritten = rewriteBooleanTerms(top, true);
+ Node n = nm->mkNode(kind::ITE, topRewritten, one, zero);
+ Debug("boolean-terms") << "constructed ITE: " << n << endl;
+ return n;
+ }
+
+ if(mk == kind::metakind::CONSTANT) {
+ Assert(k != kind::STORE_ALL, "array store-all not yet supported by Boolean-term conversion");
+ return top;
+ } else if(mk == kind::metakind::VARIABLE) {
+ TypeNode t = top.getType();
+ if(t.isFunction()) {
+ for(unsigned i = 0; i < t.getNumChildren() - 1; ++i) {
+ if(t[i].isBoolean()) {
+ vector<TypeNode> argTypes = t.getArgTypes();
+ replace(argTypes.begin(), argTypes.end(), t[i], nm->mkBitVectorType(1));
+ TypeNode newType = nm->mkFunctionType(argTypes, t.getRangeType());
+ Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()) + "_bt",
+ newType, "a function introduced by Boolean-term conversion",
+ NodeManager::SKOLEM_EXACT_NAME);
+ Debug("boolean-terms") << "constructed func: " << n << " of type " << newType << endl;
+ top.setAttribute(BooleanTermAttr(), n);
+ d_booleanTermCache[make_pair(top, boolParent)] = n;
+ return n;
+ }
+ }
+ } else if(t.isArray()) {
+ TypeNode indexType = t.getArrayIndexType();
+ TypeNode constituentType = t.getArrayConstituentType();
+ bool rewrite = false;
+ if(indexType.isBoolean()) {
+ indexType = nm->mkBitVectorType(1);
+ rewrite = true;
+ }
+ if(constituentType.isBoolean()) {
+ constituentType = nm->mkBitVectorType(1);
+ rewrite = true;
+ }
+ if(rewrite) {
+ TypeNode newType = nm->mkArrayType(indexType, constituentType);
+ Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()),
+ newType, "an array variable introduced by Boolean-term conversion",
+ NodeManager::SKOLEM_EXACT_NAME);
+ top.setAttribute(BooleanTermAttr(), n);
+ Debug("boolean-terms") << "constructed: " << n << " of type " << newType << endl;
+ d_booleanTermCache[make_pair(top, boolParent)] = n;
+ return n;
+ }
+ d_booleanTermCache[make_pair(top, boolParent)] = Node::null();
+ return top;
+ } else if(t.isTuple()) {
+ return top;
+ } else if(t.isRecord()) {
+ return top;
+ } else if(t.isDatatype()) {
+ const Datatype& dt = t.getConst<Datatype>();
+ const Datatype& dt2 = booleanTermsConvertDatatype(dt);
+ if(dt != dt2) {
+ Assert(d_booleanTermCache.find(make_pair(top, boolParent)) == d_booleanTermCache.end(),
+ "Node `%s' already in cache ?!", top.toString().c_str());
+ Assert(top.isVar());
+ TypeNode newType = TypeNode::fromType(dt2.getDatatypeType());
+ Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()),
+ newType, "an array variable introduced by Boolean-term conversion",
+ NodeManager::SKOLEM_EXACT_NAME);
+ top.setAttribute(BooleanTermAttr(), n);
+ Debug("boolean-terms") << "constructed: " << n << " of type " << newType << endl;
+ d_booleanTermCache[make_pair(top, boolParent)] = n;
+ return n;
+ } else {
+ d_booleanTermCache[make_pair(top, boolParent)] = Node::null();
+ return top;
+ }
+ } else if(t.isConstructor()) {
+ Assert(!boolParent);
+ const Datatype& dt = t[t.getNumChildren() - 1].getConst<Datatype>();
+ const Datatype& dt2 = booleanTermsConvertDatatype(dt);
+ if(dt != dt2) {
+ Assert(d_booleanTermCache.find(make_pair(top, boolParent)) != d_booleanTermCache.end(),
+ "constructor `%s' not in cache", top.toString().c_str());
+ return d_booleanTermCache[make_pair(top, boolParent)];
+ } else {
+ d_booleanTermCache[make_pair(top, boolParent)] = Node::null();
+ return top;
+ }
+ } else if(t.isTester() || t.isSelector()) {
+ Assert(!boolParent);
+ const Datatype& dt = t[0].getConst<Datatype>();
+ const Datatype& dt2 = booleanTermsConvertDatatype(dt);
+ if(dt != dt2) {
+ Assert(d_booleanTermCache.find(make_pair(top, boolParent)) != d_booleanTermCache.end(),
+ "tester or selector `%s' not in cache", top.toString().c_str());
+ return d_booleanTermCache[make_pair(top, boolParent)];
+ } else {
+ d_booleanTermCache[make_pair(top, boolParent)] = Node::null();
+ return top;
+ }
+ } else if(t.getNumChildren() > 0) {
+ for(TypeNode::iterator i = t.begin(); i != t.end(); ++i) {
+ if((*i).isBoolean()) {
+ vector<TypeNode> argTypes(t.begin(), t.end());
+ replace(argTypes.begin(), argTypes.end(), *i, nm->mkBitVectorType(1));
+ TypeNode newType = nm->mkTypeNode(t.getKind(), argTypes);
+ Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()),
+ newType, "a variable introduced by Boolean-term conversion",
+ NodeManager::SKOLEM_EXACT_NAME);
+ Debug("boolean-terms") << "constructed: " << n << " of type " << newType << endl;
+ top.setAttribute(BooleanTermAttr(), n);
+ d_booleanTermCache[make_pair(top, boolParent)] = n;
+ return n;
+ }
+ }
+ }/* else if(t.isRecord()) {
+ Unimplemented();
+ }*/
+ return top;
+ }
+ switch(k) {
+ case kind::LAMBDA:
+ case kind::FORALL:
+ case kind::EXISTS:
+ case kind::REWRITE_RULE:
+ case kind::RR_REWRITE:
+ case kind::RR_REDUCTION:
+ case kind::RR_DEDUCTION:
+ //Assert(false, "not yet supported");
+ return top;
+
+ default:
+ NodeBuilder<> b(k);
+ Debug("bt") << "looking at: " << top << std::endl;
+ if(mk == kind::metakind::PARAMETERIZED) {
+ if(kindToTheoryId(k) != THEORY_BV &&
+ k != kind::TUPLE_SELECT &&
+ k != kind::TUPLE_UPDATE &&
+ k != kind::RECORD_SELECT &&
+ k != kind::RECORD_UPDATE &&
+ k != kind::RECORD) {
+ Debug("bt") << "rewriting: " << top.getOperator() << std::endl;
+ b << rewriteBooleanTerms(top.getOperator(), kindToTheoryId(k) == THEORY_BOOL);
+ Debug("bt") << "got: " << b.getOperator() << std::endl;
+ } else {
+ b << top.getOperator();
+ }
+ }
+ for(TNode::const_iterator i = top.begin(); i != top.end(); ++i) {
+ Debug("bt") << "rewriting: " << *i << std::endl;
+ b << rewriteBooleanTerms(*i, kindToTheoryId(k) == THEORY_BOOL);
+ Debug("bt") << "got: " << b[b.getNumChildren() - 1] << std::endl;
+ }
+ Node n = b;
+ Debug("boolean-terms") << "constructed: " << n << endl;
+ d_booleanTermCache[make_pair(top, boolParent)] = n;
+ return n;
+ }
+}/* BooleanTermConverter::rewriteBooleanTerms() */
+
+}/* CVC4::smt namespace */
+}/* CVC4 namespace */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback