mirror of
https://github.com/Z3Prover/z3
synced 2025-05-05 06:45:45 +00:00
fix mb maximization logic, so far not accessible
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
c7ff05cc78
commit
9c099d6b1b
12 changed files with 318 additions and 109 deletions
127
src/qe/qsat.cpp
127
src/qe/qsat.cpp
|
@ -507,6 +507,26 @@ namespace qe {
|
|||
}
|
||||
}
|
||||
|
||||
bool pred_abs::validate_defs(model& model) const {
|
||||
bool valid = true;
|
||||
obj_map<expr, expr*>::iterator it = m_pred2lit.begin(), end = m_pred2lit.end();
|
||||
for (; it != end; ++it) {
|
||||
expr_ref val_a(m), val_b(m);
|
||||
expr* a = it->m_key;
|
||||
expr* b = it->m_value;
|
||||
VERIFY(model.eval(a, val_a));
|
||||
VERIFY(model.eval(b, val_b));
|
||||
if (val_a != val_b) {
|
||||
TRACE("qe",
|
||||
tout << mk_pp(a, m) << " := " << val_a << "\n";
|
||||
tout << mk_pp(b, m) << " := " << val_b << "\n";
|
||||
tout << m_elevel.find(a) << "\n";);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
class kernel {
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
|
@ -575,6 +595,9 @@ namespace qe {
|
|||
app* m_objective;
|
||||
opt::inf_eps* m_value;
|
||||
bool m_was_sat;
|
||||
model_ref m_model_save;
|
||||
expr_ref m_gt;
|
||||
opt::inf_eps m_value_save;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -588,15 +611,23 @@ namespace qe {
|
|||
check_cancel();
|
||||
expr_ref_vector asms(m_asms);
|
||||
m_pred_abs.get_assumptions(m_model.get(), asms);
|
||||
if (m_model.get()) {
|
||||
validate_assumptions(*m_model.get(), asms);
|
||||
}
|
||||
TRACE("qe", tout << asms << "\n";);
|
||||
solver& s = get_kernel(m_level).s();
|
||||
lbool res = s.check_sat(asms);
|
||||
switch (res) {
|
||||
case l_true:
|
||||
s.get_model(m_model);
|
||||
SASSERT(validate_defs("check_sat"));
|
||||
SASSERT(validate_assumptions(*m_model.get(), asms));
|
||||
SASSERT(validate_model(asms));
|
||||
TRACE("qe", s.display(tout); display(tout << "\n", *m_model.get()); display(tout, asms); );
|
||||
push();
|
||||
if (m_level == 1 && m_mode == qsat_maximize) {
|
||||
maximize_model();
|
||||
}
|
||||
break;
|
||||
case l_false:
|
||||
switch (m_level) {
|
||||
|
@ -607,6 +638,7 @@ namespace qe {
|
|||
return l_true;
|
||||
}
|
||||
if (m_model.get()) {
|
||||
SASSERT(validate_assumptions(*m_model.get(), asms));
|
||||
if (!project_qe(asms)) return l_undef;
|
||||
}
|
||||
else {
|
||||
|
@ -734,7 +766,28 @@ namespace qe {
|
|||
}
|
||||
}
|
||||
|
||||
bool validate_defs(char const* msg) {
|
||||
if (m_model.get() && !m_pred_abs.validate_defs(*m_model.get())) {
|
||||
TRACE("qe",
|
||||
tout << msg << "\n";
|
||||
display(tout);
|
||||
if (m_level > 0) {
|
||||
get_kernel(m_level-1).s().display(tout);
|
||||
}
|
||||
expr_ref_vector asms(m);
|
||||
m_pred_abs.get_assumptions(m_model.get(), asms);
|
||||
tout << asms << "\n";
|
||||
m_pred_abs.pred2lit(asms);
|
||||
tout << asms << "\n";);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool get_core(expr_ref_vector& core, unsigned level) {
|
||||
SASSERT(validate_defs("get_core"));
|
||||
get_kernel(level).get_core(core);
|
||||
m_pred_abs.pred2lit(core);
|
||||
return true;
|
||||
|
@ -814,33 +867,33 @@ namespace qe {
|
|||
if (!get_core(core, m_level)) {
|
||||
return false;
|
||||
}
|
||||
SASSERT(validate_core(core));
|
||||
SASSERT(validate_core(mdl, core));
|
||||
get_vars(m_level);
|
||||
SASSERT(validate_assumptions(mdl, core));
|
||||
m_mbp(force_elim(), m_avars, mdl, core);
|
||||
SASSERT(validate_defs("project_qe"));
|
||||
if (m_mode == qsat_maximize) {
|
||||
maximize(core, mdl);
|
||||
pop(1);
|
||||
maximize_core(core, mdl);
|
||||
}
|
||||
else {
|
||||
fml = negate_core(core);
|
||||
add_assumption(fml);
|
||||
m_answer.push_back(fml);
|
||||
m_free_vars.append(m_avars);
|
||||
pop(1);
|
||||
}
|
||||
pop(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool project(expr_ref_vector& core) {
|
||||
if (!get_core(core, m_level)) return false;
|
||||
TRACE("qe", display(tout); display(tout << "core\n", core););
|
||||
SASSERT(validate_core(core));
|
||||
SASSERT(m_level >= 2);
|
||||
expr_ref fml(m);
|
||||
expr_ref_vector defs(m), core_save(m);
|
||||
max_level level;
|
||||
model& mdl = *m_model.get();
|
||||
|
||||
SASSERT(validate_core(mdl, core));
|
||||
get_vars(m_level-1);
|
||||
SASSERT(validate_project(mdl, core));
|
||||
m_mbp(force_elim(), m_avars, mdl, core);
|
||||
|
@ -875,6 +928,7 @@ namespace qe {
|
|||
fml = m_pred_abs.mk_abstract(fml);
|
||||
get_kernel(m_level).assert_expr(fml);
|
||||
}
|
||||
SASSERT(!m_model.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1005,7 +1059,19 @@ namespace qe {
|
|||
}
|
||||
}
|
||||
|
||||
bool validate_core(expr_ref_vector const& core) {
|
||||
bool validate_assumptions(model& mdl, expr_ref_vector const& core) {
|
||||
for (unsigned i = 0; i < core.size(); ++i) {
|
||||
expr_ref val(m);
|
||||
VERIFY(mdl.eval(core[i], val));
|
||||
if (!m.is_true(val)) {
|
||||
TRACE("qe", tout << "component of core is not true: " << mk_pp(core[i], m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_core(model& mdl, expr_ref_vector const& core) {
|
||||
return true;
|
||||
#if 0
|
||||
TRACE("qe", tout << "Validate core\n";);
|
||||
|
@ -1130,7 +1196,8 @@ namespace qe {
|
|||
m_free_vars(m),
|
||||
m_objective(0),
|
||||
m_value(0),
|
||||
m_was_sat(false)
|
||||
m_was_sat(false),
|
||||
m_gt(m)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -1258,6 +1325,7 @@ namespace qe {
|
|||
m_objective = t;
|
||||
m_value = &value;
|
||||
m_was_sat = false;
|
||||
m_model_save.reset();
|
||||
m_pred_abs.abstract_atoms(fml, defs);
|
||||
fml = m_pred_abs.mk_abstract(fml);
|
||||
m_ex.assert_expr(mk_and(defs));
|
||||
|
@ -1271,6 +1339,7 @@ namespace qe {
|
|||
if (!m_was_sat) {
|
||||
return l_false;
|
||||
}
|
||||
mdl = m_model_save;
|
||||
break;
|
||||
case l_true:
|
||||
UNREACHABLE();
|
||||
|
@ -1286,15 +1355,49 @@ namespace qe {
|
|||
return l_true;
|
||||
}
|
||||
|
||||
void maximize(expr_ref_vector const& core, model& mdl) {
|
||||
void maximize_core(expr_ref_vector const& core, model& mdl) {
|
||||
SASSERT(m_value);
|
||||
SASSERT(m_objective);
|
||||
TRACE("qe", tout << "maximize: " << core << "\n";);
|
||||
m_was_sat |= !core.empty();
|
||||
expr_ref bound(m);
|
||||
*m_value = m_mbp.maximize(core, mdl, m_objective, bound);
|
||||
IF_VERBOSE(0, verbose_stream() << "(maximize " << *m_value << " bound: " << bound << ")\n";);
|
||||
m_ex.assert_expr(bound);
|
||||
*m_value = m_value_save;
|
||||
IF_VERBOSE(3, verbose_stream() << "(maximize " << *m_value << ")\n";);
|
||||
m_ex.assert_expr(m_gt);
|
||||
m_fa.assert_expr(m_gt);
|
||||
}
|
||||
|
||||
void maximize_model() {
|
||||
SASSERT(m_level == 1 && m_mode == qsat_maximize);
|
||||
SASSERT(m_objective);
|
||||
expr_ref ge(m);
|
||||
expr_ref_vector asms(m), defs(m);
|
||||
m_pred_abs.get_assumptions(m_model.get(), asms);
|
||||
m_pred_abs.pred2lit(asms);
|
||||
|
||||
SASSERT(validate_defs("maximize_model1"));
|
||||
|
||||
m_value_save = m_mbp.maximize(asms, *m_model.get(), m_objective, ge, m_gt);
|
||||
|
||||
SASSERT(validate_defs("maximize_model2"));
|
||||
|
||||
// bound := val <= m_objective
|
||||
|
||||
IF_VERBOSE(3, verbose_stream() << "(qsat-maximize-bound: " << m_value_save << ")\n";);
|
||||
|
||||
max_level level;
|
||||
m_pred_abs.abstract_atoms(ge, level, defs);
|
||||
m_ex.assert_expr(mk_and(defs));
|
||||
m_fa.assert_expr(mk_and(defs));
|
||||
|
||||
ge = m_pred_abs.mk_abstract(ge);
|
||||
|
||||
SASSERT(is_uninterp_const(ge));
|
||||
// update model with evaluation for bound.
|
||||
if (is_uninterp_const(ge)) {
|
||||
m_model->register_decl(to_app(ge)->get_decl(), m.mk_true());
|
||||
}
|
||||
SASSERT(validate_defs("maximize_model3"));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue