sygusComp2018: simplify beta reduction in uf rewriter. (#2106)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 6 Jul 2018 07:20:23 +0000 (08:20 +0100)
committerAndres Noetzli <andres.noetzli@gmail.com>
Fri, 6 Jul 2018 07:20:23 +0000 (00:20 -0700)
This is PR 8/18 from the sygus comp 2018 branch (https://github.com/ajreynol/CVC4/tree/sygusComp2018-2).

I am not sure how it is possible in any circumstance that the complication in the comment I am deleting would ever happen, without doing something very strange. I think it is referring to some sort of inter-dependence between macro expansion + beta-reductions. This should not concern the rewriter. Here is the commit that introduced it: bdaa304.

src/theory/uf/theory_uf_rewriter.h

index 92bfd6647429a2978c335b6239aff8c04ddeb5b8..3eb59e5fcf6f2cc6665d5b26e4603a8d03c1db40 100644 (file)
@@ -46,32 +46,20 @@ public:
     }
     if(node.getKind() == kind::APPLY_UF) {
       if( node.getOperator().getKind() == kind::LAMBDA ){
-        // resolve away the lambda
-        context::Context fakeContext;
-        theory::SubstitutionMap substitutions(&fakeContext);
         TNode lambda = node.getOperator();
-        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.)
-          Node n = Rewriter::rewrite(*arg);
-          substitutions.addSubstitution(*formal, n);
+        std::vector<TNode> vars;
+        std::vector<TNode> subs;
+        for (const TNode& v : lambda[0])
+        {
+          vars.push_back(v);
         }
-        return RewriteResponse(REWRITE_AGAIN_FULL, substitutions.apply(lambda[1]));
+        for (const TNode& s : node)
+        {
+          subs.push_back(s);
+        }
+        Node ret = lambda[1].substitute(
+            vars.begin(), vars.end(), subs.begin(), subs.end());
+        return RewriteResponse(REWRITE_AGAIN_FULL, ret);
       }else if( !canUseAsApplyUfOperator( node.getOperator() ) ){
         return RewriteResponse(REWRITE_AGAIN_FULL, getHoApplyForApplyUf(node));
       }
@@ -106,20 +94,6 @@ public:
         return RewriteResponse(REWRITE_DONE, NodeManager::currentNM()->mkConst(false));
       }
     }
-    if(node.getKind() == kind::APPLY_UF && node.getOperator().getKind() == kind::LAMBDA) {
-      // resolve away the lambda
-      context::Context fakeContext;
-      theory::SubstitutionMap substitutions(&fakeContext);
-      TNode lambda = node.getOperator();
-      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: see note in postRewrite().
-        Node n = Rewriter::rewrite(*arg);
-        substitutions.addSubstitution(*formal, n);
-      }
-      return RewriteResponse(REWRITE_DONE, substitutions.apply(lambda[1]));
-    }
     return RewriteResponse(REWRITE_DONE, node);
   }