mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 06:03:23 +00:00
add integer theory integration to theory_str::solve_concat_eq_str case 4
This commit is contained in:
parent
778c0a5563
commit
6e348720b1
1 changed files with 77 additions and 19 deletions
|
@ -4555,12 +4555,74 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
||||||
} else {
|
} else {
|
||||||
// Case 4: Concat(var, var) == const
|
// Case 4: Concat(var, var) == const
|
||||||
TRACE("t_str", tout << "Case 4: Concat(var, var) == const" << std::endl;);
|
TRACE("t_str", tout << "Case 4: Concat(var, var) == const" << std::endl;);
|
||||||
// TODO large additions required in this section
|
if (eval_concat(arg1, arg2) == NULL) {
|
||||||
if (true) { /* if (Concat(arg1, arg2) == NULL) { */
|
rational arg1Len, arg2Len;
|
||||||
int arg1Len = -1; /* = getLenValue(arg1); */
|
bool arg1Len_exists = get_len_value(arg1, arg1Len);
|
||||||
int arg2Len = -1; /* = getLenValue(arg2); */
|
bool arg2Len_exists = get_len_value(arg2, arg2Len);
|
||||||
if (arg1Len != -1 || arg2Len != -1) {
|
rational concatStrLen((unsigned)const_str.length());
|
||||||
NOT_IMPLEMENTED_YET(); // TODO
|
if (arg1Len_exists || arg2Len_exists) {
|
||||||
|
expr_ref ax_l1(ctx.mk_eq_atom(concat, str), m);
|
||||||
|
expr_ref ax_l2(m);
|
||||||
|
std::string prefixStr, suffixStr;
|
||||||
|
if (arg1Len_exists) {
|
||||||
|
if (arg1Len.is_neg()) {
|
||||||
|
TRACE("t_str_detail", tout << "length conflict: arg1Len = " << arg1Len << ", concatStrLen = " << concatStrLen << std::endl;);
|
||||||
|
expr_ref toAssert(m_autil.mk_ge(mk_strlen(arg1), mk_int(0)), m);
|
||||||
|
assert_axiom(toAssert);
|
||||||
|
return;
|
||||||
|
} else if (arg1Len > concatStrLen) {
|
||||||
|
TRACE("t_str_detail", tout << "length conflict: arg1Len = " << arg1Len << ", concatStrLen = " << concatStrLen << std::endl;);
|
||||||
|
expr_ref ax_r1(m_autil.mk_le(mk_strlen(arg1), mk_int(concatStrLen)), m);
|
||||||
|
assert_implication(ax_l1, ax_r1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixStr = const_str.substr(0, arg1Len.get_unsigned());
|
||||||
|
rational concat_minus_arg1 = concatStrLen - arg1Len;
|
||||||
|
suffixStr = const_str.substr(arg1Len.get_unsigned(), concat_minus_arg1.get_unsigned());
|
||||||
|
ax_l2 = ctx.mk_eq_atom(mk_strlen(arg1), mk_int(arg1Len));
|
||||||
|
} else {
|
||||||
|
// arg2's length is available
|
||||||
|
if (arg2Len.is_neg()) {
|
||||||
|
TRACE("t_str_detail", tout << "length conflict: arg2Len = " << arg2Len << ", concatStrLen = " << concatStrLen << std::endl;);
|
||||||
|
expr_ref toAssert(m_autil.mk_ge(mk_strlen(arg2), mk_int(0)), m);
|
||||||
|
assert_axiom(toAssert);
|
||||||
|
return;
|
||||||
|
} else if (arg2Len > concatStrLen) {
|
||||||
|
TRACE("t_str_detail", tout << "length conflict: arg2Len = " << arg2Len << ", concatStrLen = " << concatStrLen << std::endl;);
|
||||||
|
expr_ref ax_r1(m_autil.mk_le(mk_strlen(arg2), mk_int(concatStrLen)), m);
|
||||||
|
assert_implication(ax_l1, ax_r1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rational concat_minus_arg2 = concatStrLen - arg2Len;
|
||||||
|
prefixStr = const_str.substr(0, concat_minus_arg2.get_unsigned());
|
||||||
|
suffixStr = const_str.substr(concat_minus_arg2.get_unsigned(), arg2Len.get_unsigned());
|
||||||
|
ax_l2 = ctx.mk_eq_atom(mk_strlen(arg2), mk_int(arg2Len));
|
||||||
|
}
|
||||||
|
// consistency check
|
||||||
|
if (is_concat(to_app(arg1)) && !can_concat_eq_str(arg1, prefixStr)) {
|
||||||
|
expr_ref ax_r(m.mk_not(ax_l2), m);
|
||||||
|
assert_implication(ax_l1, ax_r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_concat(to_app(arg2)) && !can_concat_eq_str(arg2, suffixStr)) {
|
||||||
|
expr_ref ax_r(m.mk_not(ax_l2), m);
|
||||||
|
assert_implication(ax_l1, ax_r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expr_ref_vector r_items(m);
|
||||||
|
r_items.push_back(ctx.mk_eq_atom(arg1, m_strutil.mk_string(prefixStr)));
|
||||||
|
r_items.push_back(ctx.mk_eq_atom(arg2, m_strutil.mk_string(suffixStr)));
|
||||||
|
if (!arg1Len_exists) {
|
||||||
|
r_items.push_back(ctx.mk_eq_atom(mk_strlen(arg1), mk_int(prefixStr.size())));
|
||||||
|
}
|
||||||
|
if (!arg2Len_exists) {
|
||||||
|
r_items.push_back(ctx.mk_eq_atom(mk_strlen(arg2), mk_int(suffixStr.size())));
|
||||||
|
}
|
||||||
|
expr_ref lhs(m.mk_and(ax_l1, ax_l2), m);
|
||||||
|
expr_ref rhs(mk_and(r_items), m);
|
||||||
|
assert_implication(lhs, rhs);
|
||||||
} else { /* ! (arg1Len != 1 || arg2Len != 1) */
|
} else { /* ! (arg1Len != 1 || arg2Len != 1) */
|
||||||
expr_ref xorFlag(m);
|
expr_ref xorFlag(m);
|
||||||
std::pair<expr*, expr*> key1(arg1, arg2);
|
std::pair<expr*, expr*> key1(arg1, arg2);
|
||||||
|
@ -4569,6 +4631,8 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
||||||
// check the entries in this map to make sure they're still in scope
|
// check the entries in this map to make sure they're still in scope
|
||||||
// before we use them.
|
// before we use them.
|
||||||
|
|
||||||
|
// TODO XOR variables will always show up as "not in scope" because of how we update internal_variable_set
|
||||||
|
|
||||||
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry1 = varForBreakConcat.find(key1);
|
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry1 = varForBreakConcat.find(key1);
|
||||||
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry2 = varForBreakConcat.find(key2);
|
std::map<std::pair<expr*,expr*>, std::map<int, expr*> >::iterator entry2 = varForBreakConcat.find(key2);
|
||||||
|
|
||||||
|
@ -4609,10 +4673,7 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
||||||
int concatStrLen = const_str.length();
|
int concatStrLen = const_str.length();
|
||||||
int xor_pos = 0;
|
int xor_pos = 0;
|
||||||
int and_count = 1;
|
int and_count = 1;
|
||||||
/*
|
|
||||||
expr ** xor_items = new expr*[concatStrLen + 1];
|
|
||||||
expr ** and_items = new expr*[4 * (concatStrLen+1) + 1];
|
|
||||||
*/
|
|
||||||
expr ** xor_items = alloc_svect(expr*, (concatStrLen+1));
|
expr ** xor_items = alloc_svect(expr*, (concatStrLen+1));
|
||||||
expr ** and_items = alloc_svect(expr*, (4 * (concatStrLen+1) + 1));
|
expr ** and_items = alloc_svect(expr*, (4 * (concatStrLen+1) + 1));
|
||||||
|
|
||||||
|
@ -4620,15 +4681,12 @@ void theory_str::solve_concat_eq_str(expr * concat, expr * str) {
|
||||||
std::string prefixStr = const_str.substr(0, i);
|
std::string prefixStr = const_str.substr(0, i);
|
||||||
std::string suffixStr = const_str.substr(i, concatStrLen - i);
|
std::string suffixStr = const_str.substr(i, concatStrLen - i);
|
||||||
// skip invalid options
|
// skip invalid options
|
||||||
// TODO canConcatEqStr() checks:
|
if (is_concat(to_app(arg1)) && !can_concat_eq_str(arg1, prefixStr)) {
|
||||||
/*
|
continue;
|
||||||
if (isConcatFunc(t, arg1) && canConcatEqStr(t, arg1, prefixStr) == 0) {
|
}
|
||||||
continue;
|
if (is_concat(to_app(arg2)) && !can_concat_eq_str(arg2, suffixStr)) {
|
||||||
}
|
continue;
|
||||||
if (isConcatFunc(t, arg2) && canConcatEqStr(t, arg2, suffixStr) == 0) {
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
expr_ref xorAst(ctx.mk_eq_atom(xorFlag, m_autil.mk_numeral(rational(xor_pos), true)), m);
|
expr_ref xorAst(ctx.mk_eq_atom(xorFlag, m_autil.mk_numeral(rational(xor_pos), true)), m);
|
||||||
xor_items[xor_pos++] = xorAst;
|
xor_items[xor_pos++] = xorAst;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue