summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2018-10-18 12:51:42 -0500
committerGitHub <noreply@github.com>2018-10-18 12:51:42 -0500
commit10707e3ec6f2cab793919f2d1a159e13cdd032a9 (patch)
tree334b2abb90413d17bb60dec68f81e4f520a698fe
parentb9fed18079d1dca67739796bf1110268c070c307 (diff)
Non-contributing find replace rewrite (#2652)
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp47
-rw-r--r--test/regress/CMakeLists.txt1
-rw-r--r--test/regress/regress0/strings/ncontrib-rewrites.smt215
3 files changed, 63 insertions, 0 deletions
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index c38a5e838..7c008dc14 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -2845,6 +2845,53 @@ Node TheoryStringsRewriter::rewriteReplace( Node node ) {
}
}
}
+ // miniscope based on components that do not contribute to contains
+ // for example,
+ // str.replace( x ++ y ++ x ++ y, "A", z ) -->
+ // str.replace( x ++ y, "A", z ) ++ x ++ y
+ // since if "A" occurs in x ++ y ++ x ++ y, then it must occur in x ++ y.
+ if (node[1].isConst() && node[1].getConst<String>().size() == 1)
+ {
+ Node lastLhs;
+ unsigned lastCheckIndex = 0;
+ for (unsigned i = 1, iend = children0.size(); i < iend; i++)
+ {
+ unsigned checkIndex = children0.size() - i;
+ std::vector<Node> checkLhs;
+ checkLhs.insert(
+ checkLhs.end(), children0.begin(), children0.begin() + checkIndex);
+ Node lhs = mkConcat(STRING_CONCAT, checkLhs);
+ Node rhs = children0[checkIndex];
+ Node ctn = nm->mkNode(STRING_STRCTN, lhs, rhs);
+ ctn = Rewriter::rewrite(ctn);
+ if (ctn.isConst() && ctn.getConst<bool>())
+ {
+ lastLhs = lhs;
+ lastCheckIndex = checkIndex;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (!lastLhs.isNull())
+ {
+ std::vector<Node> remc(children0.begin() + lastCheckIndex,
+ children0.end());
+ Node rem = mkConcat(STRING_CONCAT, remc);
+ Node ret =
+ nm->mkNode(STRING_CONCAT,
+ nm->mkNode(STRING_STRREPL, lastLhs, node[1], node[2]),
+ rem);
+ // for example:
+ // str.replace( x ++ x, "A", y ) ---> str.replace( x, "A", y ) ++ x
+ // Since we know that the first occurrence of "A" cannot be in the
+ // second occurrence of x. Notice this is specific to single characters
+ // due to complications with finds that span multiple components for
+ // non-characters.
+ return returnRewrite(node, ret, "repl-char-ncontrib-find");
+ }
+ }
// TODO (#1180) incorporate these?
// contains( t, s ) =>
diff --git a/test/regress/CMakeLists.txt b/test/regress/CMakeLists.txt
index 59edb6986..a41108a71 100644
--- a/test/regress/CMakeLists.txt
+++ b/test/regress/CMakeLists.txt
@@ -807,6 +807,7 @@ set(regress_0_tests
regress0/strings/leadingzero001.smt2
regress0/strings/loop001.smt2
regress0/strings/model001.smt2
+ regress0/strings/ncontrib-rewrites.smt2
regress0/strings/norn-31.smt2
regress0/strings/norn-simp-rew.smt2
regress0/strings/repl-rewrites2.smt2
diff --git a/test/regress/regress0/strings/ncontrib-rewrites.smt2 b/test/regress/regress0/strings/ncontrib-rewrites.smt2
new file mode 100644
index 000000000..6b2e68794
--- /dev/null
+++ b/test/regress/regress0/strings/ncontrib-rewrites.smt2
@@ -0,0 +1,15 @@
+(set-logic ALL)
+(set-info :status unsat)
+(declare-fun x () String)
+(declare-fun y () String)
+(declare-fun z () String)
+
+(assert (or
+
+(not (= (str.replace (str.++ x x) "A" "B") (str.replace x "" (str.replace x "A" "B"))))
+
+(not (= (str.replace (str.++ x y "B" x y) "A" z) (str.++ (str.replace (str.++ x y) "A" z) "B" x y)))
+
+))
+
+(check-sat)
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback