3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-20 04:43:39 +00:00

fix expr_ref in theory_str splits WIP

This commit is contained in:
Murphy Berzish 2016-11-18 16:07:20 -05:00
parent 855037eed7
commit 5e37a21802

View file

@ -23,6 +23,8 @@ Revision History:
#include<list> #include<list>
#include<vector> #include<vector>
#include<algorithm> #include<algorithm>
#include "../ast/ast.h"
#include"theory_arith.h" #include"theory_arith.h"
namespace smt { namespace smt {
@ -2834,31 +2836,31 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
// len(x) < len(m) || len(y) > len(n) // len(x) < len(m) || len(y) > len(n)
//-------------------------------------- //--------------------------------------
if (!has_self_cut(m, y)) { if (!has_self_cut(m, y)) {
expr ** ax_l_items = alloc_svect(expr*, 3); expr_ref_vector ax_l_items(mgr);
expr ** ax_r_items = alloc_svect(expr*, 3); expr_ref_vector ax_r_items(mgr);
ax_l_items[0] = ctx.mk_eq_atom(concatAst1, concatAst2); ax_l_items.push_back(ctx.mk_eq_atom(concatAst1, concatAst2));
expr_ref x_t1(mk_concat(x, t1), mgr); expr_ref x_t1(mk_concat(x, t1), mgr);
expr_ref t1_n(mk_concat(t1, n), mgr); expr_ref t1_n(mk_concat(t1, n), mgr);
ax_r_items[0] = ctx.mk_eq_atom(m, x_t1); ax_r_items.push_back(ctx.mk_eq_atom(m, x_t1));
ax_r_items[1] = ctx.mk_eq_atom(y, t1_n); ax_r_items.push_back(ctx.mk_eq_atom(y, t1_n));
if (m_len_exists && x_len_exists) { if (m_len_exists && x_len_exists) {
ax_l_items[1] = ctx.mk_eq_atom(mk_strlen(x), mk_int(x_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(x), mk_int(x_len)));
ax_l_items[2] = ctx.mk_eq_atom(mk_strlen(m), mk_int(m_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(m), mk_int(m_len)));
rational m_sub_x = m_len - x_len; rational m_sub_x = m_len - x_len;
ax_r_items[2] = ctx.mk_eq_atom(mk_strlen(t1), mk_int(m_sub_x)); ax_r_items.push_back(ctx.mk_eq_atom(mk_strlen(t1), mk_int(m_sub_x)));
} else { } else {
ax_l_items[1] = ctx.mk_eq_atom(mk_strlen(y), mk_int(y_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(y), mk_int(y_len)));
ax_l_items[2] = ctx.mk_eq_atom(mk_strlen(n), mk_int(n_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(n), mk_int(n_len)));
rational y_sub_n = y_len - n_len; rational y_sub_n = y_len - n_len;
ax_r_items[2] = ctx.mk_eq_atom(mk_strlen(t1), mk_int(y_sub_n)); ax_r_items.push_back(ctx.mk_eq_atom(mk_strlen(t1), mk_int(y_sub_n)));
} }
expr_ref ax_l(mgr.mk_and(3, ax_l_items), mgr); expr_ref ax_l(mk_and(ax_l_items), mgr);
expr_ref ax_r(mgr.mk_and(3, ax_r_items), mgr); expr_ref ax_r(mk_and(ax_r_items), mgr);
// Cut Info // Cut Info
add_cut_info_merge(t1, sLevel, m); add_cut_info_merge(t1, sLevel, m);
@ -2885,27 +2887,27 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
expr_ref m_t2(mk_concat(m, t2), mgr); expr_ref m_t2(mk_concat(m, t2), mgr);
expr_ref t2_y(mk_concat(t2, y), mgr); expr_ref t2_y(mk_concat(t2, y), mgr);
expr ** ax_l_items = alloc_svect(expr*, 3); expr_ref_vector ax_l_items(mgr);
ax_l_items[0] = ctx.mk_eq_atom(concatAst1, concatAst2); ax_l_items.push_back(ctx.mk_eq_atom(concatAst1, concatAst2));
expr ** ax_r_items = alloc_svect(expr*, 3); expr_ref_vector ax_r_items(mgr);
ax_r_items[0] = ctx.mk_eq_atom(x, m_t2); ax_r_items.push_back(ctx.mk_eq_atom(x, m_t2));
ax_r_items[1] = ctx.mk_eq_atom(t2_y, n); ax_r_items.push_back(ctx.mk_eq_atom(t2_y, n));
if (m_len_exists && x_len_exists) { if (m_len_exists && x_len_exists) {
ax_l_items[1] = ctx.mk_eq_atom(mk_strlen(x), mk_int(x_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(x), mk_int(x_len)));
ax_l_items[2] = ctx.mk_eq_atom(mk_strlen(m), mk_int(m_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(m), mk_int(m_len)));
rational x_sub_m = x_len - m_len; rational x_sub_m = x_len - m_len;
ax_r_items[2] = ctx.mk_eq_atom(mk_strlen(t2), mk_int(x_sub_m)); ax_r_items.push_back(ctx.mk_eq_atom(mk_strlen(t2), mk_int(x_sub_m)));
} else { } else {
ax_l_items[1] = ctx.mk_eq_atom(mk_strlen(y), mk_int(y_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(y), mk_int(y_len)));
ax_l_items[2] = ctx.mk_eq_atom(mk_strlen(n), mk_int(n_len)); ax_l_items.push_back(ctx.mk_eq_atom(mk_strlen(n), mk_int(n_len)));
rational n_sub_y = n_len - y_len; rational n_sub_y = n_len - y_len;
ax_r_items[2] = ctx.mk_eq_atom(mk_strlen(t2), mk_int(n_sub_y)); ax_r_items.push_back(ctx.mk_eq_atom(mk_strlen(t2), mk_int(n_sub_y)));
} }
expr_ref ax_l(mgr.mk_and(3, ax_l_items), mgr); expr_ref ax_l(mk_and(ax_l_items), mgr);
expr_ref ax_r(mgr.mk_and(3, ax_r_items), mgr); expr_ref ax_r(mk_and(ax_r_items), mgr);
// Cut Info // Cut Info
add_cut_info_merge(t2, sLevel, x); add_cut_info_merge(t2, sLevel, x);
@ -2919,8 +2921,8 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
} }
} else if (splitType == -1) { } else if (splitType == -1) {
// Here we don't really have a choice. We have no length information at all... // Here we don't really have a choice. We have no length information at all...
expr ** or_item = alloc_svect(expr*, 3); expr_ref_vector or_item(mgr);
expr ** and_item = alloc_svect(expr*, 20); expr_ref_vector and_item(mgr);
int option = 0; int option = 0;
int pos = 1; int pos = 1;
@ -2928,28 +2930,29 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
// len(x) < len(m) || len(y) > len(n) // len(x) < len(m) || len(y) > len(n)
if (!avoidLoopCut || !has_self_cut(m, y)) { if (!avoidLoopCut || !has_self_cut(m, y)) {
// break down option 1-1 // break down option 1-1
expr * x_t1 = mk_concat(x, t1); expr_ref x_t1(mk_concat(x, t1), mgr);
expr * t1_n = mk_concat(t1, n); expr_ref t1_n(mk_concat(t1, n), mgr);
or_item[option] = ctx.mk_eq_atom(xorFlag, mk_int(option)); expr_ref or_item_option(ctx.mk_eq_atom(xorFlag, mk_int(option)), mgr);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(m, x_t1)); or_item.push_back(or_item_option);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(y, t1_n)); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(m, x_t1)));
and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(y, t1_n)));
expr_ref x_plus_t1(m_autil.mk_add(mk_strlen(x), mk_strlen(t1)), mgr); expr_ref x_plus_t1(m_autil.mk_add(mk_strlen(x), mk_strlen(t1)), mgr);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(mk_strlen(m), x_plus_t1)); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(mk_strlen(m), x_plus_t1)));
// These were crashing the solver because the integer theory // These were crashing the solver because the integer theory
// expects a constant on the right-hand side. // expects a constant on the right-hand side.
// The things we want to assert here are len(m) > len(x) and len(y) > len(n). // The things we want to assert here are len(m) > len(x) and len(y) > len(n).
// We rewrite A > B as A-B > 0 and then as not(A-B <= 0), // We rewrite A > B as A-B > 0 and then as not(A-B <= 0),
// and then, *because we aren't allowed to use subtraction*, // and then, *because we aren't allowed to use subtraction*,
// as not(A + -1*B <= 0) // as not(A + -1*B <= 0)
and_item[pos++] = ctx.mk_eq_atom(or_item[option], and_item.push_back(ctx.mk_eq_atom(or_item_option,
mgr.mk_not(m_autil.mk_le( mgr.mk_not(m_autil.mk_le(
m_autil.mk_add(mk_strlen(m), m_autil.mk_mul(mk_int(-1), mk_strlen(x))), m_autil.mk_add(mk_strlen(m), m_autil.mk_mul(mk_int(-1), mk_strlen(x))),
mk_int(0))) ); mk_int(0))) ));
and_item[pos++] = ctx.mk_eq_atom(or_item[option], and_item.push_back(ctx.mk_eq_atom(or_item_option,
mgr.mk_not(m_autil.mk_le( mgr.mk_not(m_autil.mk_le(
m_autil.mk_add(mk_strlen(y),m_autil.mk_mul(mk_int(-1), mk_strlen(n))), m_autil.mk_add(mk_strlen(y),m_autil.mk_mul(mk_int(-1), mk_strlen(n))),
mk_int(0))) ); mk_int(0))) ));
option++; option++;
@ -2965,25 +2968,26 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
// x = m || y = n // x = m || y = n
if (!avoidLoopCut || !has_self_cut(x, n)) { if (!avoidLoopCut || !has_self_cut(x, n)) {
// break down option 1-2 // break down option 1-2
expr * m_t2 = mk_concat(m, t2); expr_ref m_t2(mk_concat(m, t2), mgr);
expr * t2_y = mk_concat(t2, y); expr_ref t2_y(mk_concat(t2, y), mgr);
or_item[option] = ctx.mk_eq_atom(xorFlag, mk_int(option)); expr_ref or_item_option(ctx.mk_eq_atom(xorFlag, mk_int(option)), mgr);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(x, m_t2)); or_item.push_back(or_item_option);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(n, t2_y)); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(x, m_t2)));
and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(n, t2_y)));
expr_ref m_plus_t2(m_autil.mk_add(mk_strlen(m), mk_strlen(t2)), mgr); expr_ref m_plus_t2(m_autil.mk_add(mk_strlen(m), mk_strlen(t2)), mgr);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(mk_strlen(x), m_plus_t2)); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(mk_strlen(x), m_plus_t2)));
// want len(x) > len(m) and len(n) > len(y) // want len(x) > len(m) and len(n) > len(y)
and_item[pos++] = ctx.mk_eq_atom(or_item[option], and_item.push_back(ctx.mk_eq_atom(or_item_option,
mgr.mk_not(m_autil.mk_le( mgr.mk_not(m_autil.mk_le(
m_autil.mk_add(mk_strlen(x), m_autil.mk_mul(mk_int(-1), mk_strlen(m))), m_autil.mk_add(mk_strlen(x), m_autil.mk_mul(mk_int(-1), mk_strlen(m))),
mk_int(0))) ); mk_int(0))) ));
and_item[pos++] = ctx.mk_eq_atom(or_item[option], and_item.push_back(ctx.mk_eq_atom(or_item_option,
mgr.mk_not(m_autil.mk_le( mgr.mk_not(m_autil.mk_le(
m_autil.mk_add(mk_strlen(n), m_autil.mk_mul(mk_int(-1), mk_strlen(y))), m_autil.mk_add(mk_strlen(n), m_autil.mk_mul(mk_int(-1), mk_strlen(y))),
mk_int(0))) ); mk_int(0))) ));
option++; option++;
@ -2997,22 +3001,20 @@ void theory_str::process_concat_eq_type1(expr * concatAst1, expr * concatAst2) {
} }
if (can_two_nodes_eq(x, m) && can_two_nodes_eq(y, n)) { if (can_two_nodes_eq(x, m) && can_two_nodes_eq(y, n)) {
or_item[option] = ctx.mk_eq_atom(xorFlag, mk_int(option)); expr_ref or_item_option(ctx.mk_eq_atom(xorFlag, mk_int(option)), mgr);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(x, m)); or_item.push_back(or_item_option);
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(y, n)); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(x, m)));
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(mk_strlen(x), mk_strlen(m))); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(y, n)));
and_item[pos++] = ctx.mk_eq_atom(or_item[option], ctx.mk_eq_atom(mk_strlen(y), mk_strlen(n))); and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(mk_strlen(x), mk_strlen(m))));
and_item.push_back(ctx.mk_eq_atom(or_item_option, ctx.mk_eq_atom(mk_strlen(y), mk_strlen(n))));
++option; ++option;
} }
if (option > 0) { if (option > 0) {
if (option == 1) { and_item.push_back(mk_or(or_item));
and_item[0] = or_item[0];
} else {
and_item[0] = mgr.mk_or(option, or_item);
}
expr_ref premise(ctx.mk_eq_atom(concatAst1, concatAst2), mgr); expr_ref premise(ctx.mk_eq_atom(concatAst1, concatAst2), mgr);
expr_ref conclusion(mgr.mk_and(pos, and_item), mgr); expr_ref conclusion(mk_and(and_item), mgr);
assert_implication(premise, conclusion); assert_implication(premise, conclusion);
} else { } else {
TRACE("t_str", tout << "STOP: no split option found for two EQ concats." << std::endl;); TRACE("t_str", tout << "STOP: no split option found for two EQ concats." << std::endl;);