Fix for bug 517.
authorMorgan Deters <mdeters@cs.nyu.edu>
Fri, 7 Jun 2013 15:30:00 +0000 (11:30 -0400)
committerMorgan Deters <mdeters@cs.nyu.edu>
Fri, 7 Jun 2013 20:02:56 +0000 (16:02 -0400)
src/expr/type_node.cpp
src/smt/boolean_terms.cpp
src/theory/arrays/theory_arrays_rewriter.h

index e654b5d71032e240e23c733caffb2b0be7ca8060..1d4c330fac4df41890019709a3c97648ed1896d9 100644 (file)
@@ -123,6 +123,15 @@ bool TypeNode::isSubtypeOf(TypeNode t) const {
     }
     return true;
   }
+  if(isFunction()) {
+    // A function is a subtype of another if the args are the same type, and 
+    // the return type is a subtype of the other's.  This is enough for now
+    // (and it's necessary for model generation, since a Real-valued function
+    // might return a constant Int and thus the model value is typed differently).
+    return t.isFunction() &&
+           getArgTypes() == t.getArgTypes() &&
+           getRangeType().isSubtypeOf(t.getRangeType());
+  }
   if(isPredicateSubtype()) {
     return getSubtypeParentType().isSubtypeOf(t);
   }
index 166a695a43318006b5016bbe239457441fea2c06..ffd17dc07ce297069f429954650dc678987638f5 100644 (file)
@@ -487,7 +487,27 @@ Node BooleanTermConverter::rewriteBooleanTermsRec(TNode top, theory::TheoryId pa
         } else if(t.isArray()) {
           TypeNode indexType = convertType(t.getArrayIndexType(), false);
           TypeNode constituentType = convertType(t.getArrayConstituentType(), false);
-          if(indexType != t.getArrayIndexType() || constituentType != t.getArrayConstituentType()) {
+          if(indexType != t.getArrayIndexType() && constituentType == t.getArrayConstituentType()) {
+            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;
+            Node n_ff = nm->mkNode(kind::SELECT, n, d_ff);
+            Node n_tt = nm->mkNode(kind::SELECT, n, d_tt);
+            Node base = nm->mkConst(ArrayStoreAll(ArrayType(top.getType().toType()), (*TypeEnumerator(n_ff.getType())).toExpr()));
+            Node repl = nm->mkNode(kind::STORE,
+                                   nm->mkNode(kind::STORE, base, nm->mkConst(true),
+                                              n_tt),
+                                   nm->mkConst(false), n_ff);
+            Debug("boolean-terms") << "array replacement: " << top << " => " << repl << endl;
+            d_smt.d_theoryEngine->getModel()->addSubstitution(top, repl);
+            d_termCache[make_pair(top, parentTheory)] = n;
+            result.top() << n;
+            worklist.pop();
+            goto next_worklist;
+          } else if(indexType != t.getArrayIndexType() || constituentType != t.getArrayConstituentType()) {
             TypeNode newType = nm->mkArrayType(indexType, constituentType);
             Node n = nm->mkSkolem(top.getAttribute(expr::VarNameAttr()) + "'",
                                   newType, "an array variable introduced by Boolean-term conversion",
index 18bbef8cfdca3f19561c091b60753c5f82e15b2d..5df06bda889b1eab492291cce59c70420b6f31bb 100644 (file)
@@ -36,6 +36,10 @@ namespace attr {
 typedef expr::Attribute<attr::ArrayConstantMostFrequentValueCountTag, uint64_t> ArrayConstantMostFrequentValueCountAttr;
 typedef expr::Attribute<attr::ArrayConstantMostFrequentValueTag, Node> ArrayConstantMostFrequentValueAttr;
 
+static inline Node mkEqNode(Node a, Node b) {
+  return a.getType().isBoolean() ? a.iffNode(b) : a.eqNode(b);
+}
+
 class TheoryArraysRewriter {
   static Node normalizeConstant(TNode node) {
     return normalizeConstant(node, node[1].getType().getCardinality());
@@ -244,7 +248,7 @@ public:
             val = false;
           }
           else {
-            n = Rewriter::rewrite(store[1].eqNode(index));
+            n = Rewriter::rewrite(mkEqNode(store[1], index));
             if (n.getKind() != kind::CONST_BOOLEAN) {
               break;
             }
@@ -301,7 +305,7 @@ public:
             val = false;
           }
           else {
-            Node eqRewritten = Rewriter::rewrite(store[1].eqNode(index));
+            Node eqRewritten = Rewriter::rewrite(mkEqNode(store[1], index));
             if (eqRewritten.getKind() != kind::CONST_BOOLEAN) {
               Trace("arrays-postrewrite") << "Arrays::postRewrite returning " << node << std::endl;
               return RewriteResponse(REWRITE_DONE, node);
@@ -340,7 +344,7 @@ public:
                 val = false;
               }
               else {
-                n = Rewriter::rewrite(store[1].eqNode(index));
+                n = Rewriter::rewrite(mkEqNode(store[1], index));
                 if (n.getKind() != kind::CONST_BOOLEAN) {
                   break;
                 }
@@ -416,7 +420,7 @@ public:
             val = false;
           }
           else {
-            n = Rewriter::rewrite(store[1].eqNode(index));
+            n = Rewriter::rewrite(mkEqNode(store[1], index));
             if (n.getKind() != kind::CONST_BOOLEAN) {
               break;
             }
@@ -466,7 +470,7 @@ public:
             val = false;
           }
           else {
-            Node eqRewritten = Rewriter::rewrite(store[1].eqNode(index));
+            Node eqRewritten = Rewriter::rewrite(mkEqNode(store[1], index));
             if (eqRewritten.getKind() != kind::CONST_BOOLEAN) {
               break;
             }