fix beta reduction in both preRewrite() *and* postRewrite(), related to bug 417....
authorMorgan Deters <mdeters@gmail.com>
Tue, 9 Oct 2012 11:58:08 +0000 (11:58 +0000)
committerMorgan Deters <mdeters@gmail.com>
Tue, 9 Oct 2012 11:58:08 +0000 (11:58 +0000)
src/theory/uf/theory_uf_rewriter.h
test/regress/regress0/rewriterules/Makefile.am
test/regress/regress0/rewriterules/simulate_rewriting.smt2 [new file with mode: 0644]
test/regress/regress0/rewriterules/simulate_rewritting.smt2 [deleted file]

index 50211f1ad59372201f0b098d29c56f6b630df528..15ac0f605d94ff78a916bf06698aaf3ce46054c3 100644 (file)
@@ -53,7 +53,23 @@ public:
       for(TNode::iterator formal = lambda[0].begin(), arg = node.begin(); formal != lambda[0].end(); ++formal, ++arg) {
         // typechecking should ensure that the APPLY_UF is well-typed, correct arity, etc.
         Assert(formal != node.end());
-        substitutions.addSubstitution(*formal, *arg);
+        // This rewrite step is important: if we have (f (f 5)) for
+        // some lambda term f, we want to beta-reduce the inside (f 5)
+        // application first.  Otherwise, we can end up in infinite
+        // recursion, because f's formal (say "x") gives the
+        // substitution "x |-> (f 5)".  Fine, the body of the lambda
+        // gets (f 5) in place for x.  But since the same lambda ("f")
+        // now occurs in the body, it's got the same bound var "x", so
+        // substitution continues and we replace that x by (f 5).  And
+        // then again.  :-(
+        //
+        // We need a better solution for distinguishing bound
+        // variables like this, but for now, handle it by going
+        // inside-out.  (Quantifiers shouldn't ever have this problem,
+        // so long as the bound vars in different quantifiers are kept
+        // different.)
+        Node n = Rewriter::rewrite(*arg);
+        substitutions.addSubstitution(*formal, n);
       }
       return RewriteResponse(REWRITE_DONE, substitutions.apply(lambda[1]));
     }
@@ -77,21 +93,7 @@ public:
       for(TNode::iterator formal = lambda[0].begin(), arg = node.begin(); formal != lambda[0].end(); ++formal, ++arg) {
         // typechecking should ensure that the APPLY_UF is well-typed, correct arity, etc.
         Assert(formal != node.end());
-        // This rewrite step is important: if we have (f (f 5)) for
-        // some lambda term f, we want to beta-reduce the inside (f 5)
-        // application first.  Otherwise, we can end up in infinite
-        // recursion, because f's formal (say "x") gives the
-        // substitution "x |-> (f 5)".  Fine, the body of the lambda
-        // gets (f 5) in place for x.  But since the same lambda ("f")
-        // now occurs in the body, it's got the same bound var "x", so
-        // substitution continues and we replace that x by (f 5).  And
-        // then again.  :-(
-        //
-        // We need a better solution for distinguishing bound
-        // variables like this, but for now, handle it by going
-        // inside-out.  (Quantifiers shouldn't ever have this problem,
-        // so long as the bound vars in different quantifiers are kept
-        // different.)
+        // This rewrite step is important: see note in postRewrite().
         Node n = Rewriter::rewrite(*arg);
         substitutions.addSubstitution(*formal, n);
       }
index 3bcf8e62cbb500abf6273bd9fbc52bc8e03d4369..f0d45c28370ef10f1db495d6324578bd2679e7a0 100644 (file)
@@ -21,7 +21,7 @@ MAKEFLAGS = -k
 TESTS =        \
        length_trick.smt2 length_trick2.smt2 length_gen_020.smt2 \
        datatypes.smt2 datatypes_sat.smt2 set_A_new_fast_tableau-base.smt2 \
-       set_A_new_fast_tableau-base_sat.smt2 relation.smt2 simulate_rewritting.smt2 \
+       set_A_new_fast_tableau-base_sat.smt2 relation.smt2 simulate_rewriting.smt2 \
        reachability_back_to_the_future.smt2 native_arrays.smt2 reachability_bbttf_eT_arrays.smt2
 
 EXTRA_DIST = $(TESTS)
diff --git a/test/regress/regress0/rewriterules/simulate_rewriting.smt2 b/test/regress/regress0/rewriterules/simulate_rewriting.smt2
new file mode 100644 (file)
index 0000000..d1d88a5
--- /dev/null
@@ -0,0 +1,24 @@
+;; A new fast tableau-base ... Domenico Cantone et Calogero G.Zarba
+(set-logic AUFLIA)
+(set-info :status sat)
+
+(declare-sort elt1 0)
+(declare-sort elt2 0)
+
+(declare-fun g (elt2) Bool)
+
+(declare-fun p (elt1 elt1) Bool)
+(declare-fun f (elt2) elt1)
+(declare-fun c1 () elt1)
+(declare-fun c2 () elt1)
+
+(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c2)) :rewrite-rule)))
+(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c1)) :rewrite-rule)))
+
+(declare-fun e () elt2)
+
+(assert (not (=> (g e) (=> (p c1 c2) (p (f e) (f e)))) ))
+
+(check-sat)
+
+(exit)
diff --git a/test/regress/regress0/rewriterules/simulate_rewritting.smt2 b/test/regress/regress0/rewriterules/simulate_rewritting.smt2
deleted file mode 100644 (file)
index d1d88a5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-;; A new fast tableau-base ... Domenico Cantone et Calogero G.Zarba
-(set-logic AUFLIA)
-(set-info :status sat)
-
-(declare-sort elt1 0)
-(declare-sort elt2 0)
-
-(declare-fun g (elt2) Bool)
-
-(declare-fun p (elt1 elt1) Bool)
-(declare-fun f (elt2) elt1)
-(declare-fun c1 () elt1)
-(declare-fun c2 () elt1)
-
-(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c2)) :rewrite-rule)))
-(assert (forall ((?e elt2)) (! (=> (g ?e) (= (f ?e) c1)) :rewrite-rule)))
-
-(declare-fun e () elt2)
-
-(assert (not (=> (g e) (=> (p c1 c2) (p (f e) (f e)))) ))
-
-(check-sat)
-
-(exit)