uncompiling new bv to bool lifting
authorlianah <lianahady@gmail.com>
Tue, 16 Apr 2013 14:57:04 +0000 (10:57 -0400)
committerlianah <lianahady@gmail.com>
Tue, 30 Apr 2013 19:54:24 +0000 (15:54 -0400)
src/smt/smt_engine.cpp
src/theory/bv/bv_to_bool.cpp
src/theory/bv/bv_to_bool.h
src/theory/theory_engine.cpp
src/theory/theory_engine.h

index f3d5d446ec1d54b84598dfcc1a3d7fae2c26359f..0f79da82ad826899a7872e2a4894a8174da4adcd 100644 (file)
@@ -1926,9 +1926,10 @@ bool SmtEnginePrivate::nonClausalSimplify() {
 
 void SmtEnginePrivate::bvToBool() {
   Trace("simplify") << "SmtEnginePrivate::bvToBool()" << endl;
-
+  std::vector<Node> new_assertions;
+  d_smt.d_theoryEngine->ppBvToBool(d_assertionsToCheck, new_assertions); 
   for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
-    d_assertionsToCheck[i] = d_smt.d_theoryEngine->ppBvToBool(d_assertionsToCheck[i]);
+    d_assertionsToCheck[i] = Rewriter::rewrite(new_assertions[i]); 
   }
 }
 
@@ -2481,16 +2482,6 @@ bool SmtEnginePrivate::simplifyAssertions()
     Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
     Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
 
-    // Lift bit-vectors of size 1 to bool 
-    if(options::bvToBool()) {
-      Chat() << "...doing bvToBool..." << endl;
-      bvToBool();
-    }
-
-    Trace("smt") << "POST bvToBool" << endl;
-    Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
-    Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
-    
     if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
       Chat() << "...doing another round of nonclausal simplification..." << endl;
       Trace("simplify") << "SmtEnginePrivate::simplify(): "
@@ -2789,6 +2780,17 @@ void SmtEnginePrivate::processAssertions() {
   }
   dumpAssertions("post-static-learning", d_assertionsToCheck);
 
