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

Fix unsound handling of upper bounds in wmax, thanks to Patrick Trentin for report and careful repros #847

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-01-15 11:52:48 -08:00
parent bc6b3007de
commit 7df803c131
5 changed files with 44 additions and 47 deletions

View file

@ -93,7 +93,7 @@ private:
mss m_mss;
expr_ref_vector m_trail;
strategy_t m_st;
rational m_max_upper;
rational m_max_upper;
model_ref m_csmodel;
unsigned m_correction_set_size;
bool m_found_feasible_optimum;
@ -109,6 +109,7 @@ private:
bool m_pivot_on_cs; // prefer smaller correction set to core.
bool m_dump_benchmarks; // display benchmarks (into wcnf format)
std::string m_trace_id;
typedef ptr_vector<expr> exprs;
@ -150,9 +151,7 @@ public:
return
is_uninterp_const(l) ||
(m.is_not(l, l) && is_uninterp_const(l));
}
}
void add_soft(expr* e, rational const& w) {
TRACE("opt", tout << mk_pp(e, m) << " |-> " << w << "\n";);
@ -290,7 +289,7 @@ public:
index = next_index(asms, index);
}
first = false;
IF_VERBOSE(3, verbose_stream() << "weight: " << get_weight(asms[0].get()) << " " << get_weight(asms[index-1].get()) << " num soft: " << index << "\n";);
// IF_VERBOSE(3, verbose_stream() << "weight: " << get_weight(asms[0].get()) << " " << get_weight(asms[index-1].get()) << " num soft: " << index << "\n";);
m_last_index = index;
is_sat = check_sat(index, asms.c_ptr());
}
@ -490,7 +489,7 @@ public:
TRACE("opt", display_vec(tout << "minimized core: ", core););
IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core););
max_resolve(core, w);
fml = mk_not(m, mk_and(m, m_B.size(), m_B.c_ptr()));
fml = mk_not(m, mk_and(m, core.size(), core.c_ptr()));
s().assert_expr(fml);
m_lower += w;
if (m_st == s_primal_dual) {
@ -530,7 +529,10 @@ public:
}
lbool minimize_core(exprs& core) {
if (m_c.sat_enabled() || core.empty()) {
if (core.empty()) {
return l_true;
}
if (m_c.sat_enabled()) {
return l_true;
}
m_mus.reset();
@ -607,8 +609,8 @@ public:
// Soundness of this rule can be established using MaxRes
//
for (unsigned i = 1; i < core.size(); ++i) {
expr* b_i = m_B[i-1].get();
expr* b_i1 = m_B[i].get();
expr* b_i = core[i-1];
expr* b_i1 = core[i];
if (i == 1) {
d = to_app(b_i);
}
@ -658,8 +660,8 @@ public:
// d_i => d_{i-1} or b_{i-1}
//
for (unsigned i = 1; i < cs.size(); ++i) {
expr* b_i = m_B[i-1].get();
expr* b_i1 = m_B[i].get();
expr* b_i = cs[i - 1];
expr* b_i1 = cs[i];
cls = m.mk_or(b_i, d);
if (i > 2) {
d = mk_fresh_bool("d");
@ -680,10 +682,11 @@ public:
s().assert_expr(fml);
m_defs.push_back(fml);
new_assumption(asum, w);
fml = m.mk_and(b_i1, cls);
update_model(asum, fml);
}
fml = m.mk_or(m_B.size(), m_B.c_ptr());
fml = m.mk_or(cs.size(), cs.c_ptr());
s().assert_expr(fml);
}
@ -739,7 +742,7 @@ public:
nsoft.push_back(mk_not(m, m_soft[i]));
}
fml = u.mk_lt(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper);
s().assert_expr(fml);
s().assert_expr(fml);
}
bool is_true(model* mdl, expr* e) {
@ -757,10 +760,9 @@ public:
}
bool is_true(expr_ref_vector const& es) {
for (unsigned i = 0; i < es.size(); ++i) {
if (!is_true(es[i])) return false;
}
return true;
unsigned i = 0;
for (; i < es.size() && is_true(es[i]); ++i) { }
return i == es.size();
}
void remove_soft(exprs const& core, expr_ref_vector& asms) {
@ -780,7 +782,6 @@ public:
virtual void updt_params(params_ref& p) {
maxsmt_solver_base::updt_params(p);
opt_params _p(p);
m_hill_climb = _p.maxres_hill_climb();
m_add_upper_bound_block = _p.maxres_add_upper_bound_block();
m_max_num_cores = _p.maxres_max_num_cores();
@ -858,7 +859,6 @@ public:
IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";);
}
}
};
opt::maxsmt_solver_base* opt::mk_maxres(