mirror of
https://github.com/Z3Prover/z3
synced 2025-07-19 19:02:02 +00:00
#5641 - projection that skips interpreted functions can violate model evaluation.
This commit is contained in:
parent
0ca5e7207e
commit
d0fb3cba15
10 changed files with 46 additions and 36 deletions
|
@ -249,8 +249,8 @@ namespace mbp {
|
||||||
bool operator()(model& model, app* v, app_ref_vector& vars, expr_ref_vector& lits) {
|
bool operator()(model& model, app* v, app_ref_vector& vars, expr_ref_vector& lits) {
|
||||||
app_ref_vector vs(m);
|
app_ref_vector vs(m);
|
||||||
vs.push_back(v);
|
vs.push_back(v);
|
||||||
project(model, vs, lits, false);
|
vector<def> defs;
|
||||||
return vs.empty();
|
return project(model, vs, lits, defs, false) && vs.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef opt::model_based_opt::var var;
|
typedef opt::model_based_opt::var var;
|
||||||
|
@ -265,12 +265,12 @@ namespace mbp {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<def> project(model& model, app_ref_vector& vars, expr_ref_vector& fmls, bool compute_def) {
|
bool project(model& model, app_ref_vector& vars, expr_ref_vector& fmls, vector<def>& result, bool compute_def) {
|
||||||
bool has_arith = false;
|
bool has_arith = false;
|
||||||
for (expr* v : vars)
|
for (expr* v : vars)
|
||||||
has_arith |= is_arith(v);
|
has_arith |= is_arith(v);
|
||||||
if (!has_arith)
|
if (!has_arith)
|
||||||
return vector<def>();
|
return true;
|
||||||
model_evaluator eval(model);
|
model_evaluator eval(model);
|
||||||
TRACE("qe", tout << model;);
|
TRACE("qe", tout << model;);
|
||||||
eval.set_model_completion(true);
|
eval.set_model_completion(true);
|
||||||
|
@ -294,7 +294,7 @@ namespace mbp {
|
||||||
}
|
}
|
||||||
fmls.shrink(j);
|
fmls.shrink(j);
|
||||||
TRACE("qe", tout << "formulas\n" << fmls << "\n";
|
TRACE("qe", tout << "formulas\n" << fmls << "\n";
|
||||||
for (auto [e, id] : tids)
|
for (auto const& [e, id] : tids)
|
||||||
tout << mk_pp(e, m) << " -> " << id << "\n";);
|
tout << mk_pp(e, m) << " -> " << id << "\n";);
|
||||||
|
|
||||||
// fmls holds residue,
|
// fmls holds residue,
|
||||||
|
@ -312,7 +312,7 @@ namespace mbp {
|
||||||
rational r;
|
rational r;
|
||||||
expr_ref val = eval(v);
|
expr_ref val = eval(v);
|
||||||
if (!m.inc())
|
if (!m.inc())
|
||||||
return vector<def>();
|
return false;
|
||||||
if (!a.is_numeral(val, r))
|
if (!a.is_numeral(val, r))
|
||||||
throw default_exception("evaluation did not produce a numeral");
|
throw default_exception("evaluation did not produce a numeral");
|
||||||
TRACE("qe", tout << mk_pp(v, m) << " " << val << "\n";);
|
TRACE("qe", tout << mk_pp(v, m) << " " << val << "\n";);
|
||||||
|
@ -326,17 +326,15 @@ namespace mbp {
|
||||||
if (is_arith(e) && !var_mark.is_marked(e))
|
if (is_arith(e) && !var_mark.is_marked(e))
|
||||||
mark_rec(fmls_mark, e);
|
mark_rec(fmls_mark, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_check_purified) {
|
if (m_check_purified) {
|
||||||
for (expr* fml : fmls)
|
for (expr* fml : fmls)
|
||||||
mark_rec(fmls_mark, fml);
|
mark_rec(fmls_mark, fml);
|
||||||
for (auto& kv : tids) {
|
for (auto& kv : tids) {
|
||||||
expr* e = kv.m_key;
|
expr* e = kv.m_key;
|
||||||
if (!var_mark.is_marked(e)) {
|
if (!var_mark.is_marked(e))
|
||||||
mark_rec(fmls_mark, e);
|
mark_rec(fmls_mark, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ptr_vector<expr> index2expr;
|
ptr_vector<expr> index2expr;
|
||||||
for (auto& kv : tids)
|
for (auto& kv : tids)
|
||||||
|
@ -364,16 +362,18 @@ namespace mbp {
|
||||||
for (auto const& d : defs) tout << "def: " << d << "\n";
|
for (auto const& d : defs) tout << "def: " << d << "\n";
|
||||||
tout << fmls << "\n";);
|
tout << fmls << "\n";);
|
||||||
|
|
||||||
vector<def> result;
|
|
||||||
if (compute_def)
|
if (compute_def)
|
||||||
optdefs2mbpdef(defs, index2expr, real_vars, result);
|
optdefs2mbpdef(defs, index2expr, real_vars, result);
|
||||||
if (m_apply_projection)
|
if (m_apply_projection && !apply_projection(eval, result, fmls))
|
||||||
apply_projection(result, fmls);
|
return false;
|
||||||
|
|
||||||
TRACE("qe",
|
TRACE("qe",
|
||||||
for (auto [v, t] : result)
|
for (auto const& [v, t] : result)
|
||||||
tout << v << " := " << t << "\n";
|
tout << v << " := " << t << "\n";
|
||||||
|
for (auto* f : fmls)
|
||||||
|
tout << mk_pp(f, m) << " := " << eval(f) << "\n";
|
||||||
tout << "fmls:" << fmls << "\n";);
|
tout << "fmls:" << fmls << "\n";);
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void optdefs2mbpdef(vector<opt::model_based_opt::def> const& defs, ptr_vector<expr> const& index2expr, unsigned_vector const& real_vars, vector<def>& result) {
|
void optdefs2mbpdef(vector<opt::model_based_opt::def> const& defs, ptr_vector<expr> const& index2expr, unsigned_vector const& real_vars, vector<def>& result) {
|
||||||
|
@ -548,10 +548,11 @@ namespace mbp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_projection(vector<def>& defs, expr_ref_vector& fmls) {
|
bool apply_projection(model_evaluator& eval, vector<def> const& defs, expr_ref_vector& fmls) {
|
||||||
if (fmls.empty() || defs.empty())
|
if (fmls.empty() || defs.empty())
|
||||||
return;
|
return true;
|
||||||
expr_safe_replace subst(m);
|
expr_safe_replace subst(m);
|
||||||
|
expr_ref_vector fmls_tmp(m);
|
||||||
expr_ref tmp(m);
|
expr_ref tmp(m);
|
||||||
for (unsigned i = defs.size(); i-- > 0; ) {
|
for (unsigned i = defs.size(); i-- > 0; ) {
|
||||||
auto const& d = defs[i];
|
auto const& d = defs[i];
|
||||||
|
@ -561,8 +562,11 @@ namespace mbp {
|
||||||
unsigned j = 0;
|
unsigned j = 0;
|
||||||
for (expr* fml : fmls) {
|
for (expr* fml : fmls) {
|
||||||
subst(fml, tmp);
|
subst(fml, tmp);
|
||||||
|
if (m.is_false(eval(tmp)))
|
||||||
|
return false;
|
||||||
fmls[j++] = tmp;
|
fmls[j++] = tmp;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -579,12 +583,13 @@ namespace mbp {
|
||||||
return (*m_imp)(model, var, vars, lits);
|
return (*m_imp)(model, var, vars, lits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_project_plugin::operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
|
bool arith_project_plugin::operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
|
||||||
m_imp->project(model, vars, lits, false);
|
vector<def> defs;
|
||||||
|
return m_imp->project(model, vars, lits, defs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<def> arith_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
|
bool arith_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) {
|
||||||
return m_imp->project(model, vars, lits, true);
|
return m_imp->project(model, vars, lits, defs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arith_project_plugin::set_check_purified(bool check_purified) {
|
void arith_project_plugin::set_check_purified(bool check_purified) {
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace mbp {
|
||||||
bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override;
|
||||||
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override { return false; }
|
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override { return false; }
|
||||||
family_id get_family_id() override;
|
family_id get_family_id() override;
|
||||||
void operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
||||||
vector<def> project(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) override;
|
||||||
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override { UNREACHABLE(); }
|
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override { UNREACHABLE(); }
|
||||||
|
|
||||||
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt);
|
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt);
|
||||||
|
|
|
@ -1624,8 +1624,8 @@ namespace mbp {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<def> array_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
|
bool array_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) {
|
||||||
return vector<def>();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_project_plugin::saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) {
|
void array_project_plugin::saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace mbp {
|
||||||
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
||||||
void operator()(model& model, app_ref_vector& vars, expr_ref& fml, app_ref_vector& aux_vars, bool reduce_all_selects);
|
void operator()(model& model, app_ref_vector& vars, expr_ref& fml, app_ref_vector& aux_vars, bool reduce_all_selects);
|
||||||
family_id get_family_id() override;
|
family_id get_family_id() override;
|
||||||
vector<def> project(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) override;
|
||||||
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override;
|
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -300,8 +300,8 @@ namespace mbp {
|
||||||
return m_imp->solve(model, vars, lits);
|
return m_imp->solve(model, vars, lits);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<def> datatype_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
|
bool datatype_project_plugin::project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) {
|
||||||
return vector<def>();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void datatype_project_plugin::saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) {
|
void datatype_project_plugin::saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace mbp {
|
||||||
bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool operator()(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) override;
|
||||||
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
||||||
family_id get_family_id() override;
|
family_id get_family_id() override;
|
||||||
vector<def> project(model& model, app_ref_vector& vars, expr_ref_vector& lits) override;
|
bool project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) override;
|
||||||
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override;
|
void saturate(model& model, func_decl_ref_vector const& shared, expr_ref_vector& lits) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace mbp {
|
||||||
virtual bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) { return false; }
|
virtual bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) { return false; }
|
||||||
virtual family_id get_family_id() { return null_family_id; }
|
virtual family_id get_family_id() { return null_family_id; }
|
||||||
|
|
||||||
virtual void operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) { };
|
virtual bool operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits) { return false; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief project vars modulo model, return set of definitions for eliminated variables.
|
\brief project vars modulo model, return set of definitions for eliminated variables.
|
||||||
|
@ -76,7 +76,7 @@ namespace mbp {
|
||||||
- returns set of definitions
|
- returns set of definitions
|
||||||
(TBD: in triangular form, the last definition can be substituted into definitions that come before)
|
(TBD: in triangular form, the last definition can be substituted into definitions that come before)
|
||||||
*/
|
*/
|
||||||
virtual vector<def> project(model& model, app_ref_vector& vars, expr_ref_vector& lits) { return vector<def>(); }
|
virtual bool project(model& model, app_ref_vector& vars, expr_ref_vector& lits, vector<def>& defs) { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief model based saturation. Saturates theory axioms to equi-satisfiable literals over EUF,
|
\brief model based saturation. Saturates theory axioms to equi-satisfiable literals over EUF,
|
||||||
|
|
|
@ -266,7 +266,10 @@ namespace qe {
|
||||||
vector<mbp::def> uflia_mbi::arith_project(model_ref& mdl, app_ref_vector& avars, expr_ref_vector& lits) {
|
vector<mbp::def> uflia_mbi::arith_project(model_ref& mdl, app_ref_vector& avars, expr_ref_vector& lits) {
|
||||||
mbp::arith_project_plugin ap(m);
|
mbp::arith_project_plugin ap(m);
|
||||||
ap.set_check_purified(false);
|
ap.set_check_purified(false);
|
||||||
return ap.project(*mdl.get(), avars, lits);
|
vector<mbp::def> defs;
|
||||||
|
bool ok = ap.project(*mdl.get(), avars, lits, defs);
|
||||||
|
CTRACE("qe", !ok, tout << "projection failure ignored!!!!\n");
|
||||||
|
return defs;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbi_result uflia_mbi::operator()(expr_ref_vector& lits, model_ref& mdl) {
|
mbi_result uflia_mbi::operator()(expr_ref_vector& lits, model_ref& mdl) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace q {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_max_cex += ctx.get_config().m_mbqi_max_cexs;
|
m_max_cex += ctx.get_config().m_mbqi_max_cexs;
|
||||||
for (auto [qlit, fml, generation] : m_instantiations) {
|
for (auto const& [qlit, fml, generation] : m_instantiations) {
|
||||||
euf::solver::scoped_generation sg(ctx, generation + 1);
|
euf::solver::scoped_generation sg(ctx, generation + 1);
|
||||||
sat::literal lit = ctx.mk_literal(fml);
|
sat::literal lit = ctx.mk_literal(fml);
|
||||||
m_qs.add_clause(~qlit, ~lit);
|
m_qs.add_clause(~qlit, ~lit);
|
||||||
|
@ -308,8 +308,10 @@ namespace q {
|
||||||
proj.extract_literals(*m_model, vars, fmls);
|
proj.extract_literals(*m_model, vars, fmls);
|
||||||
fmls_extracted = true;
|
fmls_extracted = true;
|
||||||
}
|
}
|
||||||
if (p)
|
if (!p)
|
||||||
(*p)(*m_model, vars, fmls);
|
continue;
|
||||||
|
if (!(*p)(*m_model, vars, fmls))
|
||||||
|
return expr_ref(nullptr, m);
|
||||||
}
|
}
|
||||||
for (app* v : vars) {
|
for (app* v : vars) {
|
||||||
expr_ref term(m);
|
expr_ref term(m);
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace q {
|
||||||
tout << "invert-app " << mk_pp(t, m) << " = " << mk_pp(value, m) << "\n";
|
tout << "invert-app " << mk_pp(t, m) << " = " << mk_pp(value, m) << "\n";
|
||||||
if (v2r.find(value, r))
|
if (v2r.find(value, r))
|
||||||
tout << "inverse " << mk_pp(r->get_expr(), m) << "\n";
|
tout << "inverse " << mk_pp(r->get_expr(), m) << "\n";
|
||||||
ctx.display(tout);
|
/*ctx.display(tout); */
|
||||||
);
|
);
|
||||||
if (v2r.find(value, r))
|
if (v2r.find(value, r))
|
||||||
return r->get_expr();
|
return r->get_expr();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue