3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-13 18:54:43 +00:00

shring lar_solver.h

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2025-05-08 19:23:55 -07:00
parent 0108a86490
commit 0a0979f804
2 changed files with 59 additions and 67 deletions

View file

@ -16,6 +16,30 @@ namespace lp {
}; };
struct lar_solver::imp { struct lar_solver::imp {
struct undo_add_column;
struct term_hasher {
std::size_t operator()(const lar_term& t) const {
using std::hash;
using std::size_t;
using std::string;
size_t seed = 0;
int i = 0;
for (const auto p : t) {
hash_combine(seed, (unsigned)p.j());
hash_combine(seed, p.coeff());
if (i++ > 10)
break;
}
return seed;
}
};
struct term_comparer {
bool operator()(const lar_term& a, const lar_term& b) const {
return a == b;
}
};
lar_solver &lra; lar_solver &lra;
var_register m_var_register; var_register m_var_register;
svector<column> m_columns; svector<column> m_columns;
@ -43,7 +67,7 @@ namespace lp {
unsigned_vector m_inf_index_copy; unsigned_vector m_inf_index_copy;
vector<lar_term*> m_terms; vector<lar_term*> m_terms;
indexed_vector<mpq> m_column_buffer; indexed_vector<mpq> m_column_buffer;
std::unordered_map<lar_term, std::pair<mpq, unsigned>, lar_solver::term_hasher, lar_solver::term_comparer> std::unordered_map<lar_term, std::pair<mpq, unsigned>, term_hasher, term_comparer>
m_normalized_terms_to_columns; m_normalized_terms_to_columns;
stacked_vector<unsigned> m_usage_in_terms; stacked_vector<unsigned> m_usage_in_terms;
@ -55,6 +79,8 @@ namespace lp {
mutable std::unordered_set<mpq> m_set_of_different_singles; mutable std::unordered_set<mpq> m_set_of_different_singles;
mutable mpq m_delta; mutable mpq m_delta;
bool m_validate_blocker = false;
void set_r_upper_bound(unsigned j, const impq& b) { void set_r_upper_bound(unsigned j, const impq& b) {
m_mpq_lar_core_solver.m_r_upper_bounds[j] = b; m_mpq_lar_core_solver.m_r_upper_bounds[j] = b;
@ -85,6 +111,34 @@ namespace lp {
m_imp.m_column_updates.pop_back(); m_imp.m_column_updates.pop_back();
} }
}; };
bool validate_bound(lpvar j, lconstraint_kind kind, const mpq& rs, u_dependency* dep) {
if (m_validate_blocker) return true;
lar_solver solver;
solver.m_validate_blocker = true;
TRACE("lar_solver_validate", tout << lra.get_variable_name(j) << " " << lconstraint_kind_string(kind) << " " << rs << std::endl;);
lra.add_dep_constraints_to_solver(solver, dep);
if (solver.external_to_local(j) == null_lpvar) {
return false; // we have to mention j in the dep
}
if (kind != EQ) {
lra.add_bound_negation_to_solver(solver, j, kind, rs);
solver.find_feasible_solution();
return solver.get_status() == lp_status::INFEASIBLE;
}
else {
solver.push();
lra.add_bound_negation_to_solver(solver, j, LE, rs);
solver.find_feasible_solution();
if (solver.get_status() != lp_status::INFEASIBLE)
return false;
solver.pop();
lra.add_bound_negation_to_solver(solver, j, GE, rs);
solver.find_feasible_solution();
return solver.get_status() == lp_status::INFEASIBLE;
}
}
}; };
unsigned_vector& lar_solver::row_bounds_to_replay() { return m_imp->m_row_bounds_to_replay; } unsigned_vector& lar_solver::row_bounds_to_replay() { return m_imp->m_row_bounds_to_replay; }
@ -798,15 +852,6 @@ namespace lp {
return lp_status::FEASIBLE; return lp_status::FEASIBLE;
} }
void lar_solver::pop_core_solver_params() {
pop_core_solver_params(1);
}
void lar_solver::pop_core_solver_params(unsigned k) {
A_r().pop(k);
}
void lar_solver::set_upper_bound_witness(lpvar j, u_dependency* dep, impq const& high) { void lar_solver::set_upper_bound_witness(lpvar j, u_dependency* dep, impq const& high) {
bool has_upper = m_imp->m_columns[j].upper_bound_witness() != nullptr; bool has_upper = m_imp->m_columns[j].upper_bound_witness() != nullptr;
m_imp->m_column_updates.push_back({true, j, get_upper_bound(j), m_imp->m_columns[j]}); m_imp->m_column_updates.push_back({true, j, get_upper_bound(j), m_imp->m_columns[j]});
@ -1838,7 +1883,7 @@ namespace lp {
return get_core_solver().column_is_free(j); return get_core_solver().column_is_free(j);
} }
struct lar_solver::undo_add_column : public trail { struct lar_solver::imp::undo_add_column : public trail {
lar_solver& s; lar_solver& s;
undo_add_column(lar_solver& s) : s(s) {} undo_add_column(lar_solver& s) : s(s) {}
void undo() override { void undo() override {
@ -1867,7 +1912,7 @@ namespace lp {
SASSERT(m_imp->m_columns.size() == A_r().column_count()); SASSERT(m_imp->m_columns.size() == A_r().column_count());
local_j = A_r().column_count(); local_j = A_r().column_count();
m_imp->m_columns.push_back(column()); m_imp->m_columns.push_back(column());
trail().push(undo_add_column(*this)); trail().push(imp::undo_add_column(*this));
while (m_imp->m_usage_in_terms.size() <= local_j) while (m_imp->m_usage_in_terms.size() <= local_j)
m_imp->m_usage_in_terms.push_back(0); m_imp->m_usage_in_terms.push_back(0);
add_non_basic_var_to_core_fields(ext_j, is_int); add_non_basic_var_to_core_fields(ext_j, is_int);
@ -1999,7 +2044,7 @@ namespace lp {
column ul(term); column ul(term);
term->set_j(j); // point from the term to the column term->set_j(j); // point from the term to the column
m_imp->m_columns.push_back(ul); m_imp->m_columns.push_back(ul);
m_imp->m_trail.push(undo_add_column(*this)); m_imp->m_trail.push(imp::undo_add_column(*this));
add_basic_var_to_core_fields(); add_basic_var_to_core_fields();
A_r().fill_last_row_with_pivoting(*term, A_r().fill_last_row_with_pivoting(*term,
@ -2167,31 +2212,7 @@ namespace lp {
bool lar_solver::validate_bound(lpvar j, lconstraint_kind kind, const mpq& rs, u_dependency* dep) { bool lar_solver::validate_bound(lpvar j, lconstraint_kind kind, const mpq& rs, u_dependency* dep) {
if (m_validate_blocker) return true; return m_imp->validate_bound(j, kind, rs, dep);
lar_solver solver;
solver.m_validate_blocker = true;
TRACE("lar_solver_validate", tout << "j = " << j << " " << lconstraint_kind_string(kind) << " " << rs << std::endl;);
add_dep_constraints_to_solver(solver, dep);
if (solver.external_to_local(j) == null_lpvar) {
return false; // we have to mention j in the dep
}
if (kind != EQ) {
add_bound_negation_to_solver(solver, j, kind, rs);
solver.find_feasible_solution();
return solver.get_status() == lp_status::INFEASIBLE;
}
else {
solver.push();
add_bound_negation_to_solver(solver, j, LE, rs);
solver.find_feasible_solution();
if (solver.get_status() != lp_status::INFEASIBLE)
return false;
solver.pop();
add_bound_negation_to_solver(solver, j, GE, rs);
solver.find_feasible_solution();
return solver.get_status() == lp_status::INFEASIBLE;
}
} }
void lar_solver::add_dep_constraints_to_solver(lar_solver& ls, u_dependency* dep) { void lar_solver::add_dep_constraints_to_solver(lar_solver& ls, u_dependency* dep) {

View file

@ -50,34 +50,8 @@ class int_solver;
class lar_solver : public column_namer { class lar_solver : public column_namer {
struct imp; struct imp;
struct term_hasher {
std::size_t operator()(const lar_term& t) const {
using std::hash;
using std::size_t;
using std::string;
size_t seed = 0;
int i = 0;
for (const auto p : t) {
hash_combine(seed, (unsigned)p.j());
hash_combine(seed, p.coeff());
if (i++ > 10)
break;
}
return seed;
}
};
struct term_comparer {
bool operator()(const lar_term& a, const lar_term& b) const {
return a == b;
}
};
// the struct imp of PIMPL
imp* m_imp; imp* m_imp;
////////////////// nested structs /////////////////////////
struct undo_add_column;
////////////////// methods //////////////////////////////// ////////////////// methods ////////////////////////////////
static bool valid_index(unsigned j) { return static_cast<int>(j) >= 0; } static bool valid_index(unsigned j) { return static_cast<int>(j) >= 0; }
@ -158,9 +132,6 @@ class lar_solver : public column_namer {
void prepare_costs_for_r_solver(const lar_term& term); void prepare_costs_for_r_solver(const lar_term& term);
bool maximize_term_on_feasible_r_solver(lar_term& term, impq& term_max, vector<std::pair<mpq,lpvar>>* max_coeffs); bool maximize_term_on_feasible_r_solver(lar_term& term, impq& term_max, vector<std::pair<mpq,lpvar>>* max_coeffs);
u_dependency* get_dependencies_of_maximum(const vector<std::pair<mpq,lpvar>>& max_coeffs); u_dependency* get_dependencies_of_maximum(const vector<std::pair<mpq,lpvar>>& max_coeffs);
void pop_core_solver_params();
void pop_core_solver_params(unsigned k);
void set_upper_bound_witness(lpvar j, u_dependency* ci, impq const& high); void set_upper_bound_witness(lpvar j, u_dependency* ci, impq const& high);
void set_lower_bound_witness(lpvar j, u_dependency* ci, impq const& low); void set_lower_bound_witness(lpvar j, u_dependency* ci, impq const& low);
void substitute_terms_in_linear_expression(const vector<std::pair<mpq, lpvar>>& left_side_with_terms, void substitute_terms_in_linear_expression(const vector<std::pair<mpq, lpvar>>& left_side_with_terms,