3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 00:55:31 +00:00

fix mb maximization logic, so far not accessible

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-06-20 16:39:03 -07:00
parent c7ff05cc78
commit 9c099d6b1b
12 changed files with 318 additions and 109 deletions

View file

@ -105,7 +105,10 @@ namespace qe {
expr_ref t(m);
opt::ineq_type ty = opt::t_le;
expr* e1, *e2;
DEBUG_CODE(expr_ref val(m); VERIFY(model.eval(lit, val) && m.is_true(val)););
DEBUG_CODE(expr_ref val(m);
VERIFY(model.eval(lit, val));
CTRACE("qe", !m.is_true(val), tout << mk_pp(lit, m) << " := " << val << "\n";);
SASSERT(m.is_true(val)););
bool is_not = m.is_not(lit, lit);
if (is_not) {
@ -942,7 +945,7 @@ namespace qe {
SASSERT(m_u < m_delta && rational(0) <= m_u);
for (unsigned i = 0; i < n; ++i) {
add_lit(model, lits, mk_divides(div_divisor(i),
mk_add(mk_num(div_coeff(i) * m_u), div_term(i))));
mk_add(mk_num(div_coeff(i) * m_u), div_term(i))));
}
reset_divs();
//
@ -1070,7 +1073,7 @@ namespace qe {
for (unsigned i = 0; i < rows.size(); ++i) {
expr_ref_vector ts(m);
expr_ref t(m), s(m);
expr_ref t(m), s(m), val(m);
row const& r = rows[i];
if (r.m_vars.size() == 0) {
continue;
@ -1088,6 +1091,8 @@ namespace qe {
case opt::t_eq: t = a.mk_eq(t, s); break;
}
fmls.push_back(t);
VERIFY(model.eval(t, val));
CTRACE("qe", !m.is_true(val), tout << "Evaluated unit " << t << " to " << val << "\n";);
continue;
}
for (j = 0; j < r.m_vars.size(); ++j) {
@ -1111,10 +1116,16 @@ namespace qe {
case opt::t_eq: t = a.mk_eq(t, s); break;
}
fmls.push_back(t);
VERIFY(model.eval(t, val));
CTRACE("qe", !m.is_true(val), tout << "Evaluated " << t << " to " << val << "\n";);
}
}
opt::inf_eps maximize(expr_ref_vector const& fmls0, model& mdl, app* t, expr_ref& bound) {
opt::inf_eps maximize(expr_ref_vector const& fmls0, model& mdl, app* t, expr_ref& ge, expr_ref& gt) {
validate_model(mdl, fmls0);
m_trail.reset();
SASSERT(a.is_real(t));
expr_ref_vector fmls(fmls0);
@ -1139,11 +1150,6 @@ namespace qe {
// find optimal value
value = mbo.maximize();
expr_ref val(a.mk_numeral(value.get_rational(), false), m);
if (!value.is_finite()) {
bound = m.mk_false();
return value;
}
// update model to use new values that satisfy optimality
ptr_vector<expr> vars;
@ -1160,17 +1166,42 @@ namespace qe {
TRACE("qe", tout << "omitting model update for non-uninterpreted constant " << mk_pp(e, m) << "\n";);
}
}
expr_ref val(a.mk_numeral(value.get_rational(), false), m);
expr_ref tval(m);
VERIFY (mdl.eval(t, tval));
// update the predicate 'bound' which forces larger values.
if (value.get_infinitesimal().is_neg()) {
bound = a.mk_le(val, t);
// update the predicate 'bound' which forces larger values when 'strict' is true.
// strict: bound := valuue < t
// !strict: bound := value <= t
if (!value.is_finite()) {
ge = a.mk_ge(t, tval);
gt = m.mk_false();
}
else if (value.get_infinitesimal().is_neg()) {
ge = a.mk_ge(t, tval);
gt = a.mk_ge(t, val);
}
else {
bound = a.mk_lt(val, t);
}
ge = a.mk_ge(t, val);
gt = a.mk_gt(t, val);
}
validate_model(mdl, fmls0);
return value;
}
bool validate_model(model& mdl, expr_ref_vector const& fmls) {
bool valid = true;
for (unsigned i = 0; i < fmls.size(); ++i) {
expr_ref val(m);
VERIFY(mdl.eval(fmls[i], val));
if (!m.is_true(val)) {
valid = false;
TRACE("qe", tout << mk_pp(fmls[i], m) << " := " << val << "\n";);
}
}
return valid;
}
void extract_coefficients(opt::model_based_opt& mbo, model& model, obj_map<expr, rational> const& ts, obj_map<expr, unsigned>& tids, vars& coeffs) {
coeffs.reset();
obj_map<expr, rational>::iterator it = ts.begin(), end = ts.end();
@ -1219,8 +1250,8 @@ namespace qe {
return m_imp->a.get_family_id();
}
opt::inf_eps arith_project_plugin::maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& bound) {
return m_imp->maximize(fmls, mdl, t, bound);
opt::inf_eps arith_project_plugin::maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt) {
return m_imp->maximize(fmls, mdl, t, ge, gt);
}
bool arith_project(model& model, app* var, expr_ref_vector& lits) {

View file

@ -32,7 +32,7 @@ namespace qe {
virtual void operator()(model& model, app_ref_vector& vars, expr_ref_vector& lits);
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& bound);
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt);
};
bool arith_project(model& model, app* var, expr_ref_vector& lits);

View file

@ -285,9 +285,9 @@ class mbp::impl {
public:
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& bound) {
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt) {
arith_project_plugin arith(m);
return arith.maximize(fmls, mdl, t, bound);
return arith.maximize(fmls, mdl, t, ge, gt);
}
void extract_literals(model& model, expr_ref_vector& fmls) {
@ -428,7 +428,16 @@ public:
}
}
bool validate_model(model& model, expr_ref_vector const& fmls) {
expr_ref val(m);
for (unsigned i = 0; i < fmls.size(); ++i) {
VERIFY(model.eval(fmls[i], val) && m.is_true(val));
}
return true;
}
void operator()(bool force_elim, app_ref_vector& vars, model& model, expr_ref_vector& fmls) {
SASSERT(validate_model(model, fmls));
expr_ref val(m), tmp(m);
app_ref var(m);
expr_ref_vector unused_fmls(m);
@ -446,6 +455,7 @@ public:
}
}
while (!vars.empty() && !fmls.empty()) {
std::cout << "mbp: " << var << "\n";
var = vars.back();
vars.pop_back();
project_plugin* p = get_plugin(var);
@ -483,6 +493,7 @@ public:
vars.reset();
}
fmls.append(unused_fmls);
SASSERT(validate_model(model, fmls));
TRACE("qe", tout << vars << " " << fmls << "\n";);
}
@ -508,6 +519,6 @@ void mbp::extract_literals(model& model, expr_ref_vector& lits) {
m_impl->extract_literals(model, lits);
}
opt::inf_eps mbp::maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& bound) {
return m_impl->maximize(fmls, mdl, t, bound);
opt::inf_eps mbp::maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt) {
return m_impl->maximize(fmls, mdl, t, ge, gt);
}

View file

@ -79,7 +79,7 @@ namespace qe {
\brief
Maximize objective t under current model for constraints in fmls.
*/
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& bound);
opt::inf_eps maximize(expr_ref_vector const& fmls, model& mdl, app* t, expr_ref& ge, expr_ref& gt);
};
}

View file

@ -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"));
}
};

View file

@ -112,6 +112,8 @@ namespace qe {
void display(std::ostream& out) const;
void display(std::ostream& out, expr_ref_vector const& asms) const;
void collect_statistics(statistics& st) const;
bool validate_defs(model& model) const;
};
class qmax {