3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-18 02:16:40 +00:00
This commit is contained in:
Nikolaj Bjorner 2015-12-08 03:35:03 -08:00
commit 2b190039d5
16 changed files with 645 additions and 53 deletions

View file

@ -20,6 +20,7 @@ Notes:
#include"seq_rewriter.h"
#include"arith_decl_plugin.h"
#include"ast_pp.h"
#include"ast_util.h"
br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
@ -187,6 +188,21 @@ br_status seq_rewriter::mk_str_strctn(expr* a, expr* b, expr_ref& result) {
result = m().mk_bool_val(0 != strstr(d.c_str(), c.c_str()));
return BR_DONE;
}
// check if subsequence of a is in b.
ptr_vector<expr> as, bs;
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
bool found = false;
for (unsigned i = 0; !found && i < bs.size(); ++i) {
if (as.size() > bs.size() - i) break;
unsigned j = 0;
for (; j < as.size() && as[j] == bs[i+j]; ++j) {};
found = j == as.size();
}
if (found) {
result = m().mk_true();
return BR_DONE;
}
return BR_FAILED;
}
@ -261,6 +277,7 @@ br_status seq_rewriter::mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& resu
}
br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
TRACE("seq", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << "\n";);
std::string s1, s2;
bool isc1 = m_util.str.is_string(a, s1);
bool isc2 = m_util.str.is_string(b, s2);
@ -276,24 +293,177 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
result = m().mk_true();
return BR_DONE;
}
expr* a1 = m_util.str.get_leftmost_concat(a);
expr* b1 = m_util.str.get_leftmost_concat(b);
isc1 = m_util.str.is_string(a1, s1);
isc2 = m_util.str.is_string(b1, s2);
ptr_vector<expr> as, bs;
if (a1 != b1 && isc1 && isc2) {
if (s1.length() <= s2.length()) {
if (strncmp(s1.c_str(), s2.c_str(), s1.length()) == 0) {
if (a == a1) {
result = m().mk_true();
return BR_DONE;
}
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
SASSERT(as.size() > 1);
s2 = std::string(s2.c_str() + s1.length(), s2.length() - s1.length());
bs[0] = m_util.str.mk_string(s2);
result = m_util.str.mk_prefix(m_util.str.mk_concat(as.size()-1, as.c_ptr()+1),
m_util.str.mk_concat(bs.size(), bs.c_ptr()));
return BR_REWRITE_FULL;
}
else {
result = m().mk_false();
return BR_DONE;
}
}
else {
if (strncmp(s1.c_str(), s2.c_str(), s2.length()) == 0) {
if (b == b1) {
result = m().mk_false();
return BR_DONE;
}
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
SASSERT(bs.size() > 1);
s1 = std::string(s1.c_str() + s2.length(), s1.length() - s2.length());
as[0] = m_util.str.mk_string(s1);
result = m_util.str.mk_prefix(m_util.str.mk_concat(as.size(), as.c_ptr()),
m_util.str.mk_concat(bs.size()-1, bs.c_ptr()+1));
return BR_REWRITE_FULL;
}
else {
result = m().mk_false();
return BR_DONE;
}
}
}
if (a1 != b1) {
return BR_FAILED;
}
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
unsigned i = 0;
for (; i < as.size() && i < bs.size() && as[i] == bs[i]; ++i) {};
if (i == as.size()) {
result = m().mk_true();
return BR_DONE;
}
if (i == bs.size()) {
expr_ref_vector es(m());
for (unsigned j = i; j < as.size(); ++j) {
es.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j]));
}
result = mk_and(es);
return BR_REWRITE3;
}
if (i > 0) {
a = m_util.str.mk_concat(as.size() - i, as.c_ptr() + i);
b = m_util.str.mk_concat(bs.size() - i, bs.c_ptr() + i);
result = m_util.str.mk_prefix(a, b);
return BR_DONE;
}
UNREACHABLE();
return BR_FAILED;
}
br_status seq_rewriter::mk_seq_suffix(expr* a, expr* b, expr_ref& result) {
std::string s1, s2;
bool isc1 = m_util.str.is_string(a, s1);
if (isc1 && m_util.str.is_string(b, s2)) {
bool suffix = s1.length() <= s2.length();
for (unsigned i = 0; i < s1.length() && suffix; ++i) {
suffix = s1[s1.length() - i - 1] == s2[s2.length() - i - 1];
}
result = m().mk_bool_val(suffix);
if (a == b) {
result = m().mk_true();
return BR_DONE;
}
std::string s1, s2;
if (m_util.str.is_empty(a)) {
result = m().mk_true();
return BR_DONE;
}
if (m_util.str.is_empty(b)) {
result = m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), a);
return BR_REWRITE3;
}
// concatenation is left-associative, so a2, b2 are not concatenations
expr* a1, *a2, *b1, *b2;
if (m_util.str.is_concat(a, a1, a2) &&
m_util.str.is_concat(b, b1, b2) && a2 == b2) {
result = m_util.str.mk_suffix(a1, b1);
return BR_REWRITE1;
}
if (m_util.str.is_concat(b, b1, b2) && b2 == a) {
result = m().mk_true();
return BR_DONE;
}
bool isc1 = false;
bool isc2 = false;
if (m_util.str.is_concat(a, a1, a2) && m_util.str.is_string(a2, s1)) {
isc1 = true;
}
else if (m_util.str.is_string(a, s1)) {
isc1 = true;
a2 = a;
a1 = 0;
}
if (m_util.str.is_concat(b, b1, b2) && m_util.str.is_string(b2, s2)) {
isc2 = true;
}
else if (m_util.str.is_string(b, s2)) {
isc2 = true;
b2 = b;
b1 = 0;
}
if (isc1 && isc2) {
if (s1.length() == s2.length()) {
SASSERT(s1 != s2);
result = m().mk_false();
return BR_DONE;
}
else if (s1.length() < s2.length()) {
bool suffix = true;
for (unsigned i = 0; i < s1.length(); ++i) {
suffix = s1[s1.length()-i-1] == s2[s2.length()-i-1];
}
if (suffix && a1 == 0) {
result = m().mk_true();
return BR_DONE;
}
else if (suffix) {
s2 = std::string(s2.c_str(), s2.length()-s1.length());
b2 = m_util.str.mk_string(s2);
result = m_util.str.mk_suffix(a1, b1?m_util.str.mk_concat(b1, b2):b2);
return BR_DONE;
}
else {
result = m().mk_false();
return BR_DONE;
}
}
else {
SASSERT(s1.length() > s2.length());
if (b1 == 0) {
result = m().mk_false();
return BR_DONE;
}
bool suffix = true;
for (unsigned i = 0; i < s2.length(); ++i) {
suffix = s1[s1.length()-i-1] == s2[s2.length()-i-1];
}
if (suffix) {
s1 = std::string(s1.c_str(), s1.length()-s2.length());
a2 = m_util.str.mk_string(s1);
result = m_util.str.mk_suffix(a1?m_util.str.mk_concat(a1, a2):a2, b1);
return BR_DONE;
}
else {
result = m().mk_false();
return BR_DONE;
}
}
}
return BR_FAILED;
}