Run preprocess rewrite on equalities until fixed point (#8291)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Mon, 14 Mar 2022 16:56:52 +0000 (11:56 -0500)
committerGitHub <noreply@github.com>
Mon, 14 Mar 2022 16:56:52 +0000 (16:56 +0000)
Previously we were only running once, while strings assumed this was run on what it returned.

This should significantly improve our performance on the benchmarks from SMT-LIB that involving looping word equations.

src/preprocessing/passes/theory_rewrite_eq.cpp
test/regress/CMakeLists.txt
test/regress/regress0/strings/quad-138-4-2-unsat.smt2 [new file with mode: 0644]

index 93ba2b7cdb3450e0f5d82306d8127c88b21d1800..782d4569de7aa52f7cad82a6a2ef0a148ca1619c 100644 (file)
@@ -50,6 +50,7 @@ TrustNode TheoryRewriteEq::rewriteAssertion(TNode n)
   NodeManager* nm = NodeManager::currentNM();
   TheoryEngine* te = d_preprocContext->getTheoryEngine();
   std::unordered_map<TNode, Node> visited;
+  std::unordered_map<TNode, Node> rewrittenTo;
   std::unordered_map<TNode, Node>::iterator it;
   std::vector<TNode> visit;
   TNode cur;
@@ -57,24 +58,32 @@ TrustNode TheoryRewriteEq::rewriteAssertion(TNode n)
   do
   {
     cur = visit.back();
-    visit.pop_back();
     it = visited.find(cur);
 
     if (it == visited.end())
     {
       if (cur.getNumChildren()==0)
       {
+        visit.pop_back();
         visited[cur] = cur;
       }
       else
       {
         visited[cur] = Node::null();
-        visit.push_back(cur);
         visit.insert(visit.end(), cur.begin(), cur.end());
       }
     }
     else if (it->second.isNull())
     {
+      it = rewrittenTo.find(cur);
+      if (it != rewrittenTo.end())
+      {
+        // rewritten form is the rewritten form of what it was rewritten to
+        Assert(visited.find(it->second) != visited.end());
+        visited[cur] = visited[it->second];
+        visit.pop_back();
+        continue;
+      }
       Node ret = cur;
       bool childChanged = false;
       std::vector<Node> children;
@@ -94,14 +103,32 @@ TrustNode TheoryRewriteEq::rewriteAssertion(TNode n)
       {
         ret = nm->mkNode(cur.getKind(), children);
       }
+      bool wasRewritten = false;
       if (ret.getKind() == kind::EQUAL && !ret[0].getType().isBoolean())
       {
         // For example, (= x y) ---> (and (>= x y) (<= x y))
         TrustNode trn = te->ppRewriteEquality(ret);
         // can make proof producing by using proof generator from trn
-        ret = trn.isNull() ? Node(ret) : trn.getNode();
+        if (!trn.isNull() && trn.getNode() != ret)
+        {
+          Trace("pp-rewrite-eq") << "Rewrite equality " << ret << " to "
+                                 << trn.getNode() << std::endl;
+          wasRewritten = true;
+          Node retr = trn.getNode();
+          rewrittenTo[cur] = retr;
+          rewrittenTo[ret] = retr;
+          visit.push_back(retr);
+        }
+      }
+      if (!wasRewritten)
+      {
+        visit.pop_back();
+        visited[cur] = ret;
       }
-      visited[cur] = ret;
+    }
+    else
+    {
+      visit.pop_back();
     }
   } while (!visit.empty());
   Assert(visited.find(n) != visited.end());
index 6b73f506e1185e8cbc9847af5c3b363baa35ec43..ba1ebb1af5252f4fae725e86df1ae1605f8a3655 100644 (file)
@@ -1379,6 +1379,8 @@ set(regress_0_tests
   regress0/strings/proj-issue316-regexp-ite.smt2
   regress0/strings/proj-issue390-update-rev-rewrite.smt2
   regress0/strings/proj-issue409-re-loop-none.smt2
+  regress0/strings/quad-028-2-2-unsat.smt2
+  regress0/strings/quad-138-4-2-unsat.smt2
   regress0/strings/re_diff.smt2
   regress0/strings/re-in-rewrite.smt2
   regress0/strings/re-syntax.smt2
@@ -3032,8 +3034,6 @@ set(regression_disabled_tests
   regress0/bv/test00.smtv1.smt2
   # timeout after fixing upwards closure for relations
   regress0/rels/rel_tc_7.cvc.smt2
-  # timeout after changes to equality rewriting policy in strings
-  regress0/strings/quad-028-2-2-unsat.smt2
   # FIXME #1649
   regress0/datatypes/datatype-dump.cvc.smt2
   # no longer support overloaded symbols across multiple parametric datatypes
diff --git a/test/regress/regress0/strings/quad-138-4-2-unsat.smt2 b/test/regress/regress0/strings/quad-138-4-2-unsat.smt2
new file mode 100644 (file)
index 0000000..249ae26
--- /dev/null
@@ -0,0 +1,11 @@
+(set-info :smt-lib-version 2.6)
+(set-logic QF_SLIA)
+(set-info :status unsat)
+(declare-fun  x1 () String )
+(declare-fun  x2 () String )
+(declare-fun  z1 () String )
+(declare-fun  z2 () String )
+(declare-fun  t1 () String )
+(declare-fun  t2 () String )
+(assert ( =( str.++( str.++( str.++( str.++ x1  "abdc"  )  x2  ) ( str.++ "ac"  z1  )  ) ( str.++( str.++ "cd"  z2  )  t2  )  ) ( str.++( str.++( str.++( str.++ x2  "dcba"  )  x1  ) ( str.++ z1  "ba"  )  ) ( str.++( str.++ z2  "dc"  )  t1  )  )  ) )
+(check-sat)