summaryrefslogtreecommitdiff
path: root/src/theory/strings
diff options
context:
space:
mode:
authorAndres Noetzli <andres.noetzli@gmail.com>2018-10-10 12:30:06 -0700
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>2018-10-10 14:30:06 -0500
commit71bd93b9e073cb9d7d8e14eb5b279f29d45c1019 (patch)
tree12342caef5fa97fc9f6dd44c6cb97520c6bc401e /src/theory/strings
parent9168f325706e61bb12fec71cd375647e2102f8d3 (diff)
Add length-based rewrites for (str.substr _ _ _) (#2610)
Diffstat (limited to 'src/theory/strings')
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index b2778298a..00a711a31 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -1610,6 +1610,33 @@ Node TheoryStringsRewriter::rewriteSubstr(Node node)
return returnRewrite(node, ret, "ss-len-non-pos");
}
+ if (node[0].getKind() == STRING_SUBSTR)
+ {
+ // (str.substr (str.substr x a b) c d) ---> "" if c >= b
+ //
+ // Note that this rewrite can be generalized to:
+ //
+ // (str.substr x a b) ---> "" if a >= (str.len x)
+ //
+ // This can be done when we generalize our entailment methods to
+ // accept an optional context. Then we could conjecture that
+ // (str.substr x a b) rewrites to "" and do a case analysis:
+ //
+ // - a < 0 or b < 0 (the result is trivially empty in these cases)
+ // - a >= (str.len x) assuming that { a >= 0, b >= 0 }
+ //
+ // For example, for (str.substr (str.substr x a a) a a), we could
+ // then deduce that under those assumptions, "a" is an
+ // over-approximation of the length of (str.substr x a a), which
+ // then allows us to reason that the result of the whole term must
+ // be empty.
+ if (checkEntailArith(node[1], node[0][2]))
+ {
+ Node ret = nm->mkConst(::CVC4::String(""));
+ return returnRewrite(node, ret, "ss-start-geq-len");
+ }
+ }
+
std::vector<Node> n1;
getConcat(node[0], n1);
@@ -1673,6 +1700,14 @@ Node TheoryStringsRewriter::rewriteSubstr(Node node)
Node ret = nm->mkConst(::CVC4::String(""));
return returnRewrite(node, ret, "ss-start-entails-zero-len");
}
+
+ // (str.substr s x x) ---> "" if (str.len s) <= 1
+ Node one = nm->mkConst(CVC4::Rational(1));
+ if (node[1] == node[2] && checkEntailArith(one, tot_len))
+ {
+ Node ret = nm->mkConst(::CVC4::String(""));
+ return returnRewrite(node, ret, "ss-len-one-z-z");
+ }
}
if (!curr.isNull())
{
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback