mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 20:18:18 +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();
|
lra.remove_fixed_vars_from_base();
|
||||||
lp_assert(lia.is_feasible());
|
lp_assert(lia.is_feasible());
|
||||||
for (unsigned j : lra.r_basis())
|
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);
|
patch_basic_column(j);
|
||||||
if (!lia.has_inf_int()) {
|
if (!lia.has_inf_int()) {
|
||||||
lia.settings().stats().m_patches_success++;
|
lia.settings().stats().m_patches_success++;
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
lar_solver::lar_solver() :
|
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_mpq_lar_core_solver(m_settings, *this),
|
||||||
m_var_register(false),
|
m_var_register(false),
|
||||||
m_term_register(true),
|
m_term_register(true),
|
||||||
|
@ -213,17 +214,10 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void lar_solver::fill_explanation_from_crossed_bounds_column(explanation& evidence) const {
|
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
|
// 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;
|
svector<constraint_index> deps;
|
||||||
m_dependencies.linearize(ul.upper_bound_witness(), deps);
|
SASSERT(m_crossed_bounds_deps != nullptr);
|
||||||
for (auto d : deps)
|
m_dependencies.linearize(m_crossed_bounds_deps, deps);
|
||||||
evidence.add_pair(d, numeric_traits<mpq>::one());
|
|
||||||
deps.reset();
|
|
||||||
m_dependencies.linearize(ul.lower_bound_witness(), deps);
|
|
||||||
for (auto d : deps)
|
for (auto d : deps)
|
||||||
evidence.add_pair(d, -numeric_traits<mpq>::one());
|
evidence.add_pair(d, -numeric_traits<mpq>::one());
|
||||||
}
|
}
|
||||||
|
@ -232,7 +226,8 @@ namespace lp {
|
||||||
m_simplex_strategy = m_settings.simplex_strategy();
|
m_simplex_strategy = m_settings.simplex_strategy();
|
||||||
m_simplex_strategy.push();
|
m_simplex_strategy.push();
|
||||||
m_columns_to_ul_pairs.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_mpq_lar_core_solver.push();
|
||||||
m_term_count = m_terms.size();
|
m_term_count = m_terms.size();
|
||||||
m_term_count.push();
|
m_term_count.push();
|
||||||
|
@ -262,7 +257,8 @@ namespace lp {
|
||||||
|
|
||||||
void lar_solver::pop(unsigned k) {
|
void lar_solver::pop(unsigned k) {
|
||||||
TRACE("lar_solver", tout << "k = " << k << std::endl;);
|
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);
|
unsigned n = m_columns_to_ul_pairs.peek_size(k);
|
||||||
m_var_register.shrink(n);
|
m_var_register.shrink(n);
|
||||||
pop_tableau(n);
|
pop_tableau(n);
|
||||||
|
@ -1021,7 +1017,7 @@ namespace lp {
|
||||||
|
|
||||||
void lar_solver::get_infeasibility_explanation(explanation& exp) const {
|
void lar_solver::get_infeasibility_explanation(explanation& exp) const {
|
||||||
exp.clear();
|
exp.clear();
|
||||||
if (m_crossed_bounds_column != -1) {
|
if (m_crossed_bounds_column != null_lpvar) {
|
||||||
fill_explanation_from_crossed_bounds_column(exp);
|
fill_explanation_from_crossed_bounds_column(exp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1828,7 +1824,6 @@ namespace lp {
|
||||||
|
|
||||||
if (is_base(j) && column_is_fixed(j))
|
if (is_base(j) && column_is_fixed(j))
|
||||||
m_fixed_base_var_set.insert(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;);
|
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) {
|
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(column_has_lower_bound(j) && column_has_upper_bound(j));
|
||||||
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed ||
|
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed ||
|
||||||
|
@ -1937,12 +1931,14 @@ namespace lp {
|
||||||
case LE: {
|
case LE: {
|
||||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GT:
|
case GT:
|
||||||
|
@ -1950,25 +1946,33 @@ namespace lp {
|
||||||
case GE: {
|
case GE: {
|
||||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
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;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
case EQ: {
|
case EQ: {
|
||||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
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]) {
|
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 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1979,7 +1983,7 @@ namespace lp {
|
||||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
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) {
|
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(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);
|
lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::lower_bound);
|
||||||
|
@ -1991,12 +1995,14 @@ namespace lp {
|
||||||
case LE: {
|
case LE: {
|
||||||
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
||||||
if (up < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GT:
|
case GT:
|
||||||
|
@ -2014,13 +2020,15 @@ namespace lp {
|
||||||
case EQ: {
|
case EQ: {
|
||||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||||
if (v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2051,26 +2059,29 @@ namespace lp {
|
||||||
{
|
{
|
||||||
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
||||||
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
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;
|
break;
|
||||||
case EQ:
|
case EQ:
|
||||||
{
|
{
|
||||||
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
||||||
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2345,7 +2356,21 @@ namespace lp {
|
||||||
return false;
|
return false;
|
||||||
return true;
|
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
|
} // namespace lp
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,8 @@ class lar_solver : public column_namer {
|
||||||
lp_status m_status = lp_status::UNKNOWN;
|
lp_status m_status = lp_status::UNKNOWN;
|
||||||
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
stacked_value<simplex_strategy_enum> m_simplex_strategy;
|
||||||
// such can be found at the initialization step: u < l
|
// 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;
|
lar_core_solver m_mpq_lar_core_solver;
|
||||||
int_solver* m_int_solver = nullptr;
|
int_solver* m_int_solver = nullptr;
|
||||||
bool m_need_register_terms = false;
|
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);
|
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(); }
|
inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); }
|
||||||
|
public:
|
||||||
void insert_to_columns_with_changed_bounds(unsigned j);
|
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_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);
|
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);
|
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_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_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);
|
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 register_in_fixed_var_table(unsigned, unsigned&);
|
||||||
void remove_non_fixed_from_fixed_var_table();
|
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);
|
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) {
|
void set_infeasible_column_and_witness(unsigned j, bool lower_bound, u_dependency* dep);
|
||||||
set_status(lp_status::INFEASIBLE);
|
|
||||||
m_crossed_bounds_column = j;
|
|
||||||
}
|
|
||||||
constraint_index add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term,
|
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);
|
lconstraint_kind kind, const mpq& right_side);
|
||||||
unsigned row_of_basic_column(unsigned) const;
|
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) {
|
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;
|
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);
|
track_column_feasibility(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,51 +258,113 @@ namespace nla {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void monomial_bounds::unit_propagate() {
|
bool monomial_bounds::unit_propagate() {
|
||||||
for (auto const& m : c().m_emons)
|
unsigned sz = 0;
|
||||||
unit_propagate(m);
|
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);
|
m_propagated.reserve(m.var() + 1, false);
|
||||||
if (m_propagated[m.var()])
|
if (m_propagated[m.var()])
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
if (!is_linear(m))
|
if (!is_linear(m))
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
c().trail().push(set_bitvector_trail(m_propagated, m.var()));
|
c().trail().push(set_bitvector_trail(m_propagated, m.var()));
|
||||||
|
lpvar zero_fixed = null_lpvar, non_fixed = null_lpvar;
|
||||||
rational k = fixed_var_product(m);
|
// find a zero fixed variable and a non-fixed variable
|
||||||
|
for (lpvar v : m) {
|
||||||
new_lemma lemma(c(), "fixed-values");
|
if (c().var_is_fixed(v)) {
|
||||||
if (k == 0) {
|
if (c().val(v).is_zero()) {
|
||||||
for (auto v : m) {
|
zero_fixed = v;
|
||||||
if (c().var_is_fixed(v) && c().val(v).is_zero()) {
|
|
||||||
lemma.explain_fixed(v);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lemma += ineq(m.var(), lp::lconstraint_kind::EQ, 0);
|
else {
|
||||||
}
|
non_fixed = v;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
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) {
|
bool monomial_bounds::is_linear(monic const& m) {
|
||||||
unsigned non_fixed = 0;
|
unsigned non_fixed = 0;
|
||||||
for (lpvar v : m) {
|
for (lpvar v : m) {
|
||||||
|
@ -324,12 +386,6 @@ namespace nla {
|
||||||
return r;
|
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
|
// monomial propagation
|
||||||
bool_vector m_propagated;
|
bool_vector m_propagated;
|
||||||
void unit_propagate(monic const& m);
|
bool unit_propagate(monic const& m);
|
||||||
bool is_linear(monic const& m);
|
bool is_linear(monic const& m);
|
||||||
rational fixed_var_product(monic const& m);
|
rational fixed_var_product(monic const& m);
|
||||||
lpvar non_fixed_var(monic const& m);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
monomial_bounds(core* core);
|
monomial_bounds(core* core);
|
||||||
void propagate();
|
void propagate();
|
||||||
void unit_propagate();
|
bool unit_propagate();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1818,14 +1818,18 @@ bool core::improve_bounds() {
|
||||||
}
|
}
|
||||||
return bounds_improved;
|
return bounds_improved;
|
||||||
}
|
}
|
||||||
|
// returns false if and only if makes lp_solver inconsistent
|
||||||
void core::propagate(vector<lemma>& lemmas) {
|
bool core::propagate(vector<lemma>& lemmas) {
|
||||||
// propagate linear monomials, those that have all, or all but one, variables fixed
|
// propagate linear monomials, those that have all, or all but one, variables fixed
|
||||||
lemmas.reset();
|
lemmas.reset();
|
||||||
m_lemma_vec = &lemmas;
|
m_lemma_vec = &lemmas;
|
||||||
|
|
||||||
m_monomial_bounds.unit_propagate();
|
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;
|
bool no_lemmas_hold() const;
|
||||||
|
|
||||||
void propagate(vector<lemma>& lemmas);
|
bool propagate(vector<lemma>& lemmas);
|
||||||
|
|
||||||
lbool test_check(vector<lemma>& l);
|
lbool test_check(vector<lemma>& l);
|
||||||
lpvar map_to_root(lpvar) const;
|
lpvar map_to_root(lpvar) const;
|
||||||
|
|
|
@ -1532,11 +1532,12 @@ namespace smt {
|
||||||
bool max,
|
bool max,
|
||||||
bool maintain_integrality,
|
bool maintain_integrality,
|
||||||
bool& has_shared) {
|
bool& has_shared) {
|
||||||
|
return UNBOUNDED;
|
||||||
|
|
||||||
m_stats.m_max_min++;
|
m_stats.m_max_min++;
|
||||||
unsigned best_efforts = 0;
|
unsigned best_efforts = 0;
|
||||||
bool inc = false;
|
bool inc = false;
|
||||||
|
|
||||||
|
|
||||||
SASSERT(!maintain_integrality || valid_assignment());
|
SASSERT(!maintain_integrality || valid_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
|
|
||||||
|
|
|
@ -511,6 +511,7 @@ bool theory_arith<Ext>::propagate_nl_downward(expr * n, var_power_pair const& p)
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool theory_arith<Ext>::propagate_nl_bounds(expr * m) {
|
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";);
|
TRACE("non_linear", tout << "propagate several bounds using:\n"; display_monomial(tout, m); tout << "\n";);
|
||||||
bool result = propagate_nl_upward(m);
|
bool result = propagate_nl_upward(m);
|
||||||
buffer<var_power_pair> vp;
|
buffer<var_power_pair> vp;
|
||||||
|
@ -530,6 +531,7 @@ bool theory_arith<Ext>::propagate_nl_bounds(expr * m) {
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool theory_arith<Ext>::propagate_nl_bounds() {
|
bool theory_arith<Ext>::propagate_nl_bounds() {
|
||||||
|
return false;
|
||||||
m_dep_manager.reset();
|
m_dep_manager.reset();
|
||||||
bool propagated = false;
|
bool propagated = false;
|
||||||
for (unsigned i = 0; i < m_nl_monomials.size(); i++) {
|
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>
|
template<typename Ext>
|
||||||
bool theory_arith<Ext>::is_cross_nested_consistent(svector<theory_var> const & nl_cluster) {
|
bool theory_arith<Ext>::is_cross_nested_consistent(svector<theory_var> const & nl_cluster) {
|
||||||
|
return true;
|
||||||
for (theory_var v : nl_cluster) {
|
for (theory_var v : nl_cluster) {
|
||||||
if (!is_base(v))
|
if (!is_base(v))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -2163,8 +2163,14 @@ public:
|
||||||
if (!m_nla)
|
if (!m_nla)
|
||||||
return;
|
return;
|
||||||
m_nla->propagate(m_nla_lemma_vector);
|
m_nla->propagate(m_nla_lemma_vector);
|
||||||
for (nla::lemma const& l : m_nla_lemma_vector)
|
if (lp().get_status() == lp::lp_status::INFEASIBLE) {
|
||||||
false_case_of_check_nla(l);
|
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 {
|
bool should_propagate() const {
|
||||||
|
|
Loading…
Reference in a new issue