3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 21:38:44 +00:00

integrating new integer primal loop

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2015-01-20 16:38:45 -08:00
parent 4bb5302def
commit e24db56650
17 changed files with 183 additions and 66 deletions

View file

@ -30,6 +30,7 @@ Notes:
#include "simplify_tactic.h" #include "simplify_tactic.h"
#include "goal2sat.h" #include "goal2sat.h"
#include "ast_pp.h" #include "ast_pp.h"
#include "model_smt2_pp.h"
// incremental SAT solver. // incremental SAT solver.
class inc_sat_solver : public solver { class inc_sat_solver : public solver {
@ -396,14 +397,15 @@ private:
(*m_mc)(m_model); (*m_mc)(m_model);
} }
SASSERT(m_model); SASSERT(m_model);
// IF_VERBOSE(0, model_smt2_pp(verbose_stream(), m, *(m_model.get()), 0););
DEBUG_CODE( DEBUG_CODE(
for (unsigned i = 0; i < m_fmls.size(); ++i) { for (unsigned i = 0; i < m_fmls.size(); ++i) {
expr_ref tmp(m); expr_ref tmp(m);
VERIFY(m_model->eval(m_fmls[i].get(), tmp)); VERIFY(m_model->eval(m_fmls[i].get(), tmp));
CTRACE("opt", !m.is_true(tmp), CTRACE("opt", !m.is_true(tmp),
tout << "Evaluation failed: " << mk_pp(m_fmls[i].get(), m) << "\n";); tout << "Evaluation failed: " << mk_pp(m_fmls[i].get(), m)
<< " to " << tmp << "\n";
model_smt2_pp(tout, m, *(m_model.get()), 0););
SASSERT(m.is_true(tmp)); SASSERT(m.is_true(tmp));
}); });
} }

View file

@ -251,11 +251,11 @@ namespace opt {
} }
void maxsmt::update_lower(rational const& r) { void maxsmt::update_lower(rational const& r) {
if (m_lower > r) m_lower = r; m_lower = r;
} }
void maxsmt::update_upper(rational const& r) { void maxsmt::update_upper(rational const& r) {
if (m_upper < r) m_upper = r; m_upper = r;
} }
void maxsmt::get_model(model_ref& mdl) { void maxsmt::get_model(model_ref& mdl) {

View file

@ -247,8 +247,7 @@ namespace opt {
mdl = m_model; mdl = m_model;
} }
void context::get_model(model_ref& mdl) { void context::fix_model(model_ref& mdl) {
mdl = m_model;
if (mdl) { if (mdl) {
if (m_model_converter) { if (m_model_converter) {
(*m_model_converter)(mdl, 0); (*m_model_converter)(mdl, 0);
@ -257,6 +256,16 @@ namespace opt {
} }
} }
void context::set_model(model_ref& mdl) {
m_model = mdl;
fix_model(mdl);
}
void context::get_model(model_ref& mdl) {
mdl = m_model;
fix_model(mdl);
}
lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) { lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) {
if (scoped) get_solver().push(); if (scoped) get_solver().push();
lbool result = m_optsmt.lex(index, is_max); lbool result = m_optsmt.lex(index, is_max);
@ -384,6 +393,9 @@ namespace opt {
break; break;
} }
} }
TRACE("opt",
model_smt2_pp(tout << "Model:\n", m, *mdl, 0);
mdl->eval(term, val); tout << term << " " << val << "\n";);
VERIFY(mdl->eval(term, val) && is_numeral(val, r)); VERIFY(mdl->eval(term, val) && is_numeral(val, r));
} }
@ -914,9 +926,12 @@ namespace opt {
objective const& obj = m_objectives[i]; objective const& obj = m_objectives[i];
rational r; rational r;
switch(obj.m_type) { switch(obj.m_type) {
case O_MINIMIZE: case O_MINIMIZE: {
if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) { bool evaluated = m_model->eval(obj.m_term, val);
TRACE("opt", tout << obj.m_term << " " << val << " " << evaluated << " " << is_numeral(val, r) << "\n";);
if (evaluated && is_numeral(val, r)) {
inf_eps val = inf_eps(obj.m_adjust_value(r)); inf_eps val = inf_eps(obj.m_adjust_value(r));
TRACE("opt", tout << "adjusted value: " << val << "\n";);
if (is_lower) { if (is_lower) {
m_optsmt.update_lower(obj.m_index, val); m_optsmt.update_lower(obj.m_index, val);
} }
@ -925,9 +940,13 @@ namespace opt {
} }
} }
break; break;
case O_MAXIMIZE: }
if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) { case O_MAXIMIZE: {
bool evaluated = m_model->eval(obj.m_term, val);
TRACE("opt", tout << obj.m_term << " " << val << "\n";);
if (evaluated && is_numeral(val, r)) {
inf_eps val = inf_eps(obj.m_adjust_value(r)); inf_eps val = inf_eps(obj.m_adjust_value(r));
TRACE("opt", tout << "adjusted value: " << val << "\n";);
if (is_lower) { if (is_lower) {
m_optsmt.update_lower(obj.m_index, val); m_optsmt.update_lower(obj.m_index, val);
} }
@ -936,10 +955,13 @@ namespace opt {
} }
} }
break; break;
}
case O_MAXSMT: { case O_MAXSMT: {
bool ok = true; bool ok = true;
for (unsigned j = 0; ok && j < obj.m_terms.size(); ++j) { for (unsigned j = 0; ok && j < obj.m_terms.size(); ++j) {
if (m_model->eval(obj.m_terms[j], val)) { bool evaluated = m_model->eval(obj.m_terms[j], val);
TRACE("opt", tout << mk_pp(obj.m_terms[j], m) << " " << val << "\n";);
if (evaluated) {
if (!m.is_true(val)) { if (!m.is_true(val)) {
r += obj.m_weights[j]; r += obj.m_weights[j];
} }
@ -949,11 +971,14 @@ namespace opt {
} }
} }
if (ok) { if (ok) {
maxsmt& ms = *m_maxsmts.find(obj.m_id);
if (is_lower) { if (is_lower) {
m_maxsmts.find(obj.m_id)->update_upper(r); ms.update_upper(r);
TRACE("opt", tout << r << " " << ms.get_upper() << "\n";);
} }
else { else {
m_maxsmts.find(obj.m_id)->update_lower(r); ms.update_lower(r);
TRACE("opt", tout << r << " " << ms.get_lower() << "\n";);
} }
} }
break; break;

View file

@ -147,6 +147,8 @@ namespace opt {
virtual void set_hard_constraints(ptr_vector<expr> & hard); virtual void set_hard_constraints(ptr_vector<expr> & hard);
virtual lbool optimize(); virtual lbool optimize();
virtual void get_model(model_ref& m); virtual void get_model(model_ref& m);
virtual void set_model(model_ref& m);
virtual void fix_model(model_ref& m);
virtual void collect_statistics(statistics& stats) const; virtual void collect_statistics(statistics& stats) const;
virtual proof* get_proof() { return 0; } virtual proof* get_proof() { return 0; }
virtual void get_labels(svector<symbol> & r) {} virtual void get_labels(svector<symbol> & r) {}

View file

@ -38,7 +38,10 @@ namespace opt {
return l_undef; return l_undef;
} }
m_solver->get_model(m_model); m_solver->get_model(m_model);
IF_VERBOSE(1, model_smt2_pp(verbose_stream() << "new model:\n", m, *m_model, 0);); IF_VERBOSE(1,
model_ref mdl(m_model);
cb.fix_model(mdl);
model_smt2_pp(verbose_stream() << "new model:\n", m, *mdl, 0););
// TBD: we can also use local search to tune solution coordinate-wise. // TBD: we can also use local search to tune solution coordinate-wise.
mk_dominates(); mk_dominates();
is_sat = m_solver->check_sat(0, 0); is_sat = m_solver->check_sat(0, 0);
@ -65,6 +68,7 @@ namespace opt {
fmls.push_back(m.mk_or(gt.size(), gt.c_ptr())); fmls.push_back(m.mk_or(gt.size(), gt.c_ptr()));
fml = m.mk_and(fmls.size(), fmls.c_ptr()); fml = m.mk_and(fmls.size(), fmls.c_ptr());
IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";); IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";);
TRACE("opt", tout << fml << "\n";);
m_solver->assert_expr(fml); m_solver->assert_expr(fml);
} }
@ -77,6 +81,7 @@ namespace opt {
} }
fml = m.mk_not(m.mk_and(le.size(), le.c_ptr())); fml = m.mk_not(m.mk_and(le.size(), le.c_ptr()));
IF_VERBOSE(10, verbose_stream() << "not dominated by: " << fml << "\n";); IF_VERBOSE(10, verbose_stream() << "not dominated by: " << fml << "\n";);
TRACE("opt", tout << fml << "\n";);
m_solver->assert_expr(fml); m_solver->assert_expr(fml);
} }

View file

@ -31,6 +31,8 @@ namespace opt {
virtual expr_ref mk_gt(unsigned i, model_ref& model) = 0; virtual expr_ref mk_gt(unsigned i, model_ref& model) = 0;
virtual expr_ref mk_ge(unsigned i, model_ref& model) = 0; virtual expr_ref mk_ge(unsigned i, model_ref& model) = 0;
virtual expr_ref mk_le(unsigned i, model_ref& model) = 0; virtual expr_ref mk_le(unsigned i, model_ref& model) = 0;
virtual void set_model(model_ref& m) = 0;
virtual void fix_model(model_ref& m) = 0;
}; };
class pareto_base { class pareto_base {
protected: protected:

View file

@ -194,6 +194,7 @@ namespace opt {
inf_eps val = get_optimizer().maximize(v, blocker, has_shared); inf_eps val = get_optimizer().maximize(v, blocker, has_shared);
inf_eps val2; inf_eps val2;
m_valid_objectives[i] = true; m_valid_objectives[i] = true;
TRACE("opt", tout << (has_shared?"has shared":"non-shared") << "\n";);
if (m_context.get_context().update_model(has_shared)) { if (m_context.get_context().update_model(has_shared)) {
if (has_shared) { if (has_shared) {
val2 = current_objective_value(i); val2 = current_objective_value(i);
@ -302,20 +303,31 @@ namespace opt {
if (typeid(smt::theory_inf_arith) == typeid(opt)) { if (typeid(smt::theory_inf_arith) == typeid(opt)) {
smt::theory_inf_arith& th = dynamic_cast<smt::theory_inf_arith&>(opt); smt::theory_inf_arith& th = dynamic_cast<smt::theory_inf_arith&>(opt);
return expr_ref(th.mk_ge(m_fm, v, val), m); return th.mk_ge(m_fm, v, val);
} }
if (typeid(smt::theory_mi_arith) == typeid(opt)) { if (typeid(smt::theory_mi_arith) == typeid(opt)) {
smt::theory_mi_arith& th = dynamic_cast<smt::theory_mi_arith&>(opt); smt::theory_mi_arith& th = dynamic_cast<smt::theory_mi_arith&>(opt);
SASSERT(val.is_finite()); SASSERT(val.is_finite());
return expr_ref(th.mk_ge(m_fm, v, val.get_numeral()), m); return th.mk_ge(m_fm, v, val.get_numeral());
} }
if (typeid(smt::theory_i_arith) == typeid(opt)) { if (typeid(smt::theory_i_arith) == typeid(opt)) {
SASSERT(val.is_finite()); SASSERT(val.is_finite());
SASSERT(val.get_infinitesimal().is_zero()); SASSERT(val.get_infinitesimal().is_zero());
smt::theory_i_arith& th = dynamic_cast<smt::theory_i_arith&>(opt); smt::theory_i_arith& th = dynamic_cast<smt::theory_i_arith&>(opt);
return expr_ref(th.mk_ge(m_fm, v, val.get_rational()), m); return th.mk_ge(m_fm, v, val.get_rational());
}
if (typeid(smt::theory_idl) == typeid(opt)) {
smt::theory_idl& th = dynamic_cast<smt::theory_idl&>(opt);
return th.mk_ge(m_fm, v, val.get_rational());
}
if (typeid(smt::theory_rdl) == typeid(opt) &&
val.get_infinitesimal().is_zero()) {
smt::theory_rdl& th = dynamic_cast<smt::theory_rdl&>(opt);
return th.mk_ge(m_fm, v, val.get_rational());
} }
// difference logic? // difference logic?

View file

@ -170,11 +170,13 @@ namespace opt {
} }
void optsmt::update_lower(unsigned idx, inf_eps const& v) { void optsmt::update_lower(unsigned idx, inf_eps const& v) {
TRACE("opt", tout << "v" << idx << " >= " << v << "\n";);
m_lower_fmls[idx] = m_s->mk_ge(idx, v); m_lower_fmls[idx] = m_s->mk_ge(idx, v);
m_lower[idx] = v; m_lower[idx] = v;
} }
void optsmt::update_upper(unsigned idx, inf_eps const& v) { void optsmt::update_upper(unsigned idx, inf_eps const& v) {
TRACE("opt", tout << "v" << idx << " <= " << v << "\n";);
m_upper[idx] = v; m_upper[idx] = v;
} }
@ -302,6 +304,9 @@ namespace opt {
lbool is_sat = l_true; lbool is_sat = l_true;
expr_ref block(m), tmp(m); expr_ref block(m), tmp(m);
for (unsigned i = 0; i < obj_index; ++i) {
commit_assignment(i);
}
while (is_sat == l_true && !m_cancel) { while (is_sat == l_true && !m_cancel) {
is_sat = m_s->check_sat(0, 0); is_sat = m_s->check_sat(0, 0);
if (is_sat != l_true) break; if (is_sat != l_true) break;

View file

@ -1193,6 +1193,10 @@ public:
return m_assignment[v]; return m_assignment[v];
} }
void set_assignment(dl_var v, numeral const & n) {
m_assignment[v] = n;
}
unsigned get_timestamp() const { unsigned get_timestamp() const {
return m_timestamp; return m_timestamp;
} }

View file

@ -3944,10 +3944,12 @@ namespace smt {
if (refinalize) { if (refinalize) {
fcs = final_check(); fcs = final_check();
} }
TRACE("opt", tout << (refinalize?"refinalize":"no-op") << " " << fcs << "\n";);
if (fcs == FC_DONE) { if (fcs == FC_DONE) {
mk_proto_model(l_true); mk_proto_model(l_true);
m_model = m_proto_model->mk_model(); m_model = m_proto_model->mk_model();
} }
return fcs == FC_DONE; return fcs == FC_DONE;
} }

View file

@ -894,7 +894,7 @@ namespace smt {
void init_gains(theory_var x, bool inc, inf_numeral& min_gain, inf_numeral& max_gain); void init_gains(theory_var x, bool inc, inf_numeral& min_gain, inf_numeral& max_gain);
bool update_gains(bool inc, theory_var x_i, numeral const& a_ij, bool update_gains(bool inc, theory_var x_i, numeral const& a_ij,
inf_numeral& min_gain, inf_numeral& max_gain); inf_numeral& min_gain, inf_numeral& max_gain);
bool move_to_bound_new(theory_var x_i, bool inc, bool& best_effort, bool& has_shared); bool move_to_bound_new(theory_var x_i, bool inc, unsigned& best_efforts, bool& has_shared);
bool pick_var_to_leave( bool pick_var_to_leave(
theory_var x_j, bool inc, numeral & a_ij, theory_var x_j, bool inc, numeral & a_ij,
inf_numeral& min_gain, inf_numeral& max_gain, inf_numeral& min_gain, inf_numeral& max_gain,
@ -1036,7 +1036,7 @@ namespace smt {
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker, bool& has_shared); virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker, bool& has_shared);
virtual inf_eps_rational<inf_rational> value(theory_var v); virtual inf_eps_rational<inf_rational> value(theory_var v);
virtual theory_var add_objective(app* term); virtual theory_var add_objective(app* term);
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val); virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val);
void enable_record_conflict(expr* bound); void enable_record_conflict(expr* bound);
void record_conflict(unsigned num_lits, literal const * lits, void record_conflict(unsigned num_lits, literal const * lits,
unsigned num_eqs, enode_pair const * eqs, unsigned num_eqs, enode_pair const * eqs,

View file

@ -1189,7 +1189,7 @@ namespace smt {
This allows to handle inequalities with non-standard numbers. This allows to handle inequalities with non-standard numbers.
*/ */
template<typename Ext> template<typename Ext>
expr* theory_arith<Ext>::mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val) { expr_ref theory_arith<Ext>::mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val) {
ast_manager& m = get_manager(); ast_manager& m = get_manager();
context& ctx = get_context(); context& ctx = get_context();
std::ostringstream strm; std::ostringstream strm;
@ -1208,7 +1208,7 @@ namespace smt {
TRACE("arith", tout << mk_pp(b, m) << "\n"; TRACE("arith", tout << mk_pp(b, m) << "\n";
display_atom(tout, a, false);); display_atom(tout, a, false););
} }
return b; return expr_ref(b, m);
} }
@ -1658,9 +1658,17 @@ namespace smt {
bool is_tighter = false; bool is_tighter = false;
if (is_int(x_i)) den_aij = denominator(a_ij); if (is_int(x_i)) den_aij = denominator(a_ij);
SASSERT(den_aij.is_pos() && den_aij.is_int()); SASSERT(den_aij.is_pos() && den_aij.is_int());
if (is_int(x_i) && !den_aij.is_one()) {
SASSERT(min_gain.is_pos());
min_gain = inf_numeral(lcm(min_gain.get_rational(), den_aij));
normalize_gain(min_gain.get_rational(), max_gain);
}
if (!max_inc.is_minus_one()) { if (!max_inc.is_minus_one()) {
if (is_int(x_i)) { if (is_int(x_i)) {
normalize_gain(den_aij, max_inc); max_inc = floor(max_inc);
normalize_gain(min_gain.get_rational(), max_inc);
} }
if (unbounded_gain(max_gain)) { if (unbounded_gain(max_gain)) {
max_gain = max_inc; max_gain = max_inc;
@ -1671,13 +1679,6 @@ namespace smt {
is_tighter = true; is_tighter = true;
} }
} }
if (is_int(x_i)) {
SASSERT(min_gain.is_pos());
if (!den_aij.is_one()) {
min_gain = inf_numeral(lcm(min_gain.get_rational(), den_aij));
normalize_gain(den_aij, max_gain);
}
}
TRACE("opt", TRACE("opt",
tout << "v" << x_i << " a_ij " << a_ij << " " tout << "v" << x_i << " a_ij " << a_ij << " "
<< "min gain: " << min_gain << " " << "min gain: " << min_gain << " "
@ -1701,7 +1702,8 @@ namespace smt {
bool max, bool max,
bool& has_shared) { bool& has_shared) {
m_stats.m_max_min++; m_stats.m_max_min++;
bool best_effort = false, inc = false; unsigned best_efforts = 0;
bool inc = false;
SASSERT(valid_assignment()); SASSERT(valid_assignment());
@ -1712,7 +1714,8 @@ namespace smt {
#endif #endif
max_min_t result = OPTIMIZED; max_min_t result = OPTIMIZED;
has_shared = false; has_shared = false;
while (true) { unsigned max_efforts = 10 + (get_context().get_random_value() % 20);
while (best_efforts < max_efforts) {
theory_var x_j = null_theory_var; theory_var x_j = null_theory_var;
theory_var x_i = null_theory_var; theory_var x_i = null_theory_var;
max_gain.reset(); max_gain.reset();
@ -1734,10 +1737,11 @@ namespace smt {
if (!pick_var_to_leave(curr_x_j, curr_inc, curr_a_ij, if (!pick_var_to_leave(curr_x_j, curr_inc, curr_a_ij,
curr_min_gain, curr_max_gain, curr_min_gain, curr_max_gain,
has_shared, curr_x_i)) { has_shared, curr_x_i)) {
best_effort = true; best_efforts++;
continue; }
else {
SASSERT(safe_gain(curr_min_gain, curr_max_gain));
} }
SASSERT(safe_gain(curr_min_gain, curr_max_gain));
if (curr_x_i == null_theory_var) { if (curr_x_i == null_theory_var) {
TRACE("opt", tout << "unbounded\n";); TRACE("opt", tout << "unbounded\n";);
// we can increase/decrease curr_x_j as much as we want. // we can increase/decrease curr_x_j as much as we want.
@ -1770,7 +1774,7 @@ namespace smt {
} }
TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << max_gain << "\n"; TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << max_gain << "\n";
tout << "skipped row: " << (best_effort?"yes":"no") << "\n"; tout << "best efforts: " << best_efforts << "\n";
display(tout);); display(tout););
if (x_j == null_theory_var) { if (x_j == null_theory_var) {
@ -1781,7 +1785,7 @@ namespace smt {
} }
if (min_gain.is_pos() && !min_gain.is_one()) { if (min_gain.is_pos() && !min_gain.is_one()) {
best_effort = true; ++best_efforts;
} }
if (x_i == null_theory_var) { if (x_i == null_theory_var) {
// can increase/decrease x_j as much as we want. // can increase/decrease x_j as much as we want.
@ -1802,7 +1806,7 @@ namespace smt {
continue; continue;
} }
SASSERT(unbounded_gain(max_gain)); SASSERT(unbounded_gain(max_gain));
best_effort = false; best_efforts = 0;
result = UNBOUNDED; result = UNBOUNDED;
break; break;
} }
@ -1836,9 +1840,8 @@ namespace smt {
SASSERT(is_base(x_j)); SASSERT(is_base(x_j));
bool inc_xi = inc?a_ij.is_neg():a_ij.is_pos(); bool inc_xi = inc?a_ij.is_neg():a_ij.is_pos();
if (!move_to_bound_new(x_i, inc_xi, best_effort, has_shared)) { if (!move_to_bound_new(x_i, inc_xi, best_efforts, has_shared)) {
best_effort = true; // break;
break;
} }
row & r2 = m_rows[get_var_row(x_j)]; row & r2 = m_rows[get_var_row(x_j)];
@ -1848,7 +1851,7 @@ namespace smt {
SASSERT(valid_assignment()); SASSERT(valid_assignment());
} }
TRACE("opt", display(tout);); TRACE("opt", display(tout););
return best_effort?BEST_EFFORT:result; return (best_efforts>0)?BEST_EFFORT:result;
} }
/** /**
@ -1862,7 +1865,7 @@ namespace smt {
bool theory_arith<Ext>::move_to_bound_new( bool theory_arith<Ext>::move_to_bound_new(
theory_var x_i, // variable to move theory_var x_i, // variable to move
bool inc, // increment variable or decrement bool inc, // increment variable or decrement
bool& best_effort, // is bound move a best effort? unsigned& best_efforts, // is bound move a best effort?
bool& has_shared) { // does move include shared variables? bool& has_shared) { // does move include shared variables?
inf_numeral min_gain, max_gain; inf_numeral min_gain, max_gain;
init_gains(x_i, inc, min_gain, max_gain); init_gains(x_i, inc, min_gain, max_gain);
@ -1877,6 +1880,7 @@ namespace smt {
update_gains(inc, s, coeff, min_gain, max_gain); update_gains(inc, s, coeff, min_gain, max_gain);
has_shared |= get_context().is_shared(get_enode(s)); has_shared |= get_context().is_shared(get_enode(s));
} }
bool result = false;
if (safe_gain(min_gain, max_gain)) { if (safe_gain(min_gain, max_gain)) {
TRACE("opt", tout << "Safe delta: " << max_gain << "\n";); TRACE("opt", tout << "Safe delta: " << max_gain << "\n";);
SASSERT(!unbounded_gain(max_gain)); SASSERT(!unbounded_gain(max_gain));
@ -1884,12 +1888,15 @@ namespace smt {
max_gain.neg(); max_gain.neg();
} }
update_value(x_i, max_gain); update_value(x_i, max_gain);
best_effort = min_gain.is_pos() && !min_gain.is_one(); if (!min_gain.is_pos() || min_gain.is_one()) {
return !max_gain.is_zero(); ++best_efforts;
}
result = !max_gain.is_zero();
} }
else { if (!result) {
return false; ++best_efforts;
} }
return result;
} }
/** /**
@ -2004,7 +2011,7 @@ namespace smt {
add_tmp_row_entry<true>(m_tmp_row, it->m_coeff, it->m_var); add_tmp_row_entry<true>(m_tmp_row, it->m_coeff, it->m_var);
} }
} }
max_min_t r = max_min_orig(m_tmp_row, max, has_shared); max_min_t r = max_min_new(m_tmp_row, max, has_shared);
if (r == OPTIMIZED) { if (r == OPTIMIZED) {
TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n"; TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n";
display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row);); display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row););

View file

@ -198,6 +198,7 @@ namespace smt {
void del_vars(unsigned old_num_vars); void del_vars(unsigned old_num_vars);
void init_model(); void init_model();
bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective); bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective);
expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict);
#ifdef Z3DEBUG #ifdef Z3DEBUG
bool check_vector_sizes() const; bool check_vector_sizes() const;
bool check_matrix() const; bool check_matrix() const;
@ -270,8 +271,8 @@ namespace smt {
virtual inf_eps_rational<inf_rational> value(theory_var v); virtual inf_eps_rational<inf_rational> value(theory_var v);
virtual theory_var add_objective(app* term); virtual theory_var add_objective(app* term);
virtual expr_ref mk_gt(theory_var v, inf_rational const& val); virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; } virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val);
// ----------------------------------- // -----------------------------------
// //
// Main // Main

View file

@ -1030,6 +1030,17 @@ namespace smt {
template<typename Ext> template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) { expr_ref theory_dense_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) {
return mk_ineq(v, val, true);
}
template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_ge(
filter_model_converter& fm, theory_var v, inf_rational const& val) {
return mk_ineq(v, val, false);
}
template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) {
ast_manager& m = get_manager(); ast_manager& m = get_manager();
objective_term const& t = m_objectives[v]; objective_term const& t = m_objectives[v];
expr_ref e(m), f(m), f2(m); expr_ref e(m), f(m), f2(m);
@ -1052,19 +1063,32 @@ namespace smt {
else { else {
// //
expr_ref_vector const& core = m_objective_assignments[v]; expr_ref_vector const& core = m_objective_assignments[v];
f = m.mk_not(m.mk_and(core.size(), core.c_ptr())); f = m.mk_and(core.size(), core.c_ptr());
if (is_strict) {
f = m.mk_not(f);
}
TRACE("arith", tout << "block: " << f << "\n";); TRACE("arith", tout << "block: " << f << "\n";);
return f; return f;
} }
inf_rational new_val = val - inf_rational(m_objective_consts[v]); e = m_autil.mk_numeral(val.get_rational(), m.get_sort(f));
e = m_autil.mk_numeral(new_val.get_rational(), m.get_sort(f));
if (new_val.get_infinitesimal().is_neg()) { if (val.get_infinitesimal().is_neg()) {
f = m_autil.mk_ge(f, e); if (is_strict) {
f = m_autil.mk_ge(f, e);
}
else {
expr_ref_vector const& core = m_objective_assignments[v];
f = m.mk_and(core.size(), core.c_ptr());
}
} }
else { else {
f = m_autil.mk_gt(f, e); if (is_strict) {
f = m_autil.mk_gt(f, e);
}
else {
f = m_autil.mk_ge(f, e);
}
} }
return f; return f;
} }

View file

@ -324,13 +324,13 @@ namespace smt {
virtual inf_eps value(theory_var v); virtual inf_eps value(theory_var v);
virtual theory_var add_objective(app* term); virtual theory_var add_objective(app* term);
virtual expr_ref mk_gt(theory_var v, inf_rational const& val); virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; } virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val);
bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective); bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective);
private: private:
expr_ref block_objective(theory_var v, inf_rational const& val); expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict);
virtual void new_eq_eh(theory_var v1, theory_var v2, justification& j); virtual void new_eq_eh(theory_var v1, theory_var v2, justification& j);

View file

@ -546,7 +546,7 @@ void theory_diff_logic<Ext>::propagate_core() {
template<typename Ext> template<typename Ext>
bool theory_diff_logic<Ext>::propagate_atom(atom* a) { bool theory_diff_logic<Ext>::propagate_atom(atom* a) {
context& ctx = get_context(); context& ctx = get_context();
TRACE("arith", a->display(*this, tout); ); TRACE("arith", a->display(*this, tout); tout << "\n";);
if (ctx.inconsistent()) { if (ctx.inconsistent()) {
return false; return false;
} }
@ -1236,6 +1236,13 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
core.push_back(tmp); core.push_back(tmp);
} }
} }
compute_delta();
for (unsigned i = 0; i < m_graph.get_num_nodes(); ++i) {
unsigned w = node2simplex(i);
simplex::mpq_ext::eps_numeral const& val = S.get_value(w);
rational r = rational(val.first) + m_delta*rational(val.second);
m_graph.set_assignment(i, numeral(r));
}
blocker = mk_gt(v, r); blocker = mk_gt(v, r);
return inf_eps(rational(0), r + m_objective_consts[v]); return inf_eps(rational(0), r + m_objective_consts[v]);
} }
@ -1267,7 +1274,7 @@ theory_var theory_diff_logic<Ext>::add_objective(app* term) {
} }
template<typename Ext> template<typename Ext>
expr_ref theory_diff_logic<Ext>::block_objective(theory_var v, inf_rational const& val) { expr_ref theory_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) {
ast_manager& m = get_manager(); ast_manager& m = get_manager();
objective_term const& t = m_objectives[v]; objective_term const& t = m_objectives[v];
expr_ref e(m), f(m), f2(m); expr_ref e(m), f(m), f2(m);
@ -1290,7 +1297,10 @@ expr_ref theory_diff_logic<Ext>::block_objective(theory_var v, inf_rational cons
else { else {
// //
expr_ref_vector const& core = m_objective_assignments[v]; expr_ref_vector const& core = m_objective_assignments[v];
f = m.mk_not(m.mk_and(core.size(), core.c_ptr())); f = m.mk_and(core.size(), core.c_ptr());
if (is_strict) {
f = m.mk_not(f);
}
TRACE("arith", tout << "block: " << f << "\n";); TRACE("arith", tout << "block: " << f << "\n";);
return f; return f;
} }
@ -1299,18 +1309,35 @@ expr_ref theory_diff_logic<Ext>::block_objective(theory_var v, inf_rational cons
e = m_util.mk_numeral(new_val.get_rational(), m.get_sort(f)); e = m_util.mk_numeral(new_val.get_rational(), m.get_sort(f));
if (new_val.get_infinitesimal().is_neg()) { if (new_val.get_infinitesimal().is_neg()) {
f = m_util.mk_ge(f, e); if (is_strict) {
f = m_util.mk_ge(f, e);
}
else {
expr_ref_vector const& core = m_objective_assignments[v];
f = m.mk_and(core.size(), core.c_ptr());
}
} }
else { else {
f = m_util.mk_gt(f, e); if (is_strict) {
f = m_util.mk_gt(f, e);
}
else {
f = m_util.mk_ge(f, e);
}
} }
return f; return f;
} }
template<typename Ext> template<typename Ext>
expr_ref theory_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) { expr_ref theory_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) {
expr_ref o = block_objective(v, val); return mk_ineq(v, val, true);
return o; }
template<typename Ext>
expr_ref theory_diff_logic<Ext>::mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val) {
return mk_ineq(v, val, false);
}
#if 0 #if 0
context & ctx = get_context(); context & ctx = get_context();
model_ref mdl; model_ref mdl;
@ -1321,7 +1348,6 @@ expr_ref theory_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) {
expr_ref_vector implicants = impl_extractor.minimize_literals(formulas, mdl); expr_ref_vector implicants = impl_extractor.minimize_literals(formulas, mdl);
return m.mk_and(o, m.mk_not(m.mk_and(implicants.size(), implicants.c_ptr()))); return m.mk_and(o, m.mk_not(m.mk_and(implicants.size(), implicants.c_ptr())));
#endif #endif
}
template<typename Ext> template<typename Ext>
bool theory_diff_logic<Ext>::internalize_objective(expr * n, rational const& m, rational& q, objective_term & objective) { bool theory_diff_logic<Ext>::internalize_objective(expr * n, rational const& m, rational& q, objective_term & objective) {

View file

@ -33,7 +33,7 @@ namespace smt {
virtual inf_eps value(theory_var) = 0; virtual inf_eps value(theory_var) = 0;
virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) = 0; virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) = 0;
virtual theory_var add_objective(app* term) = 0; virtual theory_var add_objective(app* term) = 0;
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return 0; } virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return expr_ref(*((ast_manager*)0)); }
bool is_linear(ast_manager& m, expr* term); bool is_linear(ast_manager& m, expr* term);
bool is_numeral(arith_util& a, expr* term); bool is_numeral(arith_util& a, expr* term);
}; };