Use total versions of div/mod in re-elim-agg (#2986)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 1 May 2019 05:35:14 +0000 (00:35 -0500)
committerGitHub <noreply@github.com>
Wed, 1 May 2019 05:35:14 +0000 (00:35 -0500)
src/theory/strings/regexp_elim.cpp
test/regress/CMakeLists.txt
test/regress/regress1/strings/re-agg-total1.smt2 [new file with mode: 0644]
test/regress/regress1/strings/re-agg-total2.smt2 [new file with mode: 0644]

index b6a997629df477ccc6575627810c85de9f484e54..e132d8e24e4c0e40a17428d22107bdf7886cf282 100644 (file)
@@ -547,11 +547,13 @@ Node RegExpElimination::eliminateStar(Node atom)
         Node lens = nm->mkNode(STRING_LENGTH, s);
         lens = Rewriter::rewrite(lens);
         Assert(lens.isConst());
+        Assert(lens.getConst<Rational>().sgn() > 0);
         std::vector<Node> conj;
+        // lens is a positive constant, so it is safe to use total div/mod here.
         Node bound = nm->mkNode(
             AND,
             nm->mkNode(LEQ, d_zero, index),
-            nm->mkNode(LT, index, nm->mkNode(INTS_DIVISION, lenx, lens)));
+            nm->mkNode(LT, index, nm->mkNode(INTS_DIVISION_TOTAL, lenx, lens)));
         Node conc =
             nm->mkNode(STRING_SUBSTR, x, nm->mkNode(MULT, index, lens), lens)
                 .eqNode(s);
@@ -559,7 +561,9 @@ Node RegExpElimination::eliminateStar(Node atom)
         Node bvl = nm->mkNode(BOUND_VAR_LIST, index);
         Node res = nm->mkNode(FORALL, bvl, body);
         res = nm->mkNode(
-            AND, nm->mkNode(INTS_MODULUS, lenx, lens).eqNode(d_zero), res);
+            AND,
+            nm->mkNode(INTS_MODULUS_TOTAL, lenx, lens).eqNode(d_zero),
+            res);
         // e.g.
         //    x in ("abc")* --->
         //    forall k. 0 <= k < (len( x ) div 3) => substr(x,3*k,3) = "abc" ^
index 714459a852c5f06549ad4cb80a7b79bfdf785427..8ab86e772ee5ba3e580c05d6bed66bf670b46be5 100644 (file)
@@ -1558,6 +1558,8 @@ set(regress_1_tests
   regress1/strings/nterm-re-inter-sigma.smt2
   regress1/strings/pierre150331.smt2
   regress1/strings/policy_variable.smt2
+  regress1/strings/re-agg-total1.smt2
+  regress1/strings/re-agg-total2.smt2
   regress1/strings/re-elim-exact.smt2
   regress1/strings/re-unsound-080718.smt2
   regress1/strings/regexp001.smt2
diff --git a/test/regress/regress1/strings/re-agg-total1.smt2 b/test/regress/regress1/strings/re-agg-total1.smt2
new file mode 100644 (file)
index 0000000..440a733
--- /dev/null
@@ -0,0 +1,17 @@
+(set-info :smt-lib-version 2.6)
+(set-logic QF_S)
+(set-info :status unsat)
+(set-option :strings-exp true)
+(set-option :re-elim-agg true)
+(declare-const x String)
+(declare-const y String)
+
+
+(assert (str.in.re x (re.* (str.to.re "ab") ) ) )
+(assert (str.in.re x (re.* (str.to.re "abab") ) ) )
+(assert (str.in.re x (re.* (str.to.re "ababac") ) ) )
+
+(assert (> (str.len x)  1) )
+
+(check-sat)
+(get-model)
diff --git a/test/regress/regress1/strings/re-agg-total2.smt2 b/test/regress/regress1/strings/re-agg-total2.smt2
new file mode 100644 (file)
index 0000000..e6e9d49
--- /dev/null
@@ -0,0 +1,13 @@
+(set-info :smt-lib-version 2.6)
+(set-logic ALL)
+(set-info :status unsat)
+(set-option :strings-exp true)
+(set-option :re-elim-agg true)
+(declare-const x String)
+(declare-const y String)
+(assert (str.in.re x (re.* (str.to.re "'\r''k'\n'"))))
+(assert (str.in.re x (re.* (str.to.re "'\r''k'\n''\r''k'\n'"))))
+(assert (> (str.len x) 20))
+(assert (< (str.len x) 25))
+(check-sat)
+(get-model)