mirror of
https://github.com/Z3Prover/z3
synced 2026-07-02 21:36:09 +00:00
Fixed the model generation fix
This commit is contained in:
parent
2a142cd150
commit
95d28ad02c
2 changed files with 58 additions and 6 deletions
|
|
@ -324,7 +324,7 @@ namespace smt {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->is_var())
|
if (n->is_var())
|
||||||
return expr_ref(get_var_value(n), m);
|
return expr_ref(get_var_value(n, dep_values), m);
|
||||||
|
|
||||||
if (n->is_concat()) {
|
if (n->is_concat()) {
|
||||||
SASSERT(n->get_sort() && m_seq.is_seq(n->get_sort()));
|
SASSERT(n->get_sort() && m_seq.is_seq(n->get_sort()));
|
||||||
|
|
@ -436,6 +436,15 @@ namespace smt {
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (n->is_var()) {
|
||||||
|
expr* e = n->get_expr();
|
||||||
|
if (e && m_seq.is_seq(e)) {
|
||||||
|
expr_ref len_expr(m_seq.str.mk_length(e), m);
|
||||||
|
collect_expr_dependencies(m_ctx, len_expr, seen, deps);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (n->is_char() || n->is_unit()) {
|
if (n->is_char() || n->is_unit()) {
|
||||||
expr* e = n->get_expr();
|
expr* e = n->get_expr();
|
||||||
if (e && m_seq.str.is_unit(e)) {
|
if (e && m_seq.str.is_unit(e)) {
|
||||||
|
|
@ -476,7 +485,7 @@ namespace smt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* seq_model::get_var_value(euf::snode* var) {
|
expr* seq_model::get_var_value(euf::snode* var, obj_map<enode, expr*> const* dep_values) {
|
||||||
SASSERT(var);
|
SASSERT(var);
|
||||||
unsigned key = var->first()->id();
|
unsigned key = var->first()->id();
|
||||||
expr* val = nullptr;
|
expr* val = nullptr;
|
||||||
|
|
@ -484,7 +493,7 @@ namespace smt {
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
// unconstrained or regex-constrained: delegate to mk_fresh_value
|
// unconstrained or regex-constrained: delegate to mk_fresh_value
|
||||||
val = mk_fresh_value(var);
|
val = mk_fresh_value(var, dep_values);
|
||||||
if (val) {
|
if (val) {
|
||||||
m_trail.push_back(val);
|
m_trail.push_back(val);
|
||||||
m_var_values.insert(key, val);
|
m_var_values.insert(key, val);
|
||||||
|
|
@ -492,7 +501,7 @@ namespace smt {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* seq_model::mk_fresh_value(euf::snode* var) {
|
expr* seq_model::mk_fresh_value(euf::snode* var, obj_map<enode, expr*> const* dep_values) {
|
||||||
SASSERT(var->get_expr());
|
SASSERT(var->get_expr());
|
||||||
if (!m_seq.is_seq(var->get_expr()))
|
if (!m_seq.is_seq(var->get_expr()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -516,6 +525,49 @@ namespace smt {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No regex constraint: try to respect the assigned length for the variable.
|
||||||
|
// This prevents invalid models such as len(x)=1 with x="".
|
||||||
|
arith_util arith(m);
|
||||||
|
expr_ref len_expr(m_seq.str.mk_length(var->get_expr()), m);
|
||||||
|
rational len_val;
|
||||||
|
bool has_len = false;
|
||||||
|
|
||||||
|
if (dep_values) {
|
||||||
|
expr* dval = nullptr;
|
||||||
|
enode* dep = find_root_enode(m_ctx, len_expr);
|
||||||
|
if (dep && dep_values->find(dep, dval) && dval && arith.is_numeral(dval, len_val))
|
||||||
|
has_len = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_len && m_mg) {
|
||||||
|
expr_ref eval_len(m);
|
||||||
|
if (m_mg->get_model().eval(len_expr, eval_len, true) && arith.is_numeral(eval_len, len_val))
|
||||||
|
has_len = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_len) {
|
||||||
|
if (!len_val.is_int() || len_val.is_neg())
|
||||||
|
len_val = rational(0);
|
||||||
|
if (len_val.is_zero())
|
||||||
|
return m_seq.str.mk_empty(srt);
|
||||||
|
|
||||||
|
constexpr unsigned MAX_CONCRETE_WITNESS = 1024;
|
||||||
|
if (len_val.is_unsigned() && len_val.get_unsigned() <= MAX_CONCRETE_WITNESS) {
|
||||||
|
unsigned n = len_val.get_unsigned();
|
||||||
|
zstring w;
|
||||||
|
for (unsigned i = 0; i < n; ++i)
|
||||||
|
w += zstring('0');
|
||||||
|
expr* witness = m_seq.str.mk_string(w);
|
||||||
|
m_factory->register_value(witness);
|
||||||
|
return witness;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr* base = m_seq.str.mk_string("0");
|
||||||
|
expr* witness = m_seq.str.mk_power(base, arith.mk_int(len_val));
|
||||||
|
m_factory->register_value(witness);
|
||||||
|
return witness;
|
||||||
|
}
|
||||||
|
|
||||||
// no regex constraint or witness generation failed: use empty string
|
// no regex constraint or witness generation failed: use empty string
|
||||||
return m_seq.str.mk_empty(srt);
|
return m_seq.str.mk_empty(srt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,14 @@ namespace smt {
|
||||||
|
|
||||||
// look up or compute the value for an snode variable.
|
// look up or compute the value for an snode variable.
|
||||||
// If no assignment exists, delegates to mk_fresh_value.
|
// If no assignment exists, delegates to mk_fresh_value.
|
||||||
expr* get_var_value(euf::snode* var);
|
expr* get_var_value(euf::snode* var, obj_map<enode, expr*> const* dep_values = nullptr);
|
||||||
|
|
||||||
// generate a fresh value for a variable, respecting regex
|
// generate a fresh value for a variable, respecting regex
|
||||||
// membership constraints. If the variable has associated
|
// membership constraints. If the variable has associated
|
||||||
// regex constraints (collected during init), generates a
|
// regex constraints (collected during init), generates a
|
||||||
// witness satisfying the intersection; otherwise falls back
|
// witness satisfying the intersection; otherwise falls back
|
||||||
// to a plain fresh value from the factory.
|
// to a plain fresh value from the factory.
|
||||||
expr* mk_fresh_value(euf::snode* var);
|
expr* mk_fresh_value(euf::snode* var, obj_map<enode, expr*> const* dep_values = nullptr);
|
||||||
|
|
||||||
// collect per-variable regex constraints from the state.
|
// collect per-variable regex constraints from the state.
|
||||||
// For each positive str_mem, records the regex (or intersects
|
// For each positive str_mem, records the regex (or intersects
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue