diff options
author | Andrew Reynolds <andrew.j.reynolds@gmail.com> | 2018-10-10 20:53:00 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-10 20:53:00 -0500 |
commit | 308d47325ea00350d6f4475bf9156e339d4b2d36 (patch) | |
tree | eddc0d60a57df5e55ed18a1032ee4a95fcbcf8b7 /src/theory/strings/regexp_elim.cpp | |
parent | 4bca88ced88af4db8b79d6e924516a7c22168391 (diff) | |
parent | 7d70b721f43157e01bc6166a822df79250df632a (diff) |
Merge branch 'master' into miscWarnsmiscWarns
Diffstat (limited to 'src/theory/strings/regexp_elim.cpp')
-rw-r--r-- | src/theory/strings/regexp_elim.cpp | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/src/theory/strings/regexp_elim.cpp b/src/theory/strings/regexp_elim.cpp index 8ea26fca9..0310e4620 100644 --- a/src/theory/strings/regexp_elim.cpp +++ b/src/theory/strings/regexp_elim.cpp @@ -104,18 +104,21 @@ Node RegExpElimination::eliminateConcat(Node atom) // prev_end stores the current (symbolic) index in x that we are // searching. Node prev_end = d_zero; + // the symbolic index we start searching, for each child in sep_children. + std::vector<Node> prev_ends; unsigned gap_minsize_end = gap_minsize.back(); bool gap_exact_end = gap_exact.back(); std::vector<Node> non_greedy_find_vars; for (unsigned i = 0, size = sep_children.size(); i < size; i++) { - Node sc = sep_children[i]; if (gap_minsize[i] > 0) { // the gap to this child is at least gap_minsize[i] prev_end = nm->mkNode(PLUS, prev_end, nm->mkConst(Rational(gap_minsize[i]))); } + prev_ends.push_back(prev_end); + Node sc = sep_children[i]; Node lensc = nm->mkNode(STRING_LENGTH, sc); if (gap_exact[i]) { @@ -169,7 +172,6 @@ Node RegExpElimination::eliminateConcat(Node atom) Node lenSc = nm->mkNode(STRING_LENGTH, sc); Node loc = nm->mkNode(MINUS, lenx, nm->mkNode(PLUS, lenSc, cEnd)); Node scc = sc.eqNode(nm->mkNode(STRING_SUBSTR, x, loc, lenSc)); - conj.push_back(scc); // We also must ensure that we fit. This constraint is necessary in // addition to the constraint above. Take this example: // x in (re.++ "A" _ (re.* _) "B" _) ---> @@ -182,9 +184,23 @@ Node RegExpElimination::eliminateConcat(Node atom) // would have been the case than "ABB" would be a model for x, where // the second constraint refers to the third position, and the third // constraint refers to the second position. + // + // With respect to the above example, the following is an optimization. + // For that example, we instead produce: + // x in (re.++ "A" _ (re.* _) "B" _) ---> + // substr( x, 0, 1 ) = "A" ^ // find "A" + // substr( x, len(x)-2, 1 ) = "B" ^ // "B" is at end - 2 + // 2 <= len( x ) - 2 + // The intuition is that above, there are two constraints that insist + // that "B" is found, whereas we only need one. The last constraint + // above says that the "B" we find at end-2 can be found >=1 after + // the "A". + conj.pop_back(); Node fit = nm->mkNode(gap_exact[sep_children.size() - 1] ? EQUAL : LEQ, - nm->mkNode(MINUS, prev_end, lenSc), + prev_ends.back(), loc); + + conj.push_back(scc); conj.push_back(fit); } else if (gap_minsize_end > 0) |