Fix case where RE unfolding generates a trivially true lemma (#6267)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Fri, 2 Apr 2021 16:43:53 +0000 (11:43 -0500)
committerGitHub <noreply@github.com>
Fri, 2 Apr 2021 16:43:53 +0000 (16:43 +0000)
An RE unfolding lemma may rewrite to true for tautological RE memberships that our rewriter does not rewrite the membership to true.

An example is (str.in_re x (re.* (re.union (str.to_re "A") (str.to_re x))).

This PR ensures we are robust to these cases.

This fixes benchmarks 3-5 from #6203. Benchmark 3 is added here, 4-5 time out.

src/theory/strings/regexp_solver.cpp
test/regress/CMakeLists.txt
test/regress/regress0/strings/issue6203-3-unfold-trivial-true.smt2 [new file with mode: 0644]

index 7737a90f7d43be3bd1d937d6d84800cff2f815cb..0db536d1b3e78258280dbb9cd97654ee591aaab4 100644 (file)
@@ -284,16 +284,21 @@ void RegExpSolver::check(const std::map<Node, std::vector<Node> >& mems)
             }
             InferenceId inf =
                 polarity ? InferenceId::STRINGS_RE_UNFOLD_POS : InferenceId::STRINGS_RE_UNFOLD_NEG;
-            d_im.sendInference(iexp, noExplain, conc, inf);
-            addedLemma = true;
-            processed.push_back(assertion);
-            if (e == 0)
+            // in very rare cases, we may find out that the unfolding lemma
+            // for a membership is equivalent to true, in spite of the RE
+            // not being rewritten to true.
+            if (d_im.sendInference(iexp, noExplain, conc, inf))
             {
-              // Remember that we have unfolded a membership for x
-              // notice that we only do this here, after we have definitely
-              // added a lemma.
-              repUnfold.insert(rep);
+              addedLemma = true;
+              if (e == 0)
+              {
+                // Remember that we have unfolded a membership for x
+                // notice that we only do this here, after we have definitely
+                // added a lemma.
+                repUnfold.insert(rep);
+              }
             }
+            processed.push_back(assertion);
           }
           else
           {
index 64c584f7a4f631e6e1602430d20d1151437c5c61..81c2bdba3a39521e4a4cc537020038e45a08039b 100644 (file)
@@ -1111,6 +1111,7 @@ set(regress_0_tests
   regress0/strings/issue5771-eager-pp.smt2
   regress0/strings/issue5816-re-kind.smt2
   regress0/strings/issue5915-repl-ctn-rewrite.smt2
+  regress0/strings/issue6203-3-unfold-trivial-true.smt2
   regress0/strings/itos-entail.smt2
   regress0/strings/large-model.smt2
   regress0/strings/leadingzero001.smt2
diff --git a/test/regress/regress0/strings/issue6203-3-unfold-trivial-true.smt2 b/test/regress/regress0/strings/issue6203-3-unfold-trivial-true.smt2
new file mode 100644 (file)
index 0000000..1ef762d
--- /dev/null
@@ -0,0 +1,7 @@
+; COMMAND-LINE: --strings-exp
+; EXPECT: sat
+(set-logic ALL)
+(declare-fun s () String)
+(assert (str.in_re s (re.* (re.union (str.to_re "A") (str.to_re s)))))
+(assert (not (str.in_re s (re.* (re.opt (re.comp (str.to_re "A")))))))
+(check-sat)