mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 17:44:08 +00:00
propagate monomial is nla
This commit is contained in:
parent
318d7d7564
commit
41f59cb1ed
|
@ -31,7 +31,7 @@ namespace lp {
|
|||
lra.remove_fixed_vars_from_base();
|
||||
lp_assert(lia.is_feasible());
|
||||
for (unsigned j : lra.r_basis())
|
||||
if (!lra.get_value(j).is_int() && lra.column_is_int(j))
|
||||
if (!lra.get_value(j).is_int() && lra.column_is_int(j)&& !lia.is_fixed(j))
|
||||
patch_basic_column(j);
|
||||
if (!lia.has_inf_int()) {
|
||||
lia.settings().stats().m_patches_success++;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace lp {
|
|||
}
|
||||
|
||||
lar_solver::lar_solver() :
|
||||
m_crossed_bounds_column(-1),
|
||||
m_crossed_bounds_column(null_lpvar),
|
||||
m_crossed_bounds_deps(nullptr),
|
||||
m_mpq_lar_core_solver(m_settings, *this),
|
||||
m_var_register(false),
|
||||
m_term_register(true),
|
||||
|
@ -213,17 +214,10 @@ namespace lp {
|
|||
}
|
||||
|
||||
void lar_solver::fill_explanation_from_crossed_bounds_column(explanation& evidence) const {
|
||||
lp_assert(static_cast<int>(get_column_type(m_crossed_bounds_column)) >= static_cast<int>(column_type::boxed));
|
||||
lp_assert(!column_is_feasible(m_crossed_bounds_column));
|
||||
|
||||
// this is the case when the lower bound is in conflict with the upper one
|
||||
const ul_pair& ul = m_columns_to_ul_pairs[m_crossed_bounds_column];
|
||||
svector<constraint_index> deps;
|
||||
m_dependencies.linearize(ul.upper_bound_witness(), deps);
|
||||
for (auto d : deps)
|
||||
evidence.add_pair(d, numeric_traits<mpq>::one());
|
||||
deps.reset();
|
||||
m_dependencies.linearize(ul.lower_bound_witness(), deps);
|
||||
SASSERT(m_crossed_bounds_deps != nullptr);
|
||||
m_dependencies.linearize(m_crossed_bounds_deps, deps);
|
||||
for (auto d : deps)
|
||||
evidence.add_pair(d, -numeric_traits<mpq>::one());
|
||||
}
|
||||
|
@ -232,7 +226,8 @@ namespace lp {
|
|||
m_simplex_strategy = m_settings.simplex_strategy();
|
||||
m_simplex_strategy.push();
|
||||
m_columns_to_ul_pairs.push();
|
||||
m_crossed_bounds_column.push();
|
||||
m_crossed_bounds_column = null_lpvar;
|
||||
m_crossed_bounds_deps = nullptr;
|
||||
m_mpq_lar_core_solver.push();
|
||||
m_term_count = m_terms.size();
|
||||
m_term_count.push();
|
||||
|
@ -262,7 +257,8 @@ namespace lp {
|
|||
|
||||
void lar_solver::pop(unsigned k) {
|
||||
TRACE("lar_solver", tout << "k = " << k << std::endl;);
|
||||
m_crossed_bounds_column.pop(k);
|
||||
m_crossed_bounds_column = null_lpvar;
|
||||
m_crossed_bounds_deps = nullptr;
|
||||
unsigned n = m_columns_to_ul_pairs.peek_size(k);
|
||||
m_var_register.shrink(n);
|
||||
pop_tableau(n);
|
||||
|
@ -1021,7 +1017,7 @@ namespace lp {
|
|||
|
||||
void lar_solver::get_infeasibility_explanation(explanation& exp) const {
|
||||
exp.clear();
|
||||
if (m_crossed_bounds_column != -1) {
|
||||
if (m_crossed_bounds_column != null_lpvar) {
|
||||
fill_explanation_from_crossed_bounds_column(exp);
|
||||
return;
|
||||
}
|
||||
|
@ -1828,7 +1824,6 @@ namespace lp {
|
|||
|
||||
if (is_base(j) && column_is_fixed(j))
|
||||
m_fixed_base_var_set.insert(j);
|
||||
|
||||
TRACE("lar_solver_feas", tout << "j = " << j << " became " << (this->column_is_feasible(j) ? "feas" : "non-feas") << ", and " << (this->column_is_bounded(j) ? "bounded" : "non-bounded") << std::endl;);
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1919,6 @@ namespace lp {
|
|||
}
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) {
|
||||
lp_assert(column_has_lower_bound(j) && column_has_upper_bound(j));
|
||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed ||
|
||||
|
@ -1937,12 +1931,14 @@ namespace lp {
|
|||
case LE: {
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, true, dep);
|
||||
}
|
||||
else {
|
||||
if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return;
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, dep);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return;
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, dep);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
case GT:
|
||||
|
@ -1950,25 +1946,33 @@ namespace lp {
|
|||
case GE: {
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, false, dep);
|
||||
} else {
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
if (low < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
return;
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
|
||||
}
|
||||
case EQ: {
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j] || v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]){
|
||||
set_infeasible_column_and_witness(j, false, dep);
|
||||
}
|
||||
else if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column_and_witness(j, true, dep);
|
||||
}
|
||||
else {
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1979,7 +1983,7 @@ namespace lp {
|
|||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
|
||||
void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) {
|
||||
lp_assert(column_has_lower_bound(j) && !column_has_upper_bound(j));
|
||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::lower_bound);
|
||||
|
@ -1991,12 +1995,14 @@ namespace lp {
|
|||
case LE: {
|
||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, true, dep);
|
||||
}
|
||||
else {
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
||||
set_upper_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
break;
|
||||
}
|
||||
case GT:
|
||||
|
@ -2014,13 +2020,15 @@ namespace lp {
|
|||
case EQ: {
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, true, dep);
|
||||
}
|
||||
else {
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2051,26 +2059,29 @@ namespace lp {
|
|||
{
|
||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, false, dep);
|
||||
}
|
||||
else {
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed);
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
{
|
||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
||||
set_infeasible_column(j);
|
||||
set_infeasible_column_and_witness(j, false, dep);
|
||||
}
|
||||
else {
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
insert_to_columns_with_changed_bounds(j);
|
||||
}
|
||||
|
||||
set_upper_bound_witness(j, dep);
|
||||
set_lower_bound_witness(j, dep);
|
||||
m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v;
|
||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2345,7 +2356,21 @@ namespace lp {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
// If lower_bound is true than the new asserted upper bound is less than the existing lower bound.
|
||||
// Otherwise the new asserted lower bound is is greater than the existing upper bound.
|
||||
// dep is the reason for the new bound
|
||||
|
||||
void lar_solver::set_infeasible_column_and_witness(unsigned j, bool lower_bound, u_dependency* dep) {
|
||||
bool was_feas = column_is_feasible(j);
|
||||
bool in_heap = m_mpq_lar_core_solver.m_r_solver.inf_heap().contains(j);
|
||||
SASSERT(m_crossed_bounds_deps == nullptr && m_crossed_bounds_deps == nullptr);
|
||||
set_status(lp_status::INFEASIBLE);
|
||||
m_crossed_bounds_column = j;
|
||||
const auto& ul = this->m_columns_to_ul_pairs()[j];
|
||||
u_dependency* bdep = lower_bound? ul.lower_bound_witness() : ul.upper_bound_witness();
|
||||
SASSERT(bdep != nullptr);
|
||||
m_crossed_bounds_deps = m_dependencies.mk_join(bdep, dep);
|
||||
}
|
||||
} // namespace lp
|
||||
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ class lar_solver : public column_namer {
|
|||
lp_status m_status = lp_status::UNKNOWN;
|
||||
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
||||
// such can be found at the initialization step: u < l
|
||||
stacked_value<int> m_crossed_bounds_column;
|
||||
lpvar m_crossed_bounds_column;
|
||||
u_dependency* m_crossed_bounds_deps;
|
||||
lar_core_solver m_mpq_lar_core_solver;
|
||||
int_solver* m_int_solver = nullptr;
|
||||
bool m_need_register_terms = false;
|
||||
|
@ -139,10 +140,14 @@ class lar_solver : public column_namer {
|
|||
bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs);
|
||||
|
||||
inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); }
|
||||
public:
|
||||
void insert_to_columns_with_changed_bounds(unsigned j);
|
||||
private:
|
||||
void update_column_type_and_bound_check_on_equal(unsigned j, const mpq& right_side, constraint_index ci, unsigned&);
|
||||
void update_column_type_and_bound(unsigned j, const mpq& right_side, constraint_index ci);
|
||||
public:
|
||||
void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
|
||||
private:
|
||||
void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
|
||||
void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
|
||||
void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
|
||||
|
@ -152,10 +157,7 @@ class lar_solver : public column_namer {
|
|||
void register_in_fixed_var_table(unsigned, unsigned&);
|
||||
void remove_non_fixed_from_fixed_var_table();
|
||||
constraint_index add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq& right_side);
|
||||
inline void set_infeasible_column(unsigned j) {
|
||||
set_status(lp_status::INFEASIBLE);
|
||||
m_crossed_bounds_column = j;
|
||||
}
|
||||
void set_infeasible_column_and_witness(unsigned j, bool lower_bound, u_dependency* dep);
|
||||
constraint_index add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term,
|
||||
lconstraint_kind kind, const mpq& right_side);
|
||||
unsigned row_of_basic_column(unsigned) const;
|
||||
|
|
|
@ -540,9 +540,9 @@ public:
|
|||
}
|
||||
|
||||
void add_delta_to_x_and_track_feasibility(unsigned j, const X & del) {
|
||||
TRACE("lar_solver_feas_bug", tout << "del = " << del << ", was x[" << j << "] = " << m_x[j] << "\n";);
|
||||
TRACE("lar_solver_feas", tout << "del = " << del << ", was x[" << j << "] = " << m_x[j] << "\n";);
|
||||
m_x[j] += del;
|
||||
TRACE("lar_solver_feas_bug", tout << "became x[" << j << "] = " << m_x[j] << "\n";);
|
||||
TRACE("lar_solver_feas", tout << "became x[" << j << "] = " << m_x[j] << "\n";);
|
||||
track_column_feasibility(j);
|
||||
}
|
||||
|
||||
|
|
|
@ -258,51 +258,113 @@ namespace nla {
|
|||
}
|
||||
}
|
||||
|
||||
void monomial_bounds::unit_propagate() {
|
||||
for (auto const& m : c().m_emons)
|
||||
unit_propagate(m);
|
||||
bool monomial_bounds::unit_propagate() {
|
||||
unsigned sz = 0;
|
||||
vector<lpvar> monics_vars;
|
||||
for (auto const& m : c().m_emons) {
|
||||
monics_vars.push_back(m.var());
|
||||
sz++;
|
||||
}
|
||||
unsigned l = this->random();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
lpvar v = monics_vars[(i + l) % sz];
|
||||
if (!unit_propagate(c().m_emons[v])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void monomial_bounds::unit_propagate(monic const& m) {
|
||||
// returns false if and only if there is a conflict
|
||||
bool monomial_bounds::unit_propagate(monic const& m) {
|
||||
m_propagated.reserve(m.var() + 1, false);
|
||||
if (m_propagated[m.var()])
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (!is_linear(m))
|
||||
return;
|
||||
return true;
|
||||
|
||||
c().trail().push(set_bitvector_trail(m_propagated, m.var()));
|
||||
|
||||
rational k = fixed_var_product(m);
|
||||
|
||||
new_lemma lemma(c(), "fixed-values");
|
||||
if (k == 0) {
|
||||
for (auto v : m) {
|
||||
if (c().var_is_fixed(v) && c().val(v).is_zero()) {
|
||||
lemma.explain_fixed(v);
|
||||
lpvar zero_fixed = null_lpvar, non_fixed = null_lpvar;
|
||||
// find a zero fixed variable and a non-fixed variable
|
||||
for (lpvar v : m) {
|
||||
if (c().var_is_fixed(v)) {
|
||||
if (c().val(v).is_zero()) {
|
||||
zero_fixed = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lemma += ineq(m.var(), lp::lconstraint_kind::EQ, 0);
|
||||
}
|
||||
else {
|
||||
for (auto v : m)
|
||||
if (c().var_is_fixed(v))
|
||||
lemma.explain_fixed(v);
|
||||
|
||||
lpvar w = non_fixed_var(m);
|
||||
if (w != null_lpvar) {
|
||||
lp::lar_term term;
|
||||
term.add_var(m.var());
|
||||
term.add_monomial(-k, w);
|
||||
lemma += ineq(term, lp::lconstraint_kind::EQ, 0);
|
||||
} else {
|
||||
lemma += ineq(m.var(), lp::lconstraint_kind::EQ, k);
|
||||
else {
|
||||
non_fixed = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (zero_fixed != null_lpvar) {
|
||||
// the m.var() has to have a zero value
|
||||
u_dependency* d = this->dep.mk_join(c().lra.get_column_lower_bound_witness(zero_fixed),
|
||||
c().lra.get_column_upper_bound_witness(zero_fixed));
|
||||
|
||||
c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, mpq(0), d);
|
||||
} else if (non_fixed != null_lpvar) {
|
||||
u_dependency* d = nullptr;
|
||||
rational k(1);
|
||||
for (auto v : m)
|
||||
if (v != non_fixed) {
|
||||
d = this->dep.mk_join(d, c().lra.get_column_upper_bound_witness(v));
|
||||
d = this->dep.mk_join(d, c().lra.get_column_lower_bound_witness(v));
|
||||
k *= c().val(v);
|
||||
}
|
||||
SASSERT(k.is_pos() || k.is_neg());
|
||||
// we have m = k* non_fixed: m.var() getting the bounds witnesses of non_fixed
|
||||
if (k.is_pos()) {
|
||||
d = c().lra.get_column_upper_bound_witness(non_fixed);
|
||||
if (d) {
|
||||
const auto& b = c().lra.get_column_value(non_fixed);
|
||||
bool strict = b.y.is_neg();
|
||||
c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::LT : lp::lconstraint_kind::LE, k * b.x, d);
|
||||
}
|
||||
d = c().lra.get_column_lower_bound_witness(non_fixed);
|
||||
if (d) {
|
||||
const auto& b = c().lra.get_column_value(non_fixed);
|
||||
bool strict = b.y.is_pos();
|
||||
c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::GT : lp::lconstraint_kind::GE, k * b.x, d);
|
||||
}
|
||||
|
||||
} else {
|
||||
d = c().lra.get_column_upper_bound_witness(non_fixed);
|
||||
if (d) {
|
||||
const auto& b = c().lra.get_column_value(non_fixed);
|
||||
bool strict = b.y.is_neg();
|
||||
c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::GT : lp::lconstraint_kind::GE, k * b.x, d);
|
||||
}
|
||||
d = c().lra.get_column_lower_bound_witness(non_fixed);
|
||||
if (d) {
|
||||
const auto& b = c().lra.get_column_value(non_fixed);
|
||||
bool strict = b.y.is_pos();
|
||||
c().lra.update_column_type_and_bound(m.var(), strict ? lp::lconstraint_kind::LT : lp::lconstraint_kind::LE, k * b.x, d);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SASSERT(non_fixed == null_lpvar && zero_fixed == null_lpvar);
|
||||
rational k(1);
|
||||
u_dependency* d = nullptr;
|
||||
for (auto v : m) {
|
||||
SASSERT(c().var_is_fixed(v));
|
||||
d = this->dep.mk_join(d, c().lra.get_column_upper_bound_witness(v));
|
||||
d = this->dep.mk_join(d, c().lra.get_column_lower_bound_witness(v));
|
||||
k *= c().val(v);
|
||||
}
|
||||
SASSERT(k.is_pos() || k.is_neg());
|
||||
// we have m = k: m.var() getting the bounds witnesses of all fixed variables
|
||||
c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, k, d);
|
||||
}
|
||||
if (c().lra.get_status() == lp::lp_status::INFEASIBLE) {
|
||||
TRACE("nla_solver", tout << "conflict in unit_propagate\n";);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool monomial_bounds::is_linear(monic const& m) {
|
||||
unsigned non_fixed = 0;
|
||||
for (lpvar v : m) {
|
||||
|
@ -324,12 +386,6 @@ namespace nla {
|
|||
return r;
|
||||
}
|
||||
|
||||
lpvar monomial_bounds::non_fixed_var(monic const& m) {
|
||||
for (lpvar v : m)
|
||||
if (!c().var_is_fixed(v))
|
||||
return v;
|
||||
return null_lpvar;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,12 @@ namespace nla {
|
|||
|
||||
// monomial propagation
|
||||
bool_vector m_propagated;
|
||||
void unit_propagate(monic const& m);
|
||||
bool unit_propagate(monic const& m);
|
||||
bool is_linear(monic const& m);
|
||||
rational fixed_var_product(monic const& m);
|
||||
lpvar non_fixed_var(monic const& m);
|
||||
|
||||
public:
|
||||
monomial_bounds(core* core);
|
||||
void propagate();
|
||||
void unit_propagate();
|
||||
bool unit_propagate();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1818,14 +1818,18 @@ bool core::improve_bounds() {
|
|||
}
|
||||
return bounds_improved;
|
||||
}
|
||||
|
||||
void core::propagate(vector<lemma>& lemmas) {
|
||||
// returns false if and only if makes lp_solver inconsistent
|
||||
bool core::propagate(vector<lemma>& lemmas) {
|
||||
// propagate linear monomials, those that have all, or all but one, variables fixed
|
||||
lemmas.reset();
|
||||
m_lemma_vec = &lemmas;
|
||||
|
||||
m_monomial_bounds.unit_propagate();
|
||||
|
||||
if (lra.get_status() == lp::lp_status::INFEASIBLE) {
|
||||
TRACE("nla_solver", tout << "propagation found infeasibility\n";);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -392,7 +392,7 @@ public:
|
|||
|
||||
bool no_lemmas_hold() const;
|
||||
|
||||
void propagate(vector<lemma>& lemmas);
|
||||
bool propagate(vector<lemma>& lemmas);
|
||||
|
||||
lbool test_check(vector<lemma>& l);
|
||||
lpvar map_to_root(lpvar) const;
|
||||
|
|
|
@ -1532,11 +1532,12 @@ namespace smt {
|
|||
bool max,
|
||||
bool maintain_integrality,
|
||||
bool& has_shared) {
|
||||
return UNBOUNDED;
|
||||
|
||||
m_stats.m_max_min++;
|
||||
unsigned best_efforts = 0;
|
||||
bool inc = false;
|
||||
|
||||
|
||||
|
||||
SASSERT(!maintain_integrality || valid_assignment());
|
||||
SASSERT(satisfy_bounds());
|
||||
|
||||
|
|
|
@ -511,6 +511,7 @@ bool theory_arith<Ext>::propagate_nl_downward(expr * n, var_power_pair const& p)
|
|||
*/
|
||||
template<typename Ext>
|
||||
bool theory_arith<Ext>::propagate_nl_bounds(expr * m) {
|
||||
return false;
|
||||
TRACE("non_linear", tout << "propagate several bounds using:\n"; display_monomial(tout, m); tout << "\n";);
|
||||
bool result = propagate_nl_upward(m);
|
||||
buffer<var_power_pair> vp;
|
||||
|
@ -530,6 +531,7 @@ bool theory_arith<Ext>::propagate_nl_bounds(expr * m) {
|
|||
*/
|
||||
template<typename Ext>
|
||||
bool theory_arith<Ext>::propagate_nl_bounds() {
|
||||
return false;
|
||||
m_dep_manager.reset();
|
||||
bool propagated = false;
|
||||
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
||||
|
@ -1632,6 +1634,7 @@ bool theory_arith<Ext>::is_cross_nested_consistent(row const & r) {
|
|||
*/
|
||||
template<typename Ext>
|
||||
bool theory_arith<Ext>::is_cross_nested_consistent(svector<theory_var> const & nl_cluster) {
|
||||
return true;
|
||||
for (theory_var v : nl_cluster) {
|
||||
if (!is_base(v))
|
||||
continue;
|
||||
|
|
|
@ -2163,8 +2163,14 @@ public:
|
|||
if (!m_nla)
|
||||
return;
|
||||
m_nla->propagate(m_nla_lemma_vector);
|
||||
for (nla::lemma const& l : m_nla_lemma_vector)
|
||||
false_case_of_check_nla(l);
|
||||
if (lp().get_status() == lp::lp_status::INFEASIBLE) {
|
||||
TRACE("arith", tout << "propagation conflict\n";);
|
||||
get_infeasibility_explanation_and_set_conflict();
|
||||
}
|
||||
else {
|
||||
for (nla::lemma const& l : m_nla_lemma_vector)
|
||||
false_case_of_check_nla(l);
|
||||
}
|
||||
}
|
||||
|
||||
bool should_propagate() const {
|
||||
|
|
Loading…
Reference in a new issue