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

fix partial model tracking over cancellation/exceptions, reported by August Shi. Fix regression test for fp-to-real, reset the pre-processor in inc_sat_solver on exceptions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-03-07 16:42:29 -08:00
parent 4cd1efc50e
commit 5994c5a948
19 changed files with 239 additions and 193 deletions

View file

@ -203,7 +203,7 @@ namespace opt {
objective& obj = s.m_objectives[i];
m_objectives.push_back(obj);
if (obj.m_type == O_MAXSMT) {
add_maxsmt(obj.m_id);
add_maxsmt(obj.m_id, i);
}
}
m_hard_constraints.append(s.m_hard);
@ -311,7 +311,9 @@ namespace opt {
maxsmt& ms = *m_maxsmts.find(id);
if (scoped) get_solver().push();
lbool result = ms();
if (result != l_false && (ms.get_model(tmp, m_labels), tmp.get())) ms.get_model(m_model, m_labels);
if (result != l_false && (ms.get_model(tmp, m_labels), tmp.get())) {
ms.get_model(m_model, m_labels);
}
if (scoped) get_solver().pop(1);
if (result == l_true && committed) ms.commit_assignment();
return result;
@ -414,12 +416,16 @@ namespace opt {
case O_MINIMIZE:
is_ge = !is_ge;
case O_MAXIMIZE:
VERIFY(mdl->eval(obj.m_term, val) && is_numeral(val, k));
if (is_ge) {
result = mk_ge(obj.m_term, val);
if (mdl->eval(obj.m_term, val) && is_numeral(val, k)) {
if (is_ge) {
result = mk_ge(obj.m_term, val);
}
else {
result = mk_ge(val, obj.m_term);
}
}
else {
result = mk_ge(val, obj.m_term);
result = m.mk_true();
}
break;
case O_MAXSMT: {
@ -430,8 +436,7 @@ namespace opt {
for (unsigned i = 0; i < sz; ++i) {
terms.push_back(obj.m_terms[i]);
coeffs.push_back(obj.m_weights[i]);
VERIFY(mdl->eval(obj.m_terms[i], val));
if (m.is_true(val)) {
if (mdl->eval(obj.m_terms[i], val) && m.is_true(val)) {
k += obj.m_weights[i];
}
}
@ -469,8 +474,7 @@ namespace opt {
update_bound(false);
}
lbool context::execute_pareto() {
lbool context::execute_pareto() {
if (!m_pareto) {
set_pareto(alloc(gia_pareto, m, *this, m_solver.get(), m_params));
}
@ -642,8 +646,8 @@ namespace opt {
}
void context::add_maxsmt(symbol const& id) {
maxsmt* ms = alloc(maxsmt, *this);
void context::add_maxsmt(symbol const& id, unsigned index) {
maxsmt* ms = alloc(maxsmt, *this, index);
ms->updt_params(m_params);
#pragma omp critical (opt_context)
{
@ -708,7 +712,7 @@ namespace opt {
}
}
bool context::is_maximize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index) {
bool context::is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index) {
if (is_app(fml) && m_objective_fns.find(to_app(fml)->get_decl(), index) &&
m_objectives[index].m_type == O_MAXIMIZE) {
term = to_app(to_app(fml)->get_arg(0));
@ -718,7 +722,7 @@ namespace opt {
return false;
}
bool context::is_minimize(expr* fml, app_ref& term, expr*& orig_term, unsigned& index) {
bool context::is_minimize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index) {
if (is_app(fml) && m_objective_fns.find(to_app(fml)->get_decl(), index) &&
m_objectives[index].m_type == O_MINIMIZE) {
term = to_app(to_app(fml)->get_arg(0));
@ -730,7 +734,7 @@ namespace opt {
bool context::is_maxsat(expr* fml, expr_ref_vector& terms,
vector<rational>& weights, rational& offset,
bool& neg, symbol& id, unsigned& index) {
bool& neg, symbol& id, expr_ref& orig_term, unsigned& index) {
if (!is_app(fml)) return false;
neg = false;
app* a = to_app(fml);
@ -752,7 +756,6 @@ namespace opt {
return true;
}
app_ref term(m);
expr* orig_term;
offset = rational::zero();
bool is_max = is_maximize(fml, term, orig_term, index);
bool is_min = !is_max && is_minimize(fml, term, orig_term, index);
@ -773,7 +776,7 @@ namespace opt {
}
}
TRACE("opt",
tout << "Convert minimization " << mk_pp(orig_term, m) << "\n";
tout << "Convert minimization " << orig_term << "\n";
tout << "to maxsat: " << term << "\n";
for (unsigned i = 0; i < weights.size(); ++i) {
tout << mk_pp(terms[i].get(), m) << ": " << weights[i] << "\n";
@ -781,7 +784,7 @@ namespace opt {
tout << "offset: " << offset << "\n";
);
std::ostringstream out;
out << mk_pp(orig_term, m) << ":" << index;
out << orig_term << ":" << index;
id = symbol(out.str().c_str());
return true;
}
@ -804,7 +807,7 @@ namespace opt {
}
neg = true;
std::ostringstream out;
out << mk_pp(orig_term, m) << ":" << index;
out << orig_term << ":" << index;
id = symbol(out.str().c_str());
return true;
}
@ -823,7 +826,7 @@ namespace opt {
}
neg = is_max;
std::ostringstream out;
out << mk_pp(orig_term, m) << ":" << index;
out << orig_term << ":" << index;
id = symbol(out.str().c_str());
return true;
}
@ -871,7 +874,7 @@ namespace opt {
tout << mk_pp(fmls[i], m) << "\n";
});
m_hard_constraints.reset();
expr* orig_term;
expr_ref orig_term(m);
for (unsigned i = 0; i < fmls.size(); ++i) {
expr* fml = fmls[i];
app_ref tr(m);
@ -881,7 +884,7 @@ namespace opt {
unsigned index;
symbol id;
bool neg;
if (is_maxsat(fml, terms, weights, offset, neg, id, index)) {
if (is_maxsat(fml, terms, weights, offset, neg, id, orig_term, index)) {
objective& obj = m_objectives[index];
if (obj.m_type != O_MAXSMT) {
@ -889,10 +892,11 @@ namespace opt {
obj.m_id = id;
obj.m_type = O_MAXSMT;
SASSERT(!m_maxsmts.contains(id));
add_maxsmt(id);
add_maxsmt(id, index);
}
mk_atomic(terms);
SASSERT(obj.m_id == id);
obj.m_term = to_app(orig_term);
obj.m_terms.reset();
obj.m_terms.append(terms);
obj.m_weights.reset();
@ -933,6 +937,32 @@ namespace opt {
}
}
bool context::verify_model(unsigned index, model* md, rational const& _v) {
rational r;
app_ref term = m_objectives[index].m_term;
rational v = m_objectives[index].m_adjust_value(_v);
expr_ref val(m);
model_ref mdl = md;
fix_model(mdl);
if (!mdl->eval(term, val)) {
TRACE("opt", tout << "Term does not evaluate " << term << "\n";);
return false;
}
if (!m_arith.is_numeral(val, r)) {
TRACE("opt", tout << "model does not evaluate objective to a value\n";);
return false;
}
if (r != v) {
TRACE("opt", tout << "Out of bounds: " << term << " " << val << " != " << v << "\n";);
return false;
}
else {
TRACE("opt", tout << "validated: " << term << " = " << val << "\n";);
}
return true;
}
void context::purify(app_ref& term) {
filter_model_converter_ref fm;
if (m_arith.is_add(term)) {
@ -1395,8 +1425,8 @@ namespace opt {
case O_MAXSMT: {
rational value(0);
for (unsigned i = 0; i < obj.m_terms.size(); ++i) {
VERIFY(m_model->eval(obj.m_terms[i], val));
if (!m.is_true(val)) {
bool evaluated = m_model->eval(obj.m_terms[i], val);
if (evaluated && !m.is_true(val)) {
value += obj.m_weights[i];
}
// TBD: check that optimal was not changed.