+  // Lift bit-vectors of size 1 to bool 
+  if(options::bvToBool()) {
+    Chat() << "...doing bvToBool..." << endl;
+    bvToBool();
+  }
+
+  Trace("smt") << "POST bvToBool" << endl;
+  Debug("smt") << " d_assertionsToPreprocess: " << d_assertionsToPreprocess.size() << endl;
+  Debug("smt") << " d_assertionsToCheck     : " << d_assertionsToCheck.size() << endl;
+
+  
   dumpAssertions("pre-ite-removal", d_assertionsToCheck);
   {
     Chat() << "removing term ITEs..." << endl;
index 5ab7cf1446528f0a0fff228aef1c1d1db85c3c5c..7d3f58c8e1ff0d04c0b7802752ee275c8b83cb04 100644 (file)
@@ -23,22 +23,6 @@ using namespace CVC4;
 using namespace CVC4::theory;
 using namespace CVC4::theory::bv;
 
-void BvToBoolVisitor::storeBvToBool(TNode bv_term, Node bool_term) {
-  Assert (!hasBoolTerm(bv_term));
-  Assert (bool_term.getType().isBoolean()); 
-  d_bvToBoolTerm[bv_term] = bool_term; 
-}
-
-Node BvToBoolVisitor::getBoolTerm(TNode bv_term) const {
-  Assert(hasBoolTerm(bv_term));
-  return d_bvToBoolTerm.find(bv_term)->second; 
-}
-
-bool BvToBoolVisitor::hasBoolTerm(TNode bv_term) const {
-  Assert (bv_term.getType().isBitVector()); 
-  return d_bvToBoolTerm.find(bv_term) != d_bvToBoolTerm.end(); 
-}
-
 void BvToBoolVisitor::addToCache(TNode term, Node new_term) {
   Assert (new_term != Node()); 
   Assert (!hasCache(term));
@@ -56,130 +40,167 @@ bool BvToBoolVisitor::hasCache(TNode term) const {
   return d_cache.find(term) != d_cache.end(); 
 }
 
-
 void BvToBoolVisitor::start(TNode node) {}
 
+void BvToBoolVisitor::storeBvToBool(TNode bv_term, TNode bool_term) {
+  Assert (bv_term.getType().isBitVector() &&
+          bv_term.getType().getBitVectorSize() == 1);
+  Assert (bool_term.getType().isBoolean() &&  d_bvToBoolMap.find(bv_term) == d_bvToBoolMap.end());
+  d_bvToBoolMap[bv_term] = bool_term; 
+}
+
+Node BvToBoolVisitor::getBoolForBvTerm(TNode node) {
+  Assert (d_bvToBoolMap.find(node) != d_bvToBoolMap.end());
+  return d_bvToBoolMap[node]; 
+}
+
 bool BvToBoolVisitor::alreadyVisited(TNode current, TNode parent) {
-  return d_visited.find(current) != d_visited.end(); 
+  return d_cache.find(current) != d_cache.end(); 
+}
+
+bool BvToBoolVisitor::isConvertibleBvAtom(TNode node) {
+  Kind kind = node.getKind();
+  return (kind == kind::BITVECTOR_ULT ||
+          kind == kind::BITVECTOR_ULE ||
+          kind == kind::EQUAL) &&
+    node[0].getType().isBitVector() &&
+    node[0].getType().getBitVectorSize() == 1; 
 }
 
-bool BvToBoolVisitor::isConvertibleToBool(TNode current) {
-  TypeNode type = current.getType(); 
-  if (current.getNumChildren() == 0 && type.isBitVector()) {
-    return type.getBitVectorSize() == 1; 
-  }
-
-  if (current.getKind() == kind::NOT) {
-    current = current[0];
-  }
-  Kind kind = current.getKind();
-  // checking bit-vector kinds 
-  if (kind == kind::BITVECTOR_OR ||
-      kind == kind::BITVECTOR_AND ||
-      kind == kind::BITVECTOR_XOR ||
-      kind == kind::BITVECTOR_NOT ||
-      kind == kind::BITVECTOR_ULT ||
-      kind == kind::BITVECTOR_ULE ||
-      kind == kind::EQUAL) {
-    // we can convert it to bool if all of the children can also be converted
-    // to bool
-    if (! current[0].getType().getBitVectorSize() == 1)
-      return false; 
-    for (unsigned i = 0; i < current.getNumChildren(); ++i) {
-      // we assume that the children have been visited
-      if (!hasBoolTerm(current[i]))
+bool BvToBoolVisitor::isConvertibleBvTerm(TNode node) {
+  // we have already converted it and the result is cached
+  if (d_bvToBoolMap.find(node) != d_bvToBoolMap.end()) {
+    return true;
+  }
+  
+  Kind kind = node.getKind();
+  if (!node.getType().isBitVector() || node.getType().getBitVectorSize() != 1)
+    return false;
+  
+  if (kind == kind::CONST_BITVECTOR) {
+    return true; 
+  }
+
+  if (kind == kind::BITVECTOR_AND || kind == kind::BITVECTOR_OR ||
+      kind == kind::BITVECTOR_NOT || kind == kind::BITVECTOR_XOR) {
+    for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+      if (!isConvertibleBvTerm(node[i]))
         return false; 
     }
     return true; 
   }
-  if (kind == kind::ITE &&
-      type.isBitVector()) {
-    return type.getBitVectorSize() == 1 && hasBoolTerm(current[1]) && hasBoolTerm(current[2]); 
-  }
   return false; 
 }
 
-
-Node BvToBoolVisitor::convertToBool(TNode current) {
-  Debug("bv-to-bool") << "BvToBoolVisitor::convertToBool (" << current << ") "; 
-  Kind kind = current.getKind();
-
-  Node new_current; 
-  if (current.getNumChildren() == 0) {
-    if (current.getKind() == kind::CONST_BITVECTOR) {
-      new_current = current == d_one? utils::mkTrue() : utils::mkFalse(); 
-    } else {
-      new_current = utils::mkNode(kind::EQUAL, current, d_one); 
-    }
-    Debug("bv-to-bool") << "=> " << new_current << "\n"; 
-  } else if (kind == kind::BITVECTOR_ULT) {
-    TNode a = getBoolTerm(current[0]);
-    TNode b = getBoolTerm(current[1]);
-    Node a_eq_0 = utils::mkNode(kind::EQUAL, a, d_zero);
-    Node b_eq_1 = utils::mkNode(kind::EQUAL, b, d_one);
-    new_current = utils::mkNode(kind::AND, a_eq_0, b_eq_1);
-  }  else if (kind == kind::BITVECTOR_ULE) {
-    TNode a = getBoolTerm(current[0]);
-    TNode b = getBoolTerm(current[1]);
+Node BvToBoolVisitor::convertBvAtom(TNode node) {
+  Assert (node.getType().isBoolean());
+  Kind kind = node.getKind();
+  Node result; 
+  switch(kind) {
+  case kind::BITVECTOR_ULT: {
+    TNode a = getBoolForBvTerm(node[0]);
+    TNode b = getBoolForBvTerm(node[1]);
     Node a_eq_0 = utils::mkNode(kind::EQUAL, a, d_zero);
     Node b_eq_1 = utils::mkNode(kind::EQUAL, b, d_one);
-    Node a_lt_b = utils::mkNode(kind::AND, a_eq_0, b_eq_1); 
-    Node a_eq_b = utils::mkNode(kind::EQUAL, a, b);
-    new_current = utils::mkNode(kind::OR, a_lt_b, a_eq_b);
-  } else if (kind == kind::ITE) {
-    TNode cond = current[0];
-    TNode a = getBoolTerm(current[1]);
-    TNode b = getBoolTerm(current[2]);
-    new_current = utils::mkNode(kind::ITE, cond, a, b);
-  } else {
-    Kind new_kind; 
-    switch (kind) {
-    case kind::BITVECTOR_OR :
-      new_kind = kind::OR;
-      break; 
-    case kind::BITVECTOR_AND:
-      new_kind =  kind::AND;
-      break; 
-    case kind::BITVECTOR_XOR:
-      new_kind = kind::XOR;
-      break; 
-    case kind::BITVECTOR_NOT:
-      new_kind =  kind::NOT;
-      break; 
-    case kind::EQUAL:
-      new_kind = kind::IFF;
-      break; 
-    default:
-      Unreachable("Unknown kind ", kind);  
-    }
-    NodeBuilder<> builder(new_kind);
-    if (current.getMetaKind() == kind::metakind::PARAMETERIZED) {
-      builder << current.getOperator();
+    result = utils::mkNode(kind::AND, a_eq_0, b_eq_1);
+    break;
+  }
+  case kind::BITVECTOR_ULE: {
+   TNode a = getBoolForBvTerm(node[0]);
+   TNode b = getBoolForBvTerm(node[1]);
+   Node a_eq_0 = utils::mkNode(kind::EQUAL, a, d_zero);
+   Node b_eq_1 = utils::mkNode(kind::EQUAL, b, d_one);
+   Node a_lt_b = utils::mkNode(kind::AND, a_eq_0, b_eq_1); 
+   Node a_eq_b = utils::mkNode(kind::EQUAL, a, b);
+   result = utils::mkNode(kind::OR, a_lt_b, a_eq_b);    
+   break;
+  }
+  case kind::EQUAL: {
+    TNode a = getBoolForBvTerm(node[0]);
+    TNode b = getBoolForBvTerm(node[1]);
+    result = utils::mkNode(kind::IFF, a, b); 
+    break;
+  }
+  default:
+    Unhandled(); 
+  }
+  Assert (result != Node());
+  return result;
+}
+
+Node BvToBoolVisitor::convertBvTerm(TNode node) {
+  Assert (node.getType().isBitVector() &&
+          node.getType().getBitVectorSize() == 1);
+  Kind kind = node.getKind(); 
+
+  if (node.getNumChildren() == 0) {
+    if (node.getKind() == kind::VARIABLE) {
+      return getBoolForBvTerm(node);
     }
-    for (unsigned i = 0; i < current.getNumChildren(); ++i) {
-      builder << getBoolTerm(current[i]); 
+    if (node.getKind() == kind::CONST_BITVECTOR) {
+      return (node == d_one ? utils::mkTrue() : utils::mkFalse());
     }
-    new_current = builder;
   }
   
-  Debug("bv-to-bool") << "=> " << new_current << "\n";
-  if (current.getType().isBitVector()) {
-    storeBvToBool(current, new_current); 
-  } else {
-    addToCache(current, new_current); 
+  if (kind == kind::ITE) {
+    TNode cond = getCache(node[0]);
+    TNode true_branch = getBoolForBvTerm(node[1]);
+    TNode false_branch = getBoolForBvTerm(node[2]);
+    Node result = utils::mkNode(kind::ITE, cond, true_branch, false_branch);
+    storeBvToBool(node, result);
+    return result; 
+  }
+  
+  Kind new_kind; 
+  switch(kind) {
+  case kind::BITVECTOR_OR:
+    new_kind = kind::OR;
+    break;
+  case kind::BITVECTOR_AND:
+    new_kind = kind::AND;
+    break;
+  case kind::BITVECTOR_XOR:
+    new_kind = kind::XOR;
+    break;
+  case kind::BITVECTOR_NOT:
+    new_kind = kind::NOT;
+    break;
+  default:
+    Unhandled(); 
+  }
+
+  NodeBuilder<> builder(new_kind);
+  for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+    builder << getBoolForBvTerm(node[i]); 
+  }
+  Node result = builder;
+  storeBvToBool(node, result);
+  return result; 
+}
+
+void BvToBoolVisitor::check(TNode current, TNode parent) {
+  if (d_bvToBoolMap.find(current) != d_bvToBoolMap.end()) {
+    if (!isConvertibleBvTerm(parent) && !isConvertibleBvAtom(parent)) {
+      Debug("bv-to-bool") << "BvToBoolVisitor::check " << current << " in non boolean context: \n"
+                          << "           " << parent << "\n"; 
+    }
   }
-  return new_current; 
 }
 
 void BvToBoolVisitor::visit(TNode current, TNode parent) {
   Debug("bv-to-bool") << "BvToBoolVisitor visit (" << current << ", " << parent << ")\n"; 
-  Assert (!alreadyVisited(current, parent));
-  d_visited.insert(current);
+  Assert (!alreadyVisited(current, parent) &&
+          !hasCache(current));
+  
+  Node result;
 
-  Node result; 
-  // if it has more than one child
-  if (isConvertibleToBool(current)) {
-    result = convertToBool(current); 
+  // make sure that the bv terms we are replacing to not occur in other contexts
+  check(current, parent); 
+  
+  if (isConvertibleBvAtom(current)) {
+    result = convertBvAtom(current); 
+  } else if (isConvertibleBvTerm(current)) {
+    result = convertBvTerm(current); 
   } else {
     if (current.getNumChildren() == 0) {
       result = current; 
@@ -190,24 +211,60 @@ void BvToBoolVisitor::visit(TNode current, TNode parent) {
       }
       for (unsigned i = 0; i < current.getNumChildren(); ++i) {
         Node converted = getCache(current[i]);
-        if (converted.getType() == current[i].getType()) {
-          builder << converted; 
-        } else {
-          builder << current[i]; 
-        }
+        Assert (converted.getType() == current[i].getType()); 
+        builder << converted; 
       }
       result = builder;
     }
-    addToCache(current, result); 
   }
+  Assert (result != Node()); 
+  addToCache(current, result);
 }
 
+
 BvToBoolVisitor::return_type BvToBoolVisitor::done(TNode node) {
   Assert (hasCache(node)); 
   return getCache(node); 
 }
 
-Node BvToBoolPreprocessor::liftBoolToBV(TNode assertion) {
-  Node result = NodeVisitor<BvToBoolVisitor>::run(d_visitor, assertion);
-  return result; 
+bool BvToBoolPreprocessor::matchesBooleanPatern(TNode current) {
+  // we are looking for something of the type (= (bvvar 1) (some predicate))
+  if (current.getKind() == kind::IFF &&
+      current[0].getKind() == kind::EQUAL &&
+      current[0][0].getType().isBitVector() &&
+      current[0][0].getType().getBitVectorSize() == 1 &&
+      current[0][0].getKind() == kind::VARIABLE &&
+      current[0][1].getKind() == kind::CONST_BITVECTOR) {
+    return true; 
+  }    
+  return false; 
+}
+
+
+void BvToBoolPreprocessor::liftBoolToBV(const std::vector<TNode>& assertions, std::vector<Node>& new_assertions) {
+  TNodeNodeMap candidates;
+  for (unsigned i = 0; i < assertions.size(); ++i) {
+    if (matchesBooleanPatern(assertions[i])) {
+      TNode assertion = assertions[i]; 
+      TNode bv_var = assertion[0][0];
+      Assert (bv_var.getKind() == kind::VARIABLE &&
+              bv_var.getType().isBitVector() &&
+              bv_bar.getType().getBitVectorSize() == 1);
+      TNode bool_cond = assertion[1];
+      Assert (bool_cond.getType().isBoolean());
+      if (candidates.find(bv_var) == candidates.end()) {
+        Debug("bv-to-bool") << "BBvToBoolPreprocessor::liftBvToBoolBV candidate: " << bv_var <<"\n"; 
+        candidates[bv_var] = bool_cond;
+      } else {
+        Debug("bv-to-bool") << "BvToBoolPreprocessor::liftBvToBoolBV multiple def " << bv_var <<"\n"; 
+      }
+    }
+  }
+  
+  BvToBoolVisitor bvToBoolVisitor(candidates); 
+  for (unsigned i = 0; i < assertions.size(); ++i) {
+    Node new_assertion = NodeVisitor<BvToBoolVisitor>::run(bvToBoolVisitor,
+                                              assertions[i]);
+    new_assertions.push_back(new_assertion); 
+  }
 }
index d5673a295003db0d4a70e4a54d49a15b90768340..9b1534b41e2368e01c310793316dfe5172256359 100644 (file)
@@ -24,33 +24,31 @@ namespace CVC4 {
 namespace theory {
 namespace bv {
 
-class BvToBoolVisitor {
+typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet; 
+typedef __gnu_cxx::hash_map<TNode, Node, TNodeHashFunction> TNodeNodeMap; 
 
-  typedef __gnu_cxx::hash_set<TNode, TNodeHashFunction> TNodeSet; 
-  typedef __gnu_cxx::hash_map<TNode, Node, TNodeHashFunction> TNodeNodeMap; 
+class BvToBoolVisitor {
+  TNodeNodeMap d_bvToBoolMap; 
   TNodeNodeMap d_cache;
-  TNodeNodeMap d_bvToBoolTerm; 
-  TNodeSet d_visited;
   Node d_one;
   Node d_zero;
 
-  void storeBvToBool(TNode bv_term, Node bool_term);
-  Node getBoolTerm(TNode bv_term) const;
-  bool hasBoolTerm(TNode bv_term) const; 
-
   void addToCache(TNode term, Node new_term);
   Node getCache(TNode term) const;
   bool hasCache(TNode term) const; 
-
   
-  bool isConvertibleToBool(TNode current);
-  Node convertToBool(TNode current);
+  bool isConvertibleBvTerm(TNode node);
+  bool isConvertibleBvAtom(TNode node);
+  Node getBoolForBvTerm(TNode node);
+  void storeBvToBool(TNode bv_term, TNode bool_term);
+  Node convertBvAtom(TNode node);
+  Node convertBvTerm(TNode node);
+  void check(TNode current, TNode parent);
 public:
   typedef Node return_type;
-  BvToBoolVisitor()
-    : d_cache(),
-      d_bvToBoolTerm(),
-      d_visited(),
+  BvToBoolVisitor(TNodeNodeMap& bvToBool)
+    : d_bvToBoolMap(bvToBool), 
+      d_cache(),
       d_one(utils::mkConst(BitVector(1, 1u))),
       d_zero(utils::mkConst(BitVector(1, 0u)))
   {}
@@ -60,14 +58,14 @@ public:
   return_type done(TNode node);
 }; 
 
+
 class BvToBoolPreprocessor {
-  BvToBoolVisitor d_visitor; 
+  bool matchesBooleanPatern(TNode node);
 public:
   BvToBoolPreprocessor()
-    : d_visitor()
   {}
   ~BvToBoolPreprocessor() {}
-  Node liftBoolToBV(TNode assertion);
+  void liftBoolToBV(const std::vector<TNode>& assertions, std::vector<Node>& new_assertions);
 }; 
 
 
index 6f965879dd9fb13bfb556e5bfeb571482266d8e9..8c430d6d400f86e108e0c6c6045e542414735f68 100644 (file)
@@ -1277,10 +1277,8 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
   }
 }
 
-Node TheoryEngine::ppBvToBool(TNode assertion) {
-  Node result = d_bvToBoolPreprocessor.liftBoolToBV(assertion);
-  result = Rewriter::rewrite(result);
-  return result; 
+void TheoryEngine::ppBvToBool(const std::vector<TNode>& assertions, std::vector<Node> new_assertions) {
+  d_bvToBoolPreprocessor.liftBoolToBV(assertions, new_assertions);
 }
 
 Node TheoryEngine::ppSimpITE(TNode assertion)
index 324b952b043413abb7ef3da3e2acbf20ea1e8aec..d581aeda2e43d0415fc91c9292f811006a541e13 100644 (file)
@@ -753,7 +753,7 @@ private:
   theory::bv::BvToBoolPreprocessor d_bvToBoolPreprocessor; 
 public:
 
-  Node ppBvToBool(TNode assertion); 
+  void ppBvToBool(const std::vector<TNode>& assertions, std::vector<Node> new_assertions); 
   Node ppSimpITE(TNode assertion);
   void ppUnconstrainedSimp(std::vector<Node>& assertions);