3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-21 21:33:39 +00:00

Perf branch (#4710)

* avoid creating rows with  all but one fixed columns

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* pb

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* once in a while flip bounds of boxed variables during move_nbasic_to_bounds

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* flip rarely

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* flip rarely

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* flip rarely

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* return an empty model when lar_solver is not ready

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* randomly change bounded base var on demand only

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* randomly change bounded base var on demand only

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2020-09-25 17:47:29 -07:00 committed by GitHub
parent e775964cfd
commit 25724401cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 72 additions and 70 deletions

View file

@ -210,7 +210,7 @@ lp_status lar_solver::solve() {
detect_rows_with_changed_bounds();
}
m_columns_with_changed_bound.clear();
clear_columns_with_changed_bounds();
return m_status;
}
@ -272,7 +272,7 @@ void lar_solver::pop(unsigned k) {
m_mpq_lar_core_solver.pop(k);
remove_non_fixed_from_fixed_var_table();
clean_popped_elements(n, m_columns_with_changed_bound);
clean_popped_elements(n, m_columns_with_changed_bounds);
clean_popped_elements(n, m_incorrect_columns);
unsigned m = A_r().row_count();
@ -335,7 +335,7 @@ bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const {
void lar_solver::set_costs_to_zero(const lar_term& term) {
auto & rslv = m_mpq_lar_core_solver.m_r_solver;
auto & jset = m_mpq_lar_core_solver.m_r_solver.inf_set(); // hijack this set that should be empty right now
lp_assert(jset.is_empty());
lp_assert(jset.empty());
for (const auto & p : term) {
unsigned j = p.column();
@ -361,7 +361,7 @@ void lar_solver::set_costs_to_zero(const lar_term& term) {
void lar_solver::prepare_costs_for_r_solver(const lar_term & term) {
TRACE("lar_solver", print_term(term, tout << "prepare: ") << "\n";);
m_basic_columns_with_changed_cost.resize(m_mpq_lar_core_solver.m_r_x.size());
move_non_basic_columns_to_bounds();
move_non_basic_columns_to_bounds(false);
auto & rslv = m_mpq_lar_core_solver.m_r_solver;
rslv.set_using_infeas_costs(false);
lp_assert(costs_are_zeros_for_r_solver());
@ -379,53 +379,63 @@ void lar_solver::prepare_costs_for_r_solver(const lar_term & term) {
lp_assert(rslv.reduced_costs_are_correct_tableau());
}
void lar_solver::move_non_basic_columns_to_bounds() {
void lar_solver::move_non_basic_columns_to_bounds(bool shift_randomly) {
auto & lcs = m_mpq_lar_core_solver;
bool change = false;
for (unsigned j : lcs.m_r_nbasis) {
if (move_non_basic_column_to_bounds(j))
if (move_non_basic_column_to_bounds(j, shift_randomly))
change = true;
}
if (settings().simplex_strategy() == simplex_strategy_enum::tableau_costs && change)
if (!change)
return;
if (settings().simplex_strategy() == simplex_strategy_enum::tableau_costs)
update_x_and_inf_costs_for_columns_with_changed_bounds_tableau();
if (change) {
find_feasible_solution();
}
find_feasible_solution();
}
bool lar_solver::move_non_basic_column_to_bounds(unsigned j) {
bool lar_solver::move_non_basic_column_to_bounds(unsigned j, bool force_change) {
auto & lcs = m_mpq_lar_core_solver;
auto & val = lcs.m_r_x[j];
switch (lcs.m_column_types()[j]) {
case column_type::boxed:
if (val != lcs.m_r_lower_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) {
if (m_settings.random_next() % 2 == 0)
case column_type::boxed: {
bool at_l = val == lcs.m_r_lower_bounds()[j];
bool at_u = !at_l && (val == lcs.m_r_upper_bounds()[j]);
if (!at_l && !at_u) {
if (m_settings.random_next() % 2)
set_value_for_nbasic_column(j, lcs.m_r_lower_bounds()[j]);
else
set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]);
return true;
}
break;
} else if (force_change && m_settings.random_next() % 3 == 0) {
set_value_for_nbasic_column(j,
at_l?lcs.m_r_upper_bounds()[j]:lcs.m_r_lower_bounds()[j]);
return true;
}
}
break;
case column_type::lower_bound:
if (val != lcs.m_r_lower_bounds()[j]) {
set_value_for_nbasic_column(j, lcs.m_r_lower_bounds()[j]);
return true;
}
break;
case column_type::fixed:
case column_type::upper_bound:
if (val != lcs.m_r_upper_bounds()[j]) {
set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]);
return true;
}
break;
default:
case column_type::free_column:
if (column_is_int(j) && !val.is_int()) {
set_value_for_nbasic_column(j, impq(floor(val)));
return true;
}
break;
default:
SASSERT(false);
}
return false;
}
@ -728,17 +738,17 @@ void lar_solver::detect_rows_with_changed_bounds_for_column(unsigned j) {
}
void lar_solver::detect_rows_with_changed_bounds() {
for (auto j : m_columns_with_changed_bound)
for (auto j : m_columns_with_changed_bounds)
detect_rows_with_changed_bounds_for_column(j);
}
void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds() {
for (auto j : m_columns_with_changed_bound)
for (auto j : m_columns_with_changed_bounds)
update_x_and_inf_costs_for_column_with_changed_bounds(j);
}
void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds_tableau() {
for (auto j : m_columns_with_changed_bound)
for (auto j : m_columns_with_changed_bounds)
update_x_and_inf_costs_for_column_with_changed_bounds(j);
if (tableau_with_costs()) {
@ -867,15 +877,6 @@ void lar_solver::copy_from_mpq_matrix(static_matrix<U, V> & matr) {
}
}
bool lar_solver::try_to_set_fixed(column_info<mpq> & ci) {
if (ci.upper_bound_is_set() && ci.lower_bound_is_set() && ci.get_upper_bound() == ci.get_lower_bound() && !ci.is_fixed()) {
ci.set_fixed_value(ci.get_upper_bound());
return true;
}
return false;
}
bool lar_solver::all_constrained_variables_are_registered(const vector<std::pair<mpq, var_index>>& left_side) {
for (auto it : left_side) {
if (! var_is_registered(it.second))
@ -1114,7 +1115,8 @@ void lar_solver::get_infeasibility_explanation_for_inf_sign(
// (x, y) != (x', y') => (x + delta*y) != (x' + delta*y')
void lar_solver::get_model(std::unordered_map<var_index, mpq> & variable_values) const {
if (!(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE)) {
if (!(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE) ||
!m_columns_with_changed_bounds.empty()) {
variable_values.clear();
return;
}
@ -1549,7 +1551,7 @@ bool lar_solver::external_is_used(unsigned v) const {
void lar_solver::add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int) {
register_new_ext_var_index(ext_j, is_int);
m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column);
m_columns_with_changed_bound.increase_size_by_one();
increase_by_one_columns_with_changed_bounds();
add_new_var_to_core_fields_for_mpq(false); // false for not adding a row
if (use_lu())
add_new_var_to_core_fields_for_doubles(false);
@ -1710,7 +1712,7 @@ void lar_solver::add_basic_var_to_core_fields() {
bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver();
lp_assert(!use_lu || A_r().column_count() == A_d().column_count());
m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column);
m_columns_with_changed_bound.increase_size_by_one();
increase_by_one_columns_with_changed_bounds();
m_incorrect_columns.increase_size_by_one();
m_rows_with_changed_bounds.increase_size_by_one();
add_new_var_to_core_fields_for_mpq(true);
@ -2019,7 +2021,7 @@ void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, con
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, ci);
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
}
break;
case GT:
@ -2034,7 +2036,7 @@ void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, con
return;
}
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
set_lower_bound_witness(j, ci);
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);
}
@ -2074,7 +2076,7 @@ void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind,
}
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
set_upper_bound_witness(j, ci);
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
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);
}
break;
@ -2087,7 +2089,7 @@ void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind,
return;
}
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
set_lower_bound_witness(j, ci);
}
break;
@ -2124,7 +2126,7 @@ void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind,
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, ci);
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
}
break;
case GT:
@ -2136,7 +2138,7 @@ void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind,
set_infeasible_column(j);
}
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
set_lower_bound_witness(j, ci);
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);
}
@ -2161,7 +2163,7 @@ void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind,
}
void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
lp_assert(!column_has_lower_bound(j) && !column_has_upper_bound(j));
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
mpq y_of_bound(0);
switch (kind) {
@ -2181,7 +2183,7 @@ void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kin
{
auto low = numeric_pair<mpq>(right_side, y_of_bound);
m_mpq_lar_core_solver.m_r_lower_bounds[j] = low;
m_columns_with_changed_bound.insert(j);
insert_to_columns_with_changed_bounds(j);
set_lower_bound_witness(j, ci);
m_mpq_lar_core_solver.m_column_types[j] = column_type::lower_bound;
}