3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00
This commit is contained in:
Nikolaj Bjorner 2022-10-22 11:18:16 -07:00
parent 7eee7914bd
commit e3a44254c9
3 changed files with 78 additions and 7 deletions

View file

@ -407,9 +407,9 @@ namespace mbp {
TRACE("qe",
for (auto const& [v, t] : result)
tout << v << " := " << t << "\n";
for (auto* f : fmls)
tout << mk_pp(f, m) << " := " << eval(f) << "\n";
tout << "fmls:" << fmls << "\n";);
for (auto* f : fmls)
tout << mk_pp(f, m) << " := " << eval(f) << "\n";
tout << "fmls:" << fmls << "\n";);
return true;
}

View file

@ -30,6 +30,7 @@ Notes:
#include "ast/ast_util.h"
#include "ast/ast_pp.h"
#include "ast/ast_ll_pp.h"
#include "ast/for_each_expr.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/rewriter/bool_rewriter.h"
@ -117,6 +118,12 @@ namespace qe {
return all_shared;
}
void mbi_plugin::validate_interpolant(expr* itp) {
for (expr* e : subterms::ground(expr_ref(itp, m)))
if (!is_shared(e))
IF_VERBOSE(0, verbose_stream() << "non-shared subterm " << mk_bounded_pp(e, m) << "\n");
}
// -------------------------------
// prop_mbi
@ -209,12 +216,10 @@ namespace qe {
lits.reset();
IF_VERBOSE(10, verbose_stream() << "atoms: " << m_atoms << "\n");
for (expr* e : m_atoms) {
if (mdl->is_true(e)) {
if (mdl->is_true(e))
lits.push_back(e);
}
else if (mdl->is_false(e)) {
else if (mdl->is_false(e))
lits.push_back(m.mk_not(e));
}
}
TRACE("qe", tout << "atoms from model: " << lits << "\n";);
solver_ref dual = m_dual_solver->translate(m, m_dual_solver->get_params());
@ -262,6 +267,64 @@ namespace qe {
return avars;
}
/***
Arithmetic projection is not guaranteed to remove non-shared variables
when there are expressions with if-then-else constructs.
For these cases we apply model refinement to the literals: non-shared
sub-expressions are replaced by model values.
*/
void uflia_mbi::fix_non_shared(model& mdl, expr_ref_vector& lits) {
th_rewriter rewrite(m);
expr_ref_vector trail(m);
obj_map<expr, expr*> cache;
ptr_vector<expr> todo, args;
expr* f = nullptr;
todo.append(lits.size(), lits.data());
while (!todo.empty()) {
expr* e = todo.back();
if (cache.contains(e)) {
todo.pop_back();
continue;
}
if (!is_app(e)) {
cache.insert(e, e);
todo.pop_back();
continue;
}
args.reset();
unsigned sz = todo.size();
bool diff = false;
func_decl* fn = to_app(e)->get_decl();
if (!is_shared(fn)) {
expr_ref val = mdl(e);
cache.insert(e, val);
trail.push_back(val);
todo.pop_back();
continue;
}
for (expr* arg : *to_app(e)) {
if (cache.find(arg, f)) {
args.push_back(f);
diff |= f != arg;
}
else
todo.push_back(arg);
}
if (sz < todo.size())
continue;
todo.pop_back();
if (!diff) {
cache.insert(e, e);
continue;
}
f = rewrite.mk_app(to_app(e)->get_decl(), args.size(), args.data());
trail.push_back(f);
cache.insert(e, f);
}
for (unsigned i = 0; i < lits.size(); ++i)
lits[i] = cache[lits.get(i)];
}
vector<mbp::def> uflia_mbi::arith_project(model_ref& mdl, app_ref_vector& avars, expr_ref_vector& lits) {
mbp::arith_project_plugin ap(m);
ap.set_check_purified(false);
@ -269,6 +332,7 @@ namespace qe {
bool ok = ap.project(*mdl.get(), avars, lits, defs);
(void)ok;
CTRACE("qe", !ok, tout << "projection failure ignored!!!!\n");
fix_non_shared(*mdl, lits);
return defs;
}
@ -522,6 +586,7 @@ namespace qe {
break;
case l_false:
itp = mk_or(itps);
a.validate_interpolant(itp);
return l_false;
case l_undef:
return l_undef;

View file

@ -100,6 +100,11 @@ namespace qe {
*/
lbool check(expr_ref_vector& lits, model_ref& mdl);
/**
* \brief validate interpolant that it only uses shared symbols.
*/
void validate_interpolant(expr* itp);
};
class prop_mbi_plugin : public mbi_plugin {
@ -131,6 +136,7 @@ namespace qe {
void split_arith(expr_ref_vector const& lits,
expr_ref_vector& alits,
expr_ref_vector& uflits);
void fix_non_shared(model& mdl, expr_ref_vector& lits);
public:
uflia_mbi(solver* s, solver* emptySolver);
mbi_result operator()(expr_ref_vector& lits, model_ref& mdl) override;