mirror of
https://github.com/Z3Prover/z3
synced 2025-04-16 05:48:44 +00:00
bug fixes to min-max, and experiments with hsmax
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
2071029bb3
commit
57fc0f3f55
|
@ -37,6 +37,7 @@ Notes:
|
||||||
#include "opt_sls_solver.h"
|
#include "opt_sls_solver.h"
|
||||||
#include "cancel_eh.h"
|
#include "cancel_eh.h"
|
||||||
#include "scoped_timer.h"
|
#include "scoped_timer.h"
|
||||||
|
#include "optsmt.h"
|
||||||
|
|
||||||
namespace opt {
|
namespace opt {
|
||||||
|
|
||||||
|
@ -611,7 +612,11 @@ namespace opt {
|
||||||
};
|
};
|
||||||
|
|
||||||
scoped_ptr<maxsmt_solver_base> maxs;
|
scoped_ptr<maxsmt_solver_base> maxs;
|
||||||
|
optsmt m_optsmt; // hitting set optimizer based on simplex.
|
||||||
|
opt_solver m_solver;
|
||||||
|
unsigned m_objective; // index of objective
|
||||||
expr_ref_vector m_aux; // auxiliary (indicator) variables.
|
expr_ref_vector m_aux; // auxiliary (indicator) variables.
|
||||||
|
expr_ref_vector m_iaux; // auxiliary integer (indicator) variables.
|
||||||
expr_ref_vector m_naux; // negation of auxiliary variables.
|
expr_ref_vector m_naux; // negation of auxiliary variables.
|
||||||
obj_map<expr, unsigned> m_aux2index; // expr |-> index
|
obj_map<expr, unsigned> m_aux2index; // expr |-> index
|
||||||
unsigned_vector m_core_activity; // number of times soft constraint is used in a core.
|
unsigned_vector m_core_activity; // number of times soft constraint is used in a core.
|
||||||
|
@ -619,6 +624,7 @@ namespace opt {
|
||||||
svector<bool> m_aux_active; // active soft clauses.
|
svector<bool> m_aux_active; // active soft clauses.
|
||||||
ptr_vector<expr> m_asms; // assumptions (over aux)
|
ptr_vector<expr> m_asms; // assumptions (over aux)
|
||||||
pb_util pb;
|
pb_util pb;
|
||||||
|
arith_util a;
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
|
|
||||||
|
|
||||||
|
@ -626,20 +632,30 @@ namespace opt {
|
||||||
hsmax(solver* s, ast_manager& m, maxsmt_solver_base* maxs):
|
hsmax(solver* s, ast_manager& m, maxsmt_solver_base* maxs):
|
||||||
maxsmt_solver_base(s, m),
|
maxsmt_solver_base(s, m),
|
||||||
maxs(maxs),
|
maxs(maxs),
|
||||||
|
m_optsmt(m),
|
||||||
|
m_solver(m, m_params, symbol()),
|
||||||
m_aux(m),
|
m_aux(m),
|
||||||
|
m_iaux(m),
|
||||||
m_naux(m),
|
m_naux(m),
|
||||||
pb(m) {
|
pb(m),
|
||||||
|
a(m) {
|
||||||
}
|
}
|
||||||
virtual ~hsmax() {}
|
virtual ~hsmax() {}
|
||||||
|
|
||||||
virtual void set_cancel(bool f) {
|
virtual void set_cancel(bool f) {
|
||||||
maxsmt_solver_base::set_cancel(f);
|
maxsmt_solver_base::set_cancel(f);
|
||||||
maxs->set_cancel(f);
|
// maxs->set_cancel(f);
|
||||||
|
m_optsmt.set_cancel(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void updt_params(params_ref& p) {
|
||||||
|
maxsmt_solver_base::updt_params(p);
|
||||||
|
m_solver.updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collect_statistics(statistics& st) const {
|
virtual void collect_statistics(statistics& st) const {
|
||||||
maxsmt_solver_base::collect_statistics(st);
|
maxsmt_solver_base::collect_statistics(st);
|
||||||
maxs->collect_statistics(st);
|
// maxs->s().collect_statistics(st);
|
||||||
st.update("hsmax-num-iterations", m_stats.m_num_iterations);
|
st.update("hsmax-num-iterations", m_stats.m_num_iterations);
|
||||||
st.update("hsmax-num-core-reductions-n", m_stats.m_num_core_reductions_failure);
|
st.update("hsmax-num-core-reductions-n", m_stats.m_num_core_reductions_failure);
|
||||||
st.update("hsmax-num-core-reductions-y", m_stats.m_num_core_reductions_success);
|
st.update("hsmax-num-core-reductions-y", m_stats.m_num_core_reductions_success);
|
||||||
|
@ -702,9 +718,12 @@ namespace opt {
|
||||||
|
|
||||||
void init_local() {
|
void init_local() {
|
||||||
unsigned sz = num_soft();
|
unsigned sz = num_soft();
|
||||||
|
app_ref fml(m), obj(m);
|
||||||
|
expr_ref_vector sum(m);
|
||||||
m_asms.reset();
|
m_asms.reset();
|
||||||
m_seed.reset();
|
m_seed.reset();
|
||||||
m_aux.reset();
|
m_aux.reset();
|
||||||
|
m_iaux.reset();
|
||||||
m_naux.reset();
|
m_naux.reset();
|
||||||
m_aux_active.reset();
|
m_aux_active.reset();
|
||||||
m_aux2index.reset();
|
m_aux2index.reset();
|
||||||
|
@ -712,17 +731,28 @@ namespace opt {
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
bool tt = is_true(m_model, m_soft[i].get());
|
bool tt = is_true(m_model, m_soft[i].get());
|
||||||
m_seed.push_back(tt);
|
m_seed.push_back(tt);
|
||||||
m_aux. push_back(mk_fresh());
|
m_aux. push_back(mk_fresh(m.mk_bool_sort()));
|
||||||
|
m_iaux.push_back(mk_fresh(a.mk_int()));
|
||||||
|
expr* iaux = m_iaux.back();
|
||||||
m_naux.push_back(m.mk_not(m_aux.back()));
|
m_naux.push_back(m.mk_not(m_aux.back()));
|
||||||
m_aux_active.push_back(false);
|
m_aux_active.push_back(false);
|
||||||
m_core_activity.push_back(0);
|
m_core_activity.push_back(0);
|
||||||
m_aux2index.insert(m_aux[i].get(), i);
|
m_aux2index.insert(m_aux.back(), i);
|
||||||
|
m_aux2index.insert(m_iaux.back(), i);
|
||||||
|
fml = m.mk_and(a.mk_le(a.mk_numeral(rational::zero(), true), iaux),
|
||||||
|
a.mk_le(iaux, a.mk_numeral(rational::one(), true)));
|
||||||
|
rational const& w = m_weights[i];
|
||||||
|
sum.push_back(a.mk_mul(a.mk_numeral(w, w.is_int()), iaux));
|
||||||
|
m_solver.assert_expr(fml);
|
||||||
if (tt) {
|
if (tt) {
|
||||||
m_asms.push_back(m_aux.back());
|
m_asms.push_back(m_aux.back());
|
||||||
ensure_active(i);
|
ensure_active(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxs->init_soft(m_weights, m_aux);
|
obj = a.mk_add(sum.size(), sum.c_ptr());
|
||||||
|
m_objective = m_optsmt.add(obj);
|
||||||
|
m_optsmt.setup(m_solver);
|
||||||
|
// maxs->init_soft(m_weights, m_aux);
|
||||||
TRACE("opt", print_seed(tout););
|
TRACE("opt", print_seed(tout););
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,18 +888,6 @@ namespace opt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cancel_maxs {
|
|
||||||
hsmax& hs;
|
|
||||||
cancel_maxs(hsmax& hs):hs(hs) {}
|
|
||||||
void reset_cancel() {
|
|
||||||
hs.maxs->set_cancel(false);
|
|
||||||
}
|
|
||||||
void cancel() {
|
|
||||||
hs.maxs->set_cancel(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// retrieve the next seed that satisfies state of maxs.
|
// retrieve the next seed that satisfies state of maxs.
|
||||||
// state of maxs must be satisfiable before optimization is called.
|
// state of maxs must be satisfiable before optimization is called.
|
||||||
|
@ -881,6 +899,26 @@ namespace opt {
|
||||||
lbool next_seed() {
|
lbool next_seed() {
|
||||||
scoped_stopwatch _sw(m_stats.m_aux_sat_time);
|
scoped_stopwatch _sw(m_stats.m_aux_sat_time);
|
||||||
TRACE("opt", tout << "\n";);
|
TRACE("opt", tout << "\n";);
|
||||||
|
#if 1
|
||||||
|
m_solver.display(std::cout);
|
||||||
|
lbool is_sat = m_optsmt.lex(m_objective);
|
||||||
|
if (is_sat == l_true) {
|
||||||
|
model_ref mdl;
|
||||||
|
m_optsmt.get_model(mdl);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_soft(); ++i) {
|
||||||
|
if (is_active(i)) {
|
||||||
|
m_seed[i] = is_one(mdl, m_iaux[i].get());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_seed[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_seed(std::cout);
|
||||||
|
TRACE("opt", print_seed(tout););
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
lbool is_sat = maxs->s().check_sat(0,0);
|
lbool is_sat = maxs->s().check_sat(0,0);
|
||||||
if (is_sat == l_true) {
|
if (is_sat == l_true) {
|
||||||
maxs->set_model();
|
maxs->set_model();
|
||||||
|
@ -903,6 +941,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
TRACE("opt", print_seed(tout););
|
TRACE("opt", print_seed(tout););
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,6 +1109,16 @@ namespace opt {
|
||||||
}
|
}
|
||||||
expr_ref_vector fmls(m);
|
expr_ref_vector fmls(m);
|
||||||
expr_ref fml(m);
|
expr_ref fml(m);
|
||||||
|
#if 1
|
||||||
|
for (unsigned i = 0; i < num_soft(); ++i) {
|
||||||
|
if (!indices.contains(i)) {
|
||||||
|
fmls.push_back(m_iaux[i].get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fml = a.mk_ge(a.mk_add(fmls.size(), fmls.c_ptr()), a.mk_numeral(rational::one(), true));
|
||||||
|
m_solver.assert_expr(fml);
|
||||||
|
|
||||||
|
#else
|
||||||
for (unsigned i = 0; i < num_soft(); ++i) {
|
for (unsigned i = 0; i < num_soft(); ++i) {
|
||||||
if (!indices.contains(i)) {
|
if (!indices.contains(i)) {
|
||||||
fmls.push_back(m_aux[i].get());
|
fmls.push_back(m_aux[i].get());
|
||||||
|
@ -1077,8 +1126,9 @@ namespace opt {
|
||||||
}
|
}
|
||||||
fml = m.mk_or(fmls.size(), fmls.c_ptr());
|
fml = m.mk_or(fmls.size(), fmls.c_ptr());
|
||||||
maxs->add_hard(fml);
|
maxs->add_hard(fml);
|
||||||
|
#endif
|
||||||
TRACE("opt", tout << fml << "\n";);
|
TRACE("opt", tout << fml << "\n";);
|
||||||
set_upper();
|
// set_upper();
|
||||||
}
|
}
|
||||||
|
|
||||||
// constrain the upper bound.
|
// constrain the upper bound.
|
||||||
|
@ -1093,13 +1143,25 @@ namespace opt {
|
||||||
void block_up() {
|
void block_up() {
|
||||||
expr_ref_vector fmls(m);
|
expr_ref_vector fmls(m);
|
||||||
expr_ref fml(m);
|
expr_ref fml(m);
|
||||||
|
#if 1
|
||||||
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
||||||
|
unsigned index = m_aux2index.find(m_asms[i]);
|
||||||
|
m_core_activity[index]++;
|
||||||
|
fmls.push_back(m_iaux[index].get());
|
||||||
|
}
|
||||||
|
fml = a.mk_lt(a.mk_add(fmls.size(), fmls.c_ptr()), a.mk_numeral(rational(fmls.size()), true));
|
||||||
|
TRACE("opt", tout << fml << "\n";);
|
||||||
|
m_solver.assert_expr(fml);
|
||||||
|
#else
|
||||||
|
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
||||||
|
unsigned index = m_aux2index.find(m_asms[i]);
|
||||||
fmls.push_back(m.mk_not(m_asms[i]));
|
fmls.push_back(m.mk_not(m_asms[i]));
|
||||||
m_core_activity[m_aux2index.find(m_asms[i])]++;
|
m_core_activity[index]++;
|
||||||
}
|
}
|
||||||
fml = m.mk_or(fmls.size(), fmls.c_ptr());
|
fml = m.mk_or(fmls.size(), fmls.c_ptr());
|
||||||
TRACE("opt", tout << fml << "\n";);
|
TRACE("opt", tout << fml << "\n";);
|
||||||
maxs->add_hard(fml);
|
maxs->add_hard(fml);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1113,19 +1175,28 @@ namespace opt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app_ref mk_fresh() {
|
app_ref mk_fresh(sort* s) {
|
||||||
app_ref r(m);
|
app_ref r(m);
|
||||||
r = m.mk_fresh_const("r", m.mk_bool_sort());
|
r = m.mk_fresh_const("r", s);
|
||||||
m_mc->insert(r->get_decl());
|
m_mc->insert(r->get_decl());
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool is_true(model_ref& mdl, expr* e) {
|
bool is_true(model_ref& mdl, expr* e) {
|
||||||
expr_ref val(m);
|
expr_ref val(m);
|
||||||
VERIFY(mdl->eval(e, val));
|
VERIFY(mdl->eval(e, val));
|
||||||
return m.is_true(val);
|
return m.is_true(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_one(model_ref& mdl, expr* e) {
|
||||||
|
rational r;
|
||||||
|
expr_ref val(m);
|
||||||
|
VERIFY(mdl->eval(e, val));
|
||||||
|
std::cout << mk_pp(e, m) << " |-> " << val << "\n";
|
||||||
|
return a.is_numeral(val, r) && r.is_one();
|
||||||
|
}
|
||||||
|
|
||||||
bool is_active(unsigned i) const {
|
bool is_active(unsigned i) const {
|
||||||
return m_aux_active[i];
|
return m_aux_active[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -857,7 +857,7 @@ namespace smt {
|
||||||
void add_tmp_row(row & r1, numeral const & coeff, row const & r2);
|
void add_tmp_row(row & r1, numeral const & coeff, row const & r2);
|
||||||
theory_var pick_var_to_leave(bool has_int, theory_var x_j, bool inc, numeral & a_ij, inf_numeral & gain, bool& skiped_row);
|
theory_var pick_var_to_leave(bool has_int, theory_var x_j, bool inc, numeral & a_ij, inf_numeral & gain, bool& skiped_row);
|
||||||
bool is_safe_to_leave(theory_var x, bool& has_int);
|
bool is_safe_to_leave(theory_var x, bool& has_int);
|
||||||
void move_to_bound(theory_var x_i, bool inc);
|
bool move_to_bound(theory_var x_i, bool inc);
|
||||||
template<bool invert>
|
template<bool invert>
|
||||||
void add_tmp_row_entry(row & r, numeral const & coeff, theory_var v);
|
void add_tmp_row_entry(row & r, numeral const & coeff, theory_var v);
|
||||||
enum max_min_t { UNBOUNDED, AT_BOUND, OPTIMIZED, BEST_EFFORT};
|
enum max_min_t { UNBOUNDED, AT_BOUND, OPTIMIZED, BEST_EFFORT};
|
||||||
|
@ -1061,6 +1061,7 @@ namespace smt {
|
||||||
bool valid_row_assignment() const;
|
bool valid_row_assignment() const;
|
||||||
bool valid_row_assignment(row const & r) const;
|
bool valid_row_assignment(row const & r) const;
|
||||||
bool satisfy_bounds() const;
|
bool satisfy_bounds() const;
|
||||||
|
bool satisfy_integrality() const;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1069,7 +1069,7 @@ namespace smt {
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
||||||
TRACE("opt", tout << "data-size: " << m_data.size() << "\n";);
|
TRACE("bound_bug", display_var(tout, v); display(tout););
|
||||||
max_min_t r = max_min(v, true);
|
max_min_t r = max_min(v, true);
|
||||||
if (r == UNBOUNDED) {
|
if (r == UNBOUNDED) {
|
||||||
blocker = get_manager().mk_false();
|
blocker = get_manager().mk_false();
|
||||||
|
@ -1361,7 +1361,8 @@ namespace smt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << gain << "\n";
|
TRACE("opt", tout << "after traversing row:\nx_i: v" << x_i << ", x_j: v" << x_j << ", gain: " << gain << "\n";
|
||||||
tout << "skipped row: " << (skipped_row?"yes":"no") << "\n";);
|
tout << "skipped row: " << (skipped_row?"yes":"no") << "\n";
|
||||||
|
display(tout););
|
||||||
|
|
||||||
if (x_j == null_theory_var) {
|
if (x_j == null_theory_var) {
|
||||||
TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";);
|
TRACE("opt", tout << "row is " << (max ? "maximized" : "minimized") << "\n";);
|
||||||
|
@ -1378,6 +1379,7 @@ namespace smt {
|
||||||
TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";);
|
TRACE("opt", tout << "moved v" << x_j << " to upper bound\n";);
|
||||||
SASSERT(valid_row_assignment());
|
SASSERT(valid_row_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
|
SASSERT(satisfy_integrality());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!inc && lower(x_j)) {
|
if (!inc && lower(x_j)) {
|
||||||
|
@ -1385,13 +1387,14 @@ namespace smt {
|
||||||
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
TRACE("opt", tout << "moved v" << x_j << " to lower bound\n";);
|
||||||
SASSERT(valid_row_assignment());
|
SASSERT(valid_row_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
|
SASSERT(satisfy_integrality());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result = skipped_row?BEST_EFFORT:UNBOUNDED;
|
result = skipped_row?BEST_EFFORT:UNBOUNDED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_fixed(x_j) && is_bounded(x_j) && (upper_bound(x_j) - lower_bound(x_j) <= gain)) {
|
if (!is_fixed(x_j) && is_bounded(x_j) && !skipped_row && (upper_bound(x_j) - lower_bound(x_j) <= gain)) {
|
||||||
// can increase/decrease x_j up to upper/lower bound.
|
// can increase/decrease x_j up to upper/lower bound.
|
||||||
if (inc) {
|
if (inc) {
|
||||||
update_value(x_j, upper_bound(x_j) - get_value(x_j));
|
update_value(x_j, upper_bound(x_j) - get_value(x_j));
|
||||||
|
@ -1403,6 +1406,7 @@ namespace smt {
|
||||||
}
|
}
|
||||||
SASSERT(valid_row_assignment());
|
SASSERT(valid_row_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
|
SASSERT(satisfy_integrality());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,7 +1429,10 @@ namespace smt {
|
||||||
move_xi_to_lower = a_ij.is_pos();
|
move_xi_to_lower = a_ij.is_pos();
|
||||||
else
|
else
|
||||||
move_xi_to_lower = a_ij.is_neg();
|
move_xi_to_lower = a_ij.is_neg();
|
||||||
move_to_bound(x_i, move_xi_to_lower);
|
if (!move_to_bound(x_i, move_xi_to_lower)) {
|
||||||
|
result = BEST_EFFORT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
row & r2 = m_rows[get_var_row(x_j)];
|
row & r2 = m_rows[get_var_row(x_j)];
|
||||||
coeff.neg();
|
coeff.neg();
|
||||||
|
@ -1433,6 +1440,7 @@ namespace smt {
|
||||||
SASSERT(r.get_idx_of(x_j) == -1);
|
SASSERT(r.get_idx_of(x_j) == -1);
|
||||||
SASSERT(valid_row_assignment());
|
SASSERT(valid_row_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
|
SASSERT(satisfy_integrality());
|
||||||
}
|
}
|
||||||
TRACE("opt", display(tout););
|
TRACE("opt", display(tout););
|
||||||
return result;
|
return result;
|
||||||
|
@ -1444,7 +1452,7 @@ namespace smt {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void theory_arith<Ext>::move_to_bound(theory_var x_i, bool move_to_lower) {
|
bool theory_arith<Ext>::move_to_bound(theory_var x_i, bool move_to_lower) {
|
||||||
inf_numeral delta, delta_abs;
|
inf_numeral delta, delta_abs;
|
||||||
|
|
||||||
if (move_to_lower) {
|
if (move_to_lower) {
|
||||||
|
@ -1484,6 +1492,9 @@ namespace smt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_int(x_i)) {
|
||||||
|
delta_abs = floor(delta_abs);
|
||||||
|
}
|
||||||
|
|
||||||
if (move_to_lower) {
|
if (move_to_lower) {
|
||||||
delta = -delta_abs;
|
delta = -delta_abs;
|
||||||
|
@ -1493,8 +1504,8 @@ namespace smt {
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("opt", tout << "Safe delta: " << delta << "\n";);
|
TRACE("opt", tout << "Safe delta: " << delta << "\n";);
|
||||||
|
|
||||||
update_value(x_i, delta);
|
update_value(x_i, delta);
|
||||||
|
return !delta.is_zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -199,6 +199,18 @@ namespace smt {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
bool theory_arith<Ext>::satisfy_integrality() const {
|
||||||
|
int num = get_num_vars();
|
||||||
|
for (theory_var v = 0; v < num; v++) {
|
||||||
|
if (!(is_int(v) && get_value(v).is_int())) {
|
||||||
|
TRACE("bound_bug", display_var(tout, v); display(tout););
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue