3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 14:13:23 +00:00
* rename ul_pair to column

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

* t

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

* simple test passed

* remove an assert

* relax an assertion

* remove an obsolete function

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

* access a term by the term column

* remove the column index from colunm.h

* remove an unused method

* remove debug code

* fix the build of lp_tst

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

---------

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
Co-authored-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Nikolaj Bjorner 2024-01-24 16:05:18 -08:00 committed by GitHub
parent 133546625c
commit bdb9106f99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 587 additions and 973 deletions

View file

@ -291,7 +291,6 @@ private:
int bound_sign = (is_lower_bound ? 1 : -1); int bound_sign = (is_lower_bound ? 1 : -1);
int j_sign = (coeff_before_j_is_pos ? 1 : -1) * bound_sign; int j_sign = (coeff_before_j_is_pos ? 1 : -1) * bound_sign;
SASSERT(!tv::is_term(bound_j));
u_dependency* ret = nullptr; u_dependency* ret = nullptr;
for (auto const& r : lar->get_row(row_index)) { for (auto const& r : lar->get_row(row_index)) {
unsigned j = r.var(); unsigned j = r.var();

View file

@ -37,16 +37,18 @@ inline std::ostream& operator<<(std::ostream& out, lconstraint_kind k) {
return out << "??"; return out << "??";
} }
inline bool compare(const std::pair<mpq, var_index> & a, const std::pair<mpq, var_index> & b) { inline bool compare(const std::pair<mpq, lpvar> & a, const std::pair<mpq, lpvar> & b) {
return a.second < b.second; return a.second < b.second;
} }
class lar_term; // forward definition
class ul_pair { class column {
u_dependency* m_lower_bound_witness = nullptr; u_dependency* m_lower_bound_witness = nullptr;
u_dependency* m_upper_bound_witness = nullptr; u_dependency* m_upper_bound_witness = nullptr;
bool m_associated_with_row = false; bool m_associated_with_row = false;
lpvar m_j; //the column index
lar_term* m_term = nullptr;
public: public:
// TODO - seems more straight-forward to just expose ul_pair as a struct with direct access to attributes. lar_term* term() const { return m_term; }
u_dependency*& lower_bound_witness() { return m_lower_bound_witness; } u_dependency*& lower_bound_witness() { return m_lower_bound_witness; }
u_dependency* lower_bound_witness() const { return m_lower_bound_witness; } u_dependency* lower_bound_witness() const { return m_lower_bound_witness; }
@ -56,20 +58,21 @@ public:
// equality is used by stackedvector operations. // equality is used by stackedvector operations.
// this appears to be a low level reason // this appears to be a low level reason
bool operator!=(const ul_pair & p) const { bool operator!=(const column & p) const {
return !(*this == p); return !(*this == p);
} }
bool operator==(const ul_pair & p) const { bool operator==(const column & p) const {
return m_lower_bound_witness == p.m_lower_bound_witness return m_lower_bound_witness == p.m_lower_bound_witness
&& m_upper_bound_witness == p.m_upper_bound_witness && m_upper_bound_witness == p.m_upper_bound_witness
&& m_associated_with_row == p.m_associated_with_row; && m_associated_with_row == p.m_associated_with_row;
} }
// empty constructor column() = delete;
ul_pair() {} column(bool) = delete;
ul_pair(bool associated_with_row) :
m_associated_with_row(associated_with_row) {} column(bool associated_with_row, lar_term* term) :
m_associated_with_row(associated_with_row), m_term(term) {}
bool associated_with_row() const { return m_associated_with_row; } bool associated_with_row() const { return m_associated_with_row; }
}; };

View file

@ -536,7 +536,7 @@ bool emonics::invariant() const {
do { do {
auto const& m = m_monics[c->m_index]; auto const& m = m_monics[c->m_index];
bool found = false; bool found = false;
for (lp::var_index w : m.rvars()) { for (lp::lpvar w : m.rvars()) {
auto w1 = m_ve.find(w); auto w1 = m_ve.find(w);
found |= v1.var() == w1.var(); found |= v1.var() == w1.var();
} }

View file

@ -109,7 +109,7 @@ public:
auto & row = m_data[adjust_row(i)]; auto & row = m_data[adjust_row(i)];
lp_assert(row_is_initialized_correctly(row)); lp_assert(row_is_initialized_correctly(row));
for (lp::lar_term::ival p : c) { for (lp::lar_term::ival p : c) {
unsigned j = adjust_column(column_fix(p.column().index())); unsigned j = adjust_column(column_fix(p.j()));
row[j] = sign * p.coeff(); row[j] = sign * p.coeff();
} }
} }

View file

@ -156,7 +156,7 @@ struct create_cut {
template <typename T> template <typename T>
void dump_coeff(std::ostream & out, const T& c) const { void dump_coeff(std::ostream & out, const T& c) const {
dump_coeff_val(out << "(* ", c.coeff()) << " " << var_name(c.column().index()) << ")"; dump_coeff_val(out << "(* ", c.coeff()) << " " << var_name(c.j()) << ")";
} }
std::ostream& dump_row_coefficients(std::ostream & out) const { std::ostream& dump_row_coefficients(std::ostream & out) const {
@ -183,9 +183,8 @@ struct create_cut {
for (const auto & p : m_row) for (const auto & p : m_row)
dump_declaration(out, p.var()); dump_declaration(out, p.var());
for (lar_term::ival p : m_t) { for (lar_term::ival p : m_t) {
auto t = lia.lra.column2tv(p.column()); if (lia.lra.column_has_term(p.j()))
if (t.is_term()) dump_declaration(out, p.j());
dump_declaration(out, t.id());
} }
} }
@ -491,9 +490,8 @@ public:
return all_of(t, [&](auto ci) { return ci.coeff().is_small(); }); return all_of(t, [&](auto ci) { return ci.coeff().is_small(); });
}; };
auto add_cut = [&](const lar_term& t, const mpq& k, u_dependency * dep) { auto add_cut = [&](const lar_term& t, const mpq& k, u_dependency * dep) {
lp::lpvar term_index = lra.add_term(t.coeffs_as_vector(), UINT_MAX); lp::lpvar j = lra.add_term(t.coeffs_as_vector(), UINT_MAX);
term_index = lra.map_term_index_to_column_index(term_index); lra.update_column_type_and_bound(j, lp::lconstraint_kind::GE, k, dep);
lra.update_column_type_and_bound(term_index, lp::lconstraint_kind::GE, k, dep);
}; };
auto _check_feasible = [&](void) { auto _check_feasible = [&](void) {
lra.find_feasible_solution(); lra.find_feasible_solution();

View file

@ -20,7 +20,7 @@ namespace lp {
lra(lia.lra), lra(lia.lra),
m_settings(lia.settings()), m_settings(lia.settings()),
m_abs_max(zero_of_type<mpq>()), m_abs_max(zero_of_type<mpq>()),
m_var_register(false) {} m_var_register() {}
bool hnf_cutter::is_full() const { bool hnf_cutter::is_full() const {
return return
@ -50,7 +50,7 @@ namespace lp {
m_constraints_for_explanation.push_back(ci); m_constraints_for_explanation.push_back(ci);
for (lar_term::ival p : *t) { for (lar_term::ival p : *t) {
m_var_register.add_var(p.column().index(), true); // hnf only deals with integral variables for now m_var_register.add_var(p.j(), true); // hnf only deals with integral variables for now
mpq t = abs(ceil(p.coeff())); mpq t = abs(ceil(p.coeff()));
if (t > m_abs_max) if (t > m_abs_max)
m_abs_max = t; m_abs_max = t;
@ -227,12 +227,12 @@ branch y_i >= ceil(y0_i) is impossible.
svector<unsigned> hnf_cutter::vars() const { return m_var_register.vars(); } svector<unsigned> hnf_cutter::vars() const { return m_var_register.vars(); }
void hnf_cutter::try_add_term_to_A_for_hnf(tv const &i) { void hnf_cutter::try_add_term_to_A_for_hnf(lpvar j) {
mpq rs; mpq rs;
const lar_term& t = lra.get_term(i); const lar_term& t = lra.get_term(j);
u_dependency* dep; u_dependency* dep;
bool upper_bound; bool upper_bound;
if (!is_full() && lra.get_equality_and_right_side_for_term_on_current_x(i, rs, dep, upper_bound)) { if (!is_full() && lra.get_equality_and_right_side_for_term_on_current_x(j, rs, dep, upper_bound)) {
add_term(&t, rs, dep, upper_bound); add_term(&t, rs, dep, upper_bound);
} }
} }
@ -243,8 +243,8 @@ branch y_i >= ceil(y0_i) is impossible.
bool hnf_cutter::init_terms_for_hnf_cut() { bool hnf_cutter::init_terms_for_hnf_cut() {
clear(); clear();
for (unsigned i = 0; i < lra.terms().size() && !is_full(); i++) for (const lar_term* t: lra.terms())
try_add_term_to_A_for_hnf(tv::term(i)); try_add_term_to_A_for_hnf(t->j());
return hnf_has_var_with_non_integral_value(); return hnf_has_var_with_non_integral_value();
} }

View file

@ -50,7 +50,7 @@ public:
private: private:
bool init_terms_for_hnf_cut(); bool init_terms_for_hnf_cut();
bool hnf_has_var_with_non_integral_value() const; bool hnf_has_var_with_non_integral_value() const;
void try_add_term_to_A_for_hnf(tv const& i); void try_add_term_to_A_for_hnf(lpvar);
unsigned terms_count() const { return m_terms.size(); } unsigned terms_count() const { return m_terms.size(); }
const mpq & abs_max() const { return m_abs_max; } const mpq & abs_max() const { return m_abs_max; }

View file

@ -34,7 +34,7 @@ lia_move int_branch::create_branch_on_column(int j) {
lia.m_t.clear(); lia.m_t.clear();
lp_assert(j != -1); lp_assert(j != -1);
lia.m_t.add_monomial(mpq(1), lra.column_to_reported_index(j)); lia.m_t.add_monomial(mpq(1), j);
if (lia.is_free(j)) { if (lia.is_free(j)) {
lia.m_upper = lia.random() % 2; lia.m_upper = lia.random() % 2;
lia.m_k = mpq(0); lia.m_k = mpq(0);

View file

@ -55,21 +55,21 @@ namespace lp {
lia.settings().stats().m_cube_success++; lia.settings().stats().m_cube_success++;
return lia_move::sat; return lia_move::sat;
} }
// i is the column index having the term
bool int_cube::tighten_term_for_cube(unsigned i) { bool int_cube::tighten_term_for_cube(unsigned i) {
if (!lra.term_is_used_as_row(i)) if (!lra.column_associated_with_row(i))
return true; return true;
const lar_term* t = lra.terms()[i]; const lar_term& t = lra.get_term(i);
impq delta = get_cube_delta_for_term(*t); impq delta = get_cube_delta_for_term(t);
TRACE("cube", lra.print_term_as_indices(*t, tout); tout << ", delta = " << delta << "\n";); TRACE("cube", lra.print_term_as_indices(t, tout); tout << ", delta = " << delta << "\n";);
if (is_zero(delta)) if (is_zero(delta))
return true; return true;
return lra.tighten_term_bounds_by_delta(tv::term(i), delta); return lra.tighten_term_bounds_by_delta(i, delta);
} }
bool int_cube::tighten_terms_for_cube() { bool int_cube::tighten_terms_for_cube() {
for (unsigned i = 0; i < lra.terms().size(); i++) for (const lar_term* t: lra.terms())
if (!tighten_term_for_cube(i)) { if (!tighten_term_for_cube(t->j())) {
TRACE("cube", tout << "cannot tighten";); TRACE("cube", tout << "cannot tighten";);
return false; return false;
} }
@ -86,7 +86,7 @@ namespace lp {
bool seen_minus = false; bool seen_minus = false;
bool seen_plus = false; bool seen_plus = false;
for(lar_term::ival p : t) { for(lar_term::ival p : t) {
if (!lia.column_is_int(p.column())) if (!lia.column_is_int(p.j()))
goto usual_delta; goto usual_delta;
const mpq & c = p.coeff(); const mpq & c = p.coeff();
if (c == one_of_type<mpq>()) { if (c == one_of_type<mpq>()) {
@ -104,7 +104,7 @@ namespace lp {
usual_delta: usual_delta:
mpq delta = zero_of_type<mpq>(); mpq delta = zero_of_type<mpq>();
for (lar_term::ival p : t) for (lar_term::ival p : t)
if (lia.column_is_int(p.column())) if (lia.column_is_int(p.j()))
delta += abs(p.coeff()); delta += abs(p.coeff());
delta *= mpq(1, 2); delta *= mpq(1, 2);

View file

@ -228,7 +228,7 @@ namespace lp {
bool int_solver::cut_indices_are_columns() const { bool int_solver::cut_indices_are_columns() const {
for (lar_term::ival p : m_t) { for (lar_term::ival p : m_t) {
if (p.column().index() >= lra.A_r().column_count()) if (p.j() >= lra.A_r().column_count())
return false; return false;
} }
return true; return true;
@ -271,7 +271,7 @@ namespace lp {
return lra.settings(); return lra.settings();
} }
bool int_solver::column_is_int(column_index const& j) const { bool int_solver::column_is_int(lpvar j) const {
return lra.column_is_int(j); return lra.column_is_int(j);
} }
@ -296,7 +296,7 @@ namespace lp {
} }
bool int_solver::is_term(unsigned j) const { bool int_solver::is_term(unsigned j) const {
return lra.column_corresponds_to_term(j); return lra.column_has_term(j);
} }
unsigned int_solver::column_count() const { unsigned int_solver::column_count() const {

View file

@ -83,7 +83,7 @@ public:
bool is_real(unsigned j) const; bool is_real(unsigned j) const;
const impq & lower_bound(unsigned j) const; const impq & lower_bound(unsigned j) const;
const impq & upper_bound(unsigned j) const; const impq & upper_bound(unsigned j) const;
bool column_is_int(column_index const& j) const; bool column_is_int(lpvar j) const;
const impq & get_value(unsigned j) const; const impq & get_value(unsigned j) const;
bool at_lower(unsigned j) const; bool at_lower(unsigned j) const;
bool at_upper(unsigned j) const; bool at_upper(unsigned j) const;

View file

@ -16,7 +16,7 @@ Author:
#include "util/region.h" #include "util/region.h"
#include "util/stacked_value.h" #include "util/stacked_value.h"
#include "math/lp/lp_utils.h" #include "math/lp/lp_utils.h"
#include "math/lp/ul_pair.h" #include "math/lp/column.h"
#include "math/lp/lar_term.h" #include "math/lp/lar_term.h"
#include "math/lp/column_namer.h" #include "math/lp/column_namer.h"
namespace lp { namespace lp {
@ -46,7 +46,7 @@ class lar_base_constraint {
public: public:
virtual vector<std::pair<mpq, var_index>> coeffs() const = 0; virtual vector<std::pair<mpq, lpvar>> coeffs() const = 0;
lar_base_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) : lar_base_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) :
m_kind(kind), m_right_side(right_side), m_active(false), m_j(j), m_dep(dep) {} m_kind(kind), m_right_side(right_side), m_active(false), m_j(j), m_dep(dep) {}
virtual ~lar_base_constraint() = default; virtual ~lar_base_constraint() = default;
@ -69,8 +69,8 @@ public:
lar_var_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) : lar_var_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) :
lar_base_constraint(j, kind, dep, right_side) {} lar_base_constraint(j, kind, dep, right_side) {}
vector<std::pair<mpq, var_index>> coeffs() const override { vector<std::pair<mpq, lpvar>> coeffs() const override {
vector<std::pair<mpq, var_index>> ret; vector<std::pair<mpq, lpvar>> ret;
ret.push_back(std::make_pair(one_of_type<mpq>(), column())); ret.push_back(std::make_pair(one_of_type<mpq>(), column()));
return ret; return ret;
} }
@ -84,7 +84,7 @@ public:
lar_term_constraint(unsigned j, const lar_term* t, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) : lar_term_constraint(unsigned j, const lar_term* t, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) :
lar_base_constraint(j, kind, dep, right_side), m_term(t) {} lar_base_constraint(j, kind, dep, right_side), m_term(t) {}
vector<std::pair<mpq, var_index>> coeffs() const override { return m_term->coeffs_as_vector(); } vector<std::pair<mpq, lpvar>> coeffs() const override { return m_term->coeffs_as_vector(); }
unsigned size() const override { return m_term->size();} unsigned size() const override { return m_term->size();}
}; };
@ -168,7 +168,7 @@ public:
m_region.pop_scope(k); m_region.pop_scope(k);
} }
constraint_index add_var_constraint(var_index j, lconstraint_kind k, mpq const& rhs) { constraint_index add_var_constraint(lpvar j, lconstraint_kind k, mpq const& rhs) {
return add(new (m_region) lar_var_constraint(j, k, mk_dep(), rhs)); return add(new (m_region) lar_var_constraint(j, k, mk_dep(), rhs));
} }

File diff suppressed because it is too large Load diff

View file

@ -59,7 +59,7 @@ class lar_solver : public column_namer {
size_t seed = 0; size_t seed = 0;
int i = 0; int i = 0;
for (const auto p : t) { for (const auto p : t) {
hash_combine(seed, (unsigned)p.column()); hash_combine(seed, (unsigned)p.j());
hash_combine(seed, p.coeff()); hash_combine(seed, p.coeff());
if (i++ > 10) if (i++ > 10)
break; break;
@ -86,8 +86,7 @@ class lar_solver : public column_namer {
int_solver* m_int_solver = nullptr; int_solver* m_int_solver = nullptr;
bool m_need_register_terms = false; bool m_need_register_terms = false;
var_register m_var_register; var_register m_var_register;
var_register m_term_register; svector<column> m_columns;
svector<ul_pair> m_columns_to_ul_pairs;
constraint_set m_constraints; constraint_set m_constraints;
// the set of column indices j such that bounds have changed for j // the set of column indices j such that bounds have changed for j
indexed_uint_set m_columns_with_changed_bounds; indexed_uint_set m_columns_with_changed_bounds;
@ -119,16 +118,13 @@ class lar_solver : public column_namer {
////////////////// nested structs ///////////////////////// ////////////////// nested structs /////////////////////////
struct undo_add_column; struct undo_add_column;
struct undo_add_term;
////////////////// 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; }
const lar_term& get_term(unsigned j) const;
bool row_has_a_big_num(unsigned i) const; bool row_has_a_big_num(unsigned i) const;
// init region // init region
bool strategy_is_undecided() const; void register_new_external_var(unsigned ext_v, bool is_int);
void register_new_ext_var_index(unsigned ext_v, bool is_int);
bool term_is_int(const lar_term* t) const; bool term_is_int(const lar_term* t) const;
bool term_is_int(const vector<std::pair<mpq, unsigned int>>& coeffs) const; bool term_is_int(const vector<std::pair<mpq, unsigned int>>& coeffs) const;
void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int); void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int);
@ -136,10 +132,9 @@ class lar_solver : public column_namer {
mpq adjust_bound_for_int(lpvar j, lconstraint_kind&, const mpq&); mpq adjust_bound_for_int(lpvar j, lconstraint_kind&, const mpq&);
// terms // terms
bool all_vars_are_registered(const vector<std::pair<mpq, var_index>>& coeffs); bool all_vars_are_registered(const vector<std::pair<mpq, lpvar>>& coeffs);
bool term_coeffs_are_ok(const vector<std::pair<mpq, var_index>>& coeffs); bool term_coeffs_are_ok(const vector<std::pair<mpq, lpvar>>& coeffs);
void push_term(lar_term* t); void add_row_from_term_no_constraint(lar_term* term, unsigned term_ext_index);
void add_row_from_term_no_constraint(const lar_term* term, unsigned term_ext_index);
void add_basic_var_to_core_fields(); void add_basic_var_to_core_fields();
bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs); bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs);
@ -168,27 +163,20 @@ class lar_solver : public column_namer {
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: private:
void require_nbasis_sort() { m_mpq_lar_core_solver.m_r_solver.m_nbasis_sort_counter = 0; } void require_nbasis_sort() { m_mpq_lar_core_solver.m_r_solver.m_nbasis_sort_counter = 0; }
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(lpvar 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(lpvar 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(lpvar j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
void update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); void update_bound_with_no_ub_lb(lpvar j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
void update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); void update_bound_with_ub_no_lb(lpvar j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
void update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); void update_bound_with_no_ub_no_lb(lpvar j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep);
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(lpvar j, lconstraint_kind kind, const mpq& right_side);
void set_crossed_bounds_column_and_deps(unsigned j, bool lower_bound, u_dependency* dep); void set_crossed_bounds_column_and_deps(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; unsigned row_of_basic_column(unsigned) const;
void decide_on_strategy_and_adjust_initial_state();
void adjust_initial_state();
void adjust_initial_state_for_tableau_rows();
bool sizes_are_correct() const; bool sizes_are_correct() const;
bool implied_bound_is_correctly_explained(implied_bound const& be, const vector<std::pair<mpq, unsigned>>& explanation) const; bool implied_bound_is_correctly_explained(implied_bound const& be, const vector<std::pair<mpq, unsigned>>& explanation) const;
void substitute_basis_var_in_terms_for_row(unsigned i);
template <typename T> template <typename T>
unsigned calculate_implied_bounds_for_row(unsigned row_index, lp_bound_propagator<T>& bp) { unsigned calculate_implied_bounds_for_row(unsigned row_index, lp_bound_propagator<T>& bp) {
if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation || row_has_a_big_num(row_index)) if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation || row_has_a_big_num(row_index))
@ -214,10 +202,10 @@ class lar_solver : public column_namer {
void pop_core_solver_params(); void pop_core_solver_params();
void pop_core_solver_params(unsigned k); void pop_core_solver_params(unsigned k);
void set_upper_bound_witness(var_index j, u_dependency* ci); void set_upper_bound_witness(lpvar j, u_dependency* ci);
void set_lower_bound_witness(var_index j, u_dependency* ci); void set_lower_bound_witness(lpvar j, u_dependency* ci);
void substitute_terms_in_linear_expression(const vector<std::pair<mpq, var_index>>& left_side_with_terms, void substitute_terms_in_linear_expression(const vector<std::pair<mpq, lpvar>>& left_side_with_terms,
vector<std::pair<mpq, var_index>>& left_side) const; vector<std::pair<mpq, lpvar>>& left_side) const;
bool use_tableau_costs() const; bool use_tableau_costs() const;
bool tableau_with_costs() const; bool tableau_with_costs() const;
@ -231,11 +219,11 @@ class lar_solver : public column_namer {
void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau(); void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau();
void solve_with_core_solver(); void solve_with_core_solver();
numeric_pair<mpq> get_basic_var_value_from_row(unsigned i); numeric_pair<mpq> get_basic_var_value_from_row(unsigned i);
bool all_constrained_variables_are_registered(const vector<std::pair<mpq, var_index>>& left_side); bool all_constrained_variables_are_registered(const vector<std::pair<mpq, lpvar>>& left_side);
bool all_constraints_hold() const; bool all_constraints_hold() const;
bool constraint_holds(const lar_base_constraint& constr, std::unordered_map<var_index, mpq>& var_map) const; bool constraint_holds(const lar_base_constraint& constr, std::unordered_map<lpvar, mpq>& var_map) const;
static void register_in_map(std::unordered_map<var_index, mpq>& coeffs, const lar_base_constraint& cn, const mpq& a); static void register_in_map(std::unordered_map<lpvar, mpq>& coeffs, const lar_base_constraint& cn, const mpq& a);
static void register_monoid_in_map(std::unordered_map<var_index, mpq>& coeffs, const mpq& a, unsigned j); static void register_monoid_in_map(std::unordered_map<lpvar, mpq>& coeffs, const mpq& a, unsigned j);
bool the_left_sides_sum_to_zero(const vector<std::pair<mpq, unsigned>>& evidence) const; bool the_left_sides_sum_to_zero(const vector<std::pair<mpq, unsigned>>& evidence) const;
bool explanation_is_correct(explanation&) const; bool explanation_is_correct(explanation&) const;
bool inf_explanation_is_correct() const; bool inf_explanation_is_correct() const;
@ -244,8 +232,8 @@ class lar_solver : public column_namer {
explanation& exp, explanation& exp,
const vector<std::pair<mpq, unsigned>>& inf_row, const vector<std::pair<mpq, unsigned>>& inf_row,
int inf_sign) const; int inf_sign) const;
mpq get_left_side_val(const lar_base_constraint& cns, const std::unordered_map<var_index, mpq>& var_map) const; mpq get_left_side_val(const lar_base_constraint& cns, const std::unordered_map<lpvar, mpq>& var_map) const;
void fill_var_set_for_random_update(unsigned sz, var_index const* vars, vector<unsigned>& column_list); void fill_var_set_for_random_update(unsigned sz, lpvar const* vars, vector<unsigned>& column_list);
bool column_represents_row_in_tableau(unsigned j); bool column_represents_row_in_tableau(unsigned j);
void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j); void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j);
void remove_last_row_and_column_from_tableau(unsigned j); void remove_last_row_and_column_from_tableau(unsigned j);
@ -259,7 +247,7 @@ class lar_solver : public column_namer {
bool bound_is_integer_for_integer_column(unsigned j, const mpq& right_side) const; bool bound_is_integer_for_integer_column(unsigned j, const mpq& right_side) const;
inline lar_core_solver& get_core_solver() { return m_mpq_lar_core_solver; } inline lar_core_solver& get_core_solver() { return m_mpq_lar_core_solver; }
var_index to_column(unsigned ext_j) const; lpvar to_column(unsigned ext_j) const;
void fix_terms_with_rounded_columns(); void fix_terms_with_rounded_columns();
bool remove_from_basis(unsigned); bool remove_from_basis(unsigned);
lar_term get_term_to_maximize(unsigned ext_j) const; lar_term get_term_to_maximize(unsigned ext_j) const;
@ -299,8 +287,6 @@ public:
template <typename T> template <typename T>
void remove_non_fixed_from_table(T&); void remove_non_fixed_from_table(T&);
unsigned external_to_column_index(unsigned) const;
bool inside_bounds(lpvar, const impq&) const; bool inside_bounds(lpvar, const impq&) const;
inline void set_column_value(unsigned j, const impq& v) { inline void set_column_value(unsigned j, const impq& v) {
@ -311,7 +297,7 @@ public:
set_column_value(j, v); set_column_value(j, v);
} }
var_index add_named_var(unsigned ext_j, bool is_integer, const std::string&); lpvar add_named_var(unsigned ext_j, bool is_integer, const std::string&);
lp_status maximize_term(unsigned j_or_term, impq& term_max); lp_status maximize_term(unsigned j_or_term, impq& term_max);
@ -348,7 +334,7 @@ public:
mpq const& a = r.coeff(); mpq const& a = r.coeff();
int a_sign = is_pos(a) ? 1 : -1; int a_sign = is_pos(a) ? 1 : -1;
int sign = j_sign * a_sign; int sign = j_sign * a_sign;
const ul_pair& ul = m_columns_to_ul_pairs[j]; const column& ul = m_columns[j];
auto* witness = sign > 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); auto* witness = sign > 0 ? ul.upper_bound_witness() : ul.lower_bound_witness();
lp_assert(witness); lp_assert(witness);
for (auto ci : flatten(witness)) for (auto ci : flatten(witness))
@ -367,10 +353,10 @@ public:
#ifdef Z3DEBUG #ifdef Z3DEBUG
bool fixed_base_removed_correctly() const; bool fixed_base_removed_correctly() const;
#endif #endif
constraint_index mk_var_bound(var_index j, lconstraint_kind kind, const mpq& right_side); constraint_index mk_var_bound(lpvar j, lconstraint_kind kind, const mpq& right_side);
void activate_check_on_equal(constraint_index, var_index&); void activate_check_on_equal(constraint_index, lpvar&);
void activate(constraint_index); void activate(constraint_index);
void random_update(unsigned sz, var_index const* vars); void random_update(unsigned sz, lpvar const* vars);
void add_column_rows_to_touched_rows(lpvar j); void add_column_rows_to_touched_rows(lpvar j);
template <typename T> template <typename T>
void propagate_bounds_for_touched_rows(lp_bound_propagator<T>& bp) { void propagate_bounds_for_touched_rows(lp_bound_propagator<T>& bp) {
@ -404,34 +390,24 @@ public:
} }
} }
bool is_fixed(column_index const& j) const { return column_is_fixed(j); }
inline column_index to_column_index(unsigned v) const { return column_index(external_to_column_index(v)); }
bool external_is_used(unsigned) const; bool external_is_used(unsigned) const;
void pop(unsigned k); void pop(unsigned k);
unsigned num_scopes() const { return m_trail.get_num_scopes(); } unsigned num_scopes() const { return m_trail.get_num_scopes(); }
bool compare_values(var_index j, lconstraint_kind kind, const mpq& right_side); bool compare_values(lpvar j, lconstraint_kind kind, const mpq& right_side);
var_index add_term(const vector<std::pair<mpq, var_index>>& coeffs, unsigned ext_i); lpvar add_term(const vector<std::pair<mpq, lpvar>>& coeffs, unsigned ext_i);
void register_existing_terms(); void register_existing_terms();
var_index ensure_column(var_index vi); constraint_index add_var_bound(lpvar, lconstraint_kind, const mpq&);
constraint_index add_var_bound(var_index, lconstraint_kind, const mpq&); constraint_index add_var_bound_check_on_equal(lpvar, lconstraint_kind, const mpq&, lpvar&);
constraint_index add_var_bound_check_on_equal(var_index, lconstraint_kind, const mpq&, var_index&);
var_index add_var(unsigned ext_j, bool is_integer); lpvar add_var(unsigned ext_j, bool is_integer);
void set_cut_strategy(unsigned cut_frequency); void set_cut_strategy(unsigned cut_frequency);
inline unsigned column_count() const { return A_r().column_count(); } inline unsigned column_count() const { return A_r().column_count(); }
inline var_index local_to_external(var_index idx) const { inline lpvar local_to_external(lpvar idx) const {
return tv::is_term(idx) ? m_term_register.local_to_external(idx) : m_var_register.local_to_external(idx); return m_var_register.local_to_external(idx);
} }
bool column_corresponds_to_term(unsigned) const; inline bool column_associated_with_row(lpvar j) const { return m_columns[j].associated_with_row(); }
const lar_term& column_to_term(unsigned j) const {
SASSERT(column_corresponds_to_term(j));
return get_term(column2tv(to_column_index(j)));
}
lar_term unfold_nested_subterms(lar_term const& term);
inline unsigned row_count() const { return A_r().row_count(); } inline unsigned row_count() const { return A_r().row_count(); }
bool var_is_registered(var_index vj) const; bool var_is_registered(lpvar vj) const;
void clear_inf_heap() { void clear_inf_heap() {
m_mpq_lar_core_solver.m_r_solver.inf_heap().clear(); m_mpq_lar_core_solver.m_r_solver.inf_heap().clear();
} }
@ -518,33 +494,28 @@ public:
u_dependency_manager& dep_manager() { return m_dependencies; } u_dependency_manager& dep_manager() { return m_dependencies; }
inline u_dependency* get_column_upper_bound_witness(unsigned j) const { inline u_dependency* get_column_upper_bound_witness(unsigned j) const {
if (tv::is_term(j)) { return m_columns[j].upper_bound_witness();
j = m_var_register.external_to_local(j);
}
return m_columns_to_ul_pairs[j].upper_bound_witness();
} }
inline const impq& get_upper_bound(column_index j) const { inline const impq& get_upper_bound(lpvar j) const {
return m_mpq_lar_core_solver.m_r_solver.m_upper_bounds[j]; return m_mpq_lar_core_solver.m_r_solver.m_upper_bounds[j];
} }
inline const impq& get_lower_bound(column_index j) const { inline const impq& get_lower_bound(lpvar j) const {
return m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j]; return m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j];
} }
inline mpq bound_span_x(column_index j) const { inline mpq bound_span_x(lpvar j) const {
return m_mpq_lar_core_solver.m_r_solver.m_upper_bounds[j].x - m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j].x; return m_mpq_lar_core_solver.m_r_solver.m_upper_bounds[j].x - m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j].x;
} }
bool has_lower_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const; bool has_lower_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const;
bool has_upper_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const; bool has_upper_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const;
bool has_value(var_index var, mpq& value) const; bool has_value(lpvar var, mpq& value) const;
bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const; bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const;
unsigned map_term_index_to_column_index(unsigned j) const;
bool column_is_fixed(unsigned j) const; bool column_is_fixed(unsigned j) const;
bool column_is_free(unsigned j) const; bool column_is_free(unsigned j) const;
bool column_is_feasible(unsigned j) const { return m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j);} bool column_is_feasible(unsigned j) const { return m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j);}
unsigned column_to_reported_index(unsigned j) const;
lp_settings& settings(); lp_settings& settings();
lp_settings const& settings() const; lp_settings const& settings() const;
statistics& stats(); statistics& stats();
@ -552,8 +523,6 @@ public:
void updt_params(params_ref const& p); void updt_params(params_ref const& p);
column_type get_column_type(unsigned j) const { return m_mpq_lar_core_solver.m_column_types()[j]; } column_type get_column_type(unsigned j) const { return m_mpq_lar_core_solver.m_column_types()[j]; }
const vector<column_type>& get_column_types() const { return m_mpq_lar_core_solver.m_column_types(); } const vector<column_type>& get_column_types() const { return m_mpq_lar_core_solver.m_column_types(); }
const impq& get_lower_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_lower_bounds()[j]; }
const impq& get_upper_bound(unsigned j) const { return m_mpq_lar_core_solver.m_r_upper_bounds()[j]; }
std::ostream& print_terms(std::ostream& out) const; std::ostream& print_terms(std::ostream& out) const;
std::ostream& print_term(lar_term const& term, std::ostream& out) const; std::ostream& print_term(lar_term const& term, std::ostream& out) const;
static std::ostream& print_term_as_indices(lar_term const& term, std::ostream& out); static std::ostream& print_term_as_indices(lar_term const& term, std::ostream& out);
@ -566,14 +535,12 @@ public:
} }
bool init_model() const; bool init_model() const;
mpq from_model_in_impq_to_mpq(const impq& v) const { return v.x + m_delta * v.y; } mpq from_model_in_impq_to_mpq(const impq& v) const { return v.x + m_delta * v.y; }
mpq get_value(column_index const& j) const; mpq get_value(lpvar j) const;
mpq get_tv_value(tv const& t) const; void get_model(std::unordered_map<lpvar, mpq>& variable_values) const;
const impq& get_tv_ivalue(tv const& t) const;
void get_model(std::unordered_map<var_index, mpq>& variable_values) const;
void get_rid_of_inf_eps(); void get_rid_of_inf_eps();
void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq>& variable_values) const; void get_model_do_not_care_about_diff_vars(std::unordered_map<lpvar, mpq>& variable_values) const;
std::string get_variable_name(var_index vi) const override; std::string get_variable_name(lpvar vi) const override;
void set_variable_name(var_index vi, std::string); void set_variable_name(lpvar vi, std::string);
inline unsigned number_of_vars() const { return m_var_register.size(); } inline unsigned number_of_vars() const { return m_var_register.size(); }
inline bool is_base(unsigned j) const { return m_mpq_lar_core_solver.m_r_heading[j] >= 0; } inline bool is_base(unsigned j) const { return m_mpq_lar_core_solver.m_r_heading[j] >= 0; }
inline const impq& column_lower_bound(unsigned j) const { inline const impq& column_lower_bound(unsigned j) const {
@ -595,7 +562,7 @@ public:
std::pair<constraint_index, constraint_index> add_equality(lpvar j, lpvar k); std::pair<constraint_index, constraint_index> add_equality(lpvar j, lpvar k);
u_dependency* get_bound_constraint_witnesses_for_column(unsigned j) { u_dependency* get_bound_constraint_witnesses_for_column(unsigned j) {
const ul_pair& ul = m_columns_to_ul_pairs[j]; const column& ul = m_columns[j];
return m_dependencies.mk_join(ul.lower_bound_witness(), ul.upper_bound_witness()); return m_dependencies.mk_join(ul.lower_bound_witness(), ul.upper_bound_witness());
} }
template <typename T> template <typename T>
@ -613,22 +580,15 @@ public:
void pop(); void pop();
inline u_dependency* get_column_lower_bound_witness(unsigned j) const { inline u_dependency* get_column_lower_bound_witness(unsigned j) const {
if (tv::is_term(j)) { return m_columns[j].lower_bound_witness();
j = m_var_register.external_to_local(j);
}
return m_columns_to_ul_pairs[j].lower_bound_witness();
} }
inline bool column_has_term(lpvar j) const { return m_columns[j].term() != nullptr; }
inline tv column2tv(column_index const& c) const {
return tv::raw(column_to_reported_index(c));
}
inline std::ostream& print_column_info(unsigned j, std::ostream& out) const { inline std::ostream& print_column_info(unsigned j, std::ostream& out) const {
m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out); m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out);
if (tv::is_term(j)) { if (column_has_term(j)) {
print_term_as_indices(get_term(j), out) << "\n"; print_term_as_indices(get_term(j), out) << "\n";
} else if (column_corresponds_to_term(j)) { } else if (column_has_term(j)) {
const lar_term& t = get_term(m_var_register.local_to_external(j)); const lar_term& t = get_term(m_var_register.local_to_external(j));
print_term_as_indices(t, out) << "\n"; print_term_as_indices(t, out) << "\n";
} }
@ -651,13 +611,12 @@ public:
return false; return false;
} }
inline const vector<lar_term*>& terms() const { return m_terms; } inline const vector<lar_term*>& terms() const { return m_terms; }
inline lar_term const& term(unsigned i) const { return *m_terms[i]; }
inline void set_int_solver(int_solver* int_slv) { m_int_solver = int_slv; } inline void set_int_solver(int_solver* int_slv) { m_int_solver = int_slv; }
inline int_solver* get_int_solver() { return m_int_solver; } inline int_solver* get_int_solver() { return m_int_solver; }
inline const int_solver* get_int_solver() const { return m_int_solver; } inline const int_solver* get_int_solver() const { return m_int_solver; }
inline const lar_term& get_term(tv const& t) const { inline const lar_term& get_term(lpvar j) const {
lp_assert(t.is_term()); return *m_columns[j].term();
return *m_terms[t.id()];
} }
lp_status find_feasible_solution(); lp_status find_feasible_solution();
void move_non_basic_columns_to_bounds(); void move_non_basic_columns_to_bounds();
@ -675,8 +634,8 @@ public:
inline const column_strip& get_column(unsigned i) const { return A_r().m_columns[i]; } inline const column_strip& get_column(unsigned i) const { return A_r().m_columns[i]; }
bool row_is_correct(unsigned i) const; bool row_is_correct(unsigned i) const;
bool ax_is_correct() const; bool ax_is_correct() const;
bool get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, u_dependency*& ci, bool& upper_bound) const; bool get_equality_and_right_side_for_term_on_current_x(lpvar j, mpq& rs, u_dependency*& ci, bool& upper_bound) const;
bool var_is_int(var_index v) const; bool var_is_int(lpvar v) const;
inline const vector<int>& r_heading() const { return m_mpq_lar_core_solver.m_r_heading; } inline const vector<int>& r_heading() const { return m_mpq_lar_core_solver.m_r_heading; }
inline const vector<unsigned>& r_basis() const { return m_mpq_lar_core_solver.r_basis(); } inline const vector<unsigned>& r_basis() const { return m_mpq_lar_core_solver.r_basis(); }
inline const vector<unsigned>& r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); } inline const vector<unsigned>& r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); }
@ -687,7 +646,7 @@ public:
lp_status solve(); lp_status solve();
void fill_explanation_from_crossed_bounds_column(explanation& evidence) const; void fill_explanation_from_crossed_bounds_column(explanation& evidence) const;
bool term_is_used_as_row(unsigned term) const; bool term_is_used_as_row(unsigned term) const;
bool tighten_term_bounds_by_delta(tv const& t, const impq&); bool tighten_term_bounds_by_delta(lpvar j, const impq&);
lar_solver(); lar_solver();
void track_touched_rows(bool v); void track_touched_rows(bool v);
bool touched_rows_are_tracked() const; bool touched_rows_are_tracked() const;
@ -698,18 +657,16 @@ public:
inline static_matrix<mpq, impq>& A_r() { return m_mpq_lar_core_solver.m_r_A; } inline static_matrix<mpq, impq>& A_r() { return m_mpq_lar_core_solver.m_r_A; }
inline const static_matrix<mpq, impq>& A_r() const { return m_mpq_lar_core_solver.m_r_A; } inline const static_matrix<mpq, impq>& A_r() const { return m_mpq_lar_core_solver.m_r_A; }
// columns // columns
bool column_is_int(column_index const& j) const { return column_is_int((unsigned)j); } const impq& get_column_value(lpvar j) const { return m_mpq_lar_core_solver.m_r_x[j]; }
const impq& get_column_value(column_index const& j) const { return m_mpq_lar_core_solver.m_r_x[j]; } inline lpvar external_to_local(unsigned j) const {
inline var_index external_to_local(unsigned j) const { lpvar local_j;
var_index local_j; if (m_var_register.external_is_used(j, local_j)) {
if (m_var_register.external_is_used(j, local_j) ||
m_term_register.external_is_used(j, local_j)) {
return local_j; return local_j;
} else { } else {
return -1; return -1;
} }
} }
unsigned usage_in_terms(column_index j) const { unsigned usage_in_terms(lpvar j) const {
if (j >= m_usage_in_terms.size()) if (j >= m_usage_in_terms.size())
return 0; return 0;
return m_usage_in_terms[j]; return m_usage_in_terms[j];

View file

@ -26,8 +26,12 @@ namespace lp {
class lar_term { class lar_term {
typedef unsigned lpvar; typedef unsigned lpvar;
u_map<mpq> m_coeffs; u_map<mpq> m_coeffs;
// the column index related to the term
lpvar m_j = -1;
public: public:
lar_term() {} // the column index related to the term
lpvar j() const { return m_j; }
lpvar& j() { return m_j; }
void add_monomial(const mpq& c, unsigned j) { void add_monomial(const mpq& c, unsigned j) {
if (c.is_zero()) if (c.is_zero())
return; return;
@ -62,10 +66,11 @@ public:
mpq a = it->get_data().m_value; mpq a = it->get_data().m_value;
this->m_coeffs.erase(term_column); this->m_coeffs.erase(term_column);
for (auto p : t) { for (auto p : t) {
this->add_monomial(a * p.coeff(), p.column()); this->add_monomial(a * p.coeff(), p.j());
} }
} }
// constructors
lar_term() {}
lar_term(const vector<std::pair<mpq, unsigned>>& coeffs) { lar_term(const vector<std::pair<mpq, unsigned>>& coeffs) {
for (auto const& p : coeffs) { for (auto const& p : coeffs) {
add_monomial(p.first, p.second); add_monomial(p.first, p.second);
@ -150,11 +155,11 @@ public:
} }
class ival { class ival {
unsigned m_var; lpvar m_var;
const mpq & m_coeff; const mpq & m_coeff;
public: public:
ival(unsigned var, const mpq & val) : m_var(var), m_coeff(val) { } ival(lpvar var, const mpq & val) : m_var(var), m_coeff(val) { }
column_index column() const { return column_index(m_var); } lpvar j() const { return m_var; }
const mpq & coeff() const { return m_coeff; } const mpq & coeff() const { return m_coeff; }
}; };
@ -173,13 +178,13 @@ public:
lpvar min_var = -1; lpvar min_var = -1;
mpq c; mpq c;
for (ival p : *this) { for (ival p : *this) {
if (p.column() < min_var) { if (p.j() < min_var) {
min_var = p.column(); min_var = p.j();
} }
} }
lar_term r; lar_term r;
for (ival p : *this) { for (ival p : *this) {
if (p.column() == min_var) { if (p.j() == min_var) {
return p.coeff().is_one(); return p.coeff().is_one();
} }
} }

View file

@ -31,7 +31,7 @@ namespace lp_api {
class bound { class bound {
Literal m_bv; Literal m_bv;
theory_var m_var; theory_var m_var;
lp::lpvar m_vi; lp::lpvar m_column_index;
bool m_is_int; bool m_is_int;
rational m_value; rational m_value;
bound_kind m_bound_kind; bound_kind m_bound_kind;
@ -41,7 +41,7 @@ namespace lp_api {
bound(Literal bv, theory_var v, lp::lpvar vi, bool is_int, rational const& val, bound_kind k, lp::constraint_index ct, lp::constraint_index cf) : bound(Literal bv, theory_var v, lp::lpvar vi, bool is_int, rational const& val, bound_kind k, lp::constraint_index ct, lp::constraint_index cf) :
m_bv(bv), m_bv(bv),
m_var(v), m_var(v),
m_vi(vi), m_column_index(vi),
m_is_int(is_int), m_is_int(is_int),
m_value(val), m_value(val),
m_bound_kind(k) { m_bound_kind(k) {
@ -53,7 +53,7 @@ namespace lp_api {
theory_var get_var() const { return m_var; } theory_var get_var() const { return m_var; }
lp::tv tv() const { return lp::tv::raw(m_vi); } lp::lpvar column_index() const { return m_column_index; }
Literal get_lit() const { return m_bv; } Literal get_lit() const { return m_bv; }

View file

@ -147,8 +147,6 @@ public:
void add_bound(mpq const& v, unsigned j, bool is_low, bool strict, std::function<u_dependency* ()> explain_bound) { void add_bound(mpq const& v, unsigned j, bool is_low, bool strict, std::function<u_dependency* ()> explain_bound) {
j = lp().column_to_reported_index(j);
lconstraint_kind kind = is_low ? GE : LE; lconstraint_kind kind = is_low ? GE : LE;
if (strict) if (strict)
kind = static_cast<lconstraint_kind>(kind / 2); kind = static_cast<lconstraint_kind>(kind / 2);
@ -222,14 +220,11 @@ public:
return out; return out;
} }
bool add_eq_on_columns(const explanation& exp, lpvar j, lpvar k, bool is_fixed) { bool add_eq_on_columns(const explanation& exp, lpvar je, lpvar ke, bool is_fixed) {
lp_assert(j != k && is_int(j) == is_int(k)); lp_assert(je != ke && is_int(je) == is_int(ke));
lp_assert(ival(j) == ival(k)); lp_assert(ival(je) == ival(ke));
unsigned je = lp().column_to_reported_index(j);
unsigned ke = lp().column_to_reported_index(k);
TRACE("eq", TRACE("eq",
tout << "reporting eq " << j << ", " << k << "\n";
tout << "reported idx " << je << ", " << ke << "\n"; tout << "reported idx " << je << ", " << ke << "\n";
print_expl(tout, exp); print_expl(tout, exp);
tout << "theory_vars v" << lp().local_to_external(je) << " == v" << lp().local_to_external(ke) << "\n";); tout << "theory_vars v" << lp().local_to_external(je) << " == v" << lp().local_to_external(ke) << "\n";);
@ -246,12 +241,12 @@ public:
// column to theory_var // column to theory_var
unsigned col_to_imp(unsigned j) const { unsigned col_to_imp(unsigned j) const {
return lp().local_to_external(lp().column_to_reported_index(j)); return lp().local_to_external(j);
} }
// theory_var to column // theory_var to column
unsigned imp_to_col(unsigned j) const { unsigned imp_to_col(unsigned j) const {
return lp().external_to_column_index(j); return lp().external_to_local(j);
} }
bool is_int(lpvar j) const { bool is_int(lpvar j) const {
@ -261,7 +256,7 @@ public:
void explain_fixed_in_row(unsigned row, explanation& ex) { void explain_fixed_in_row(unsigned row, explanation& ex) {
TRACE("eq", tout << lp().get_row(row) << std::endl); TRACE("eq", tout << lp().get_row(row) << std::endl);
for (const auto& c : lp().get_row(row)) for (const auto& c : lp().get_row(row))
if (lp().is_fixed(c.var())) if (lp().column_is_fixed(c.var()))
explain_fixed_column(c.var(), ex); explain_fixed_column(c.var(), ex);
} }
@ -269,7 +264,7 @@ public:
unsigned base = UINT_MAX; unsigned base = UINT_MAX;
TRACE("eq", tout << lp().get_row(row) << std::endl); TRACE("eq", tout << lp().get_row(row) << std::endl);
for (const auto& c : lp().get_row(row)) { for (const auto& c : lp().get_row(row)) {
if (lp().is_fixed(c.var())) { if (lp().column_is_fixed(c.var())) {
explain_fixed_column(c.var(), ex); explain_fixed_column(c.var(), ex);
} }
else if (lp().is_base(c.var())) { else if (lp().is_base(c.var())) {
@ -288,7 +283,7 @@ public:
#ifdef Z3DEBUG #ifdef Z3DEBUG
bool all_fixed_in_row(unsigned row) const { bool all_fixed_in_row(unsigned row) const {
for (const auto& c : lp().get_row(row)) for (const auto& c : lp().get_row(row))
if (!lp().is_fixed(c.var())) if (!lp().column_is_fixed(c.var()))
return false; return false;
return true; return true;
} }

View file

@ -53,9 +53,8 @@ inline std::ostream& operator<<(std::ostream& out, column_type const& t) {
} }
enum class simplex_strategy_enum { enum class simplex_strategy_enum {
undecided = 3, tableau_rows,
tableau_rows = 0, tableau_costs
tableau_costs = 1
}; };
std::string column_type_to_string(column_type t); std::string column_type_to_string(column_type t);

View file

@ -30,72 +30,12 @@ namespace nla {
namespace lp { namespace lp {
typedef unsigned var_index;
typedef unsigned constraint_index; typedef unsigned constraint_index;
typedef unsigned row_index; typedef unsigned row_index;
enum lconstraint_kind { LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0, NE = 3 }; enum lconstraint_kind { LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0, NE = 3 };
typedef unsigned lpvar; typedef unsigned lpvar;
const lpvar null_lpvar = UINT_MAX; const lpvar null_lpvar = UINT_MAX;
const constraint_index null_ci = UINT_MAX; const constraint_index null_ci = UINT_MAX;
class column_index {
unsigned m_index;
friend class lar_solver;
friend class lar_term;
friend nla::core;
operator unsigned() const { return m_index; }
public:
column_index(unsigned j): m_index(j) {}
unsigned index() const { return m_index; }
bool is_null() const { return m_index == null_lpvar; }
};
// index that comes from term or variable.
class tv {
unsigned m_index;
static const unsigned EF = UINT_MAX >> 1;
tv(unsigned i): m_index(i) {}
public:
static tv term(unsigned i) { SASSERT(0 == (i & left_most_bit)); return tv(mask_term(i)); }
static tv var(unsigned i) { SASSERT(0 == (i & left_most_bit)); return tv(i); }
static tv raw(unsigned i) { return tv(i); }
// retrieve the identifier associated with tv
unsigned id() const { return unmask_term(m_index); }
column_index column() const { SASSERT(is_var()); return column_index(id()); }
// retrieve the raw index.
unsigned index() const { return m_index; }
bool is_term() const { return 0 != (m_index & left_most_bit); }
bool is_var() const { return 0 == (m_index & left_most_bit); }
// utilities useful where tv isn't already encapsulating id's.
static inline unsigned unmask_term(unsigned j) { return j & EF; }
static inline bool is_term(unsigned j) { return j & left_most_bit; }
static inline unsigned mask_term(unsigned j) { return j | left_most_bit; }
// used by var_register. could we encapsulate even this?
static const unsigned left_most_bit = ~EF;
std::string to_string() const {
std::ostringstream strm;
strm << (is_term() ? "t" : "j") << id();
return strm.str();
}
bool is_null() const { return m_index == UINT_MAX; }
};
} }
inline std::ostream& operator<<(std::ostream& out, lp::tv const& t) {
return out << (t.is_term() ? "t":"j") << t.id() << "\n";
}

View file

@ -116,12 +116,9 @@ template <typename T>
std::ostream& print_linear_combination_of_column_indices_only(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) { std::ostream& print_linear_combination_of_column_indices_only(const vector<std::pair<T, unsigned>> & coeffs, std::ostream & out) {
return print_linear_combination_customized( return print_linear_combination_customized(
coeffs, coeffs,
[](unsigned j) {std::stringstream ss; [](unsigned j) {
if (tv::is_term(j)) { std::stringstream ss;
ss << "t" << tv::unmask_term(j); ss << "j" << j;
} else {
ss << "j" << j;
}
return ss.str();}, return ss.str();},
out); out);
} }

View file

@ -21,15 +21,15 @@ namespace nla {
class mon_eq { class mon_eq {
// fields // fields
lp::var_index m_v; lp::lpvar m_v;
svector<lp::var_index> m_vs; svector<lp::lpvar> m_vs;
public: public:
// constructors // constructors
mon_eq(lp::var_index v, unsigned sz, lp::var_index const* vs): mon_eq(lp::lpvar v, unsigned sz, lp::lpvar const* vs):
m_v(v), m_vs(sz, vs) { m_v(v), m_vs(sz, vs) {
std::sort(m_vs.begin(), m_vs.end()); std::sort(m_vs.begin(), m_vs.end());
} }
mon_eq(lp::var_index v, const svector<lp::var_index> &vs): mon_eq(lp::lpvar v, const svector<lp::lpvar> &vs):
m_v(v), m_vs(vs) { m_v(v), m_vs(vs) {
std::sort(m_vs.begin(), m_vs.end()); std::sort(m_vs.begin(), m_vs.end());
} }
@ -37,7 +37,7 @@ public:
unsigned var() const { return m_v; } unsigned var() const { return m_v; }
unsigned size() const { return m_vs.size(); } unsigned size() const { return m_vs.size(); }
const svector<lp::var_index>& vars() const { return m_vs; } const svector<lp::lpvar>& vars() const { return m_vs; }
bool empty() const { return m_vs.empty(); } bool empty() const { return m_vs.empty(); }
bool is_sorted() const { bool is_sorted() const {
for (unsigned i = 0; i + 1 < size(); i++) for (unsigned i = 0; i + 1 < size(); i++)
@ -49,7 +49,7 @@ public:
return std::binary_search(m_vs.begin(), m_vs.end(), j); return std::binary_search(m_vs.begin(), m_vs.end(), j);
} }
protected: protected:
svector<lp::var_index>& vars1() { return m_vs; } svector<lp::lpvar>& vars1() { return m_vs; }
}; };
// support the congruence // support the congruence

View file

@ -376,7 +376,7 @@ namespace nla {
// propagate fixed equality // propagate fixed equality
auto exp = get_explanation(dep); auto exp = get_explanation(dep);
c().add_fixed_equality(c().lra.column_to_reported_index(m.var()), rational(0), exp); c().add_fixed_equality(m.var(), rational(0), exp);
} }
void monomial_bounds::propagate_fixed(monic const& m, rational const& k) { void monomial_bounds::propagate_fixed(monic const& m, rational const& k) {
@ -386,22 +386,21 @@ namespace nla {
// propagate fixed equality // propagate fixed equality
auto exp = get_explanation(dep); auto exp = get_explanation(dep);
c().add_fixed_equality(c().lra.column_to_reported_index(m.var()), k, exp); c().add_fixed_equality(m.var(), k, exp);
} }
void monomial_bounds::propagate_nonfixed(monic const& m, rational const& k, lpvar w) { void monomial_bounds::propagate_nonfixed(monic const& m, rational const& k, lpvar w) {
vector<std::pair<lp::mpq, unsigned>> coeffs; vector<std::pair<lp::mpq, unsigned>> coeffs;
coeffs.push_back({-k, w}); coeffs.push_back({-k, w});
coeffs.push_back({rational::one(), m.var()}); coeffs.push_back({rational::one(), m.var()});
lp::lpvar term_index = c().lra.add_term(coeffs, UINT_MAX); lp::lpvar j = c().lra.add_term(coeffs, UINT_MAX);
auto* dep = explain_fixed(m, k); auto* dep = explain_fixed(m, k);
term_index = c().lra.map_term_index_to_column_index(term_index);
TRACE("nla_solver", tout << "propagate nonfixed " << m << " = " << k << " " << w << "\n";); TRACE("nla_solver", tout << "propagate nonfixed " << m << " = " << k << " " << w << "\n";);
c().lra.update_column_type_and_bound(term_index, lp::lconstraint_kind::EQ, mpq(0), dep); c().lra.update_column_type_and_bound(j, lp::lconstraint_kind::EQ, mpq(0), dep);
if (k == 1) { if (k == 1) {
lp::explanation exp = get_explanation(dep); lp::explanation exp = get_explanation(dep);
c().add_equality(c().lra.column_to_reported_index(m.var()), c().lra.column_to_reported_index(w), exp); c().add_equality(m.var(), w, exp);
} }
} }

View file

@ -68,21 +68,10 @@ bool core::compare_holds(const rational& ls, llc cmp, const rational& rs) const
rational core::value(const lp::lar_term& r) const { rational core::value(const lp::lar_term& r) const {
rational ret(0); rational ret(0);
for (lp::lar_term::ival t : r) for (lp::lar_term::ival t : r)
ret += t.coeff() * val(t.column()); ret += t.coeff() * val(t.j());
return ret; return ret;
} }
lp::lar_term core::subs_terms_to_columns(const lp::lar_term& t) const {
lp::lar_term r;
for (lp::lar_term::ival p : t) {
lpvar j = p.column();
if (lp::tv::is_term(j))
j = lra.map_term_index_to_column_index(j);
r.add_monomial(p.coeff(), j);
}
return r;
}
bool core::ineq_holds(const ineq& n) const { bool core::ineq_holds(const ineq& n) const {
return compare_holds(value(n.term()), n.cmp(), n.rs()); return compare_holds(value(n.term()), n.cmp(), n.rs());
} }
@ -139,10 +128,7 @@ bool core::canonize_sign(const factorization& f) const {
void core::add_monic(lpvar v, unsigned sz, lpvar const* vs) { void core::add_monic(lpvar v, unsigned sz, lpvar const* vs) {
m_add_buffer.resize(sz); m_add_buffer.resize(sz);
for (unsigned i = 0; i < sz; i++) { for (unsigned i = 0; i < sz; i++) {
lpvar j = vs[i]; m_add_buffer[i] = vs[i];
if (lp::tv::is_term(j))
j = lra.map_term_index_to_column_index(j);
m_add_buffer[i] = j;
} }
m_emons.add(v, m_add_buffer); m_emons.add(v, m_add_buffer);
m_monics_with_changed_bounds.insert(v); m_monics_with_changed_bounds.insert(v);
@ -326,25 +312,25 @@ bool core::explain_coeff_lower_bound(const lp::lar_term::ival& p, rational& boun
const rational& a = p.coeff(); const rational& a = p.coeff();
SASSERT(!a.is_zero()); SASSERT(!a.is_zero());
if (a.is_pos()) { if (a.is_pos()) {
auto* dep = lra.get_column_lower_bound_witness(p.column()); auto* dep = lra.get_column_lower_bound_witness(p.j());
if (!dep) if (!dep)
return false; return false;
bound = a * lra.get_lower_bound(p.column()).x; bound = a * lra.get_lower_bound(p.j()).x;
lra.push_explanation(dep, e); lra.push_explanation(dep, e);
return true; return true;
} }
// a.is_neg() // a.is_neg()
auto* dep = lra.get_column_upper_bound_witness(p.column()); auto* dep = lra.get_column_upper_bound_witness(p.j());
if (!dep) if (!dep)
return false; return false;
bound = a * lra.get_upper_bound(p.column()).x; bound = a * lra.get_upper_bound(p.j()).x;
lra.push_explanation(dep, e); lra.push_explanation(dep, e);
return true; return true;
} }
bool core::explain_coeff_upper_bound(const lp::lar_term::ival& p, rational& bound, lp::explanation& e) const { bool core::explain_coeff_upper_bound(const lp::lar_term::ival& p, rational& bound, lp::explanation& e) const {
const rational& a = p.coeff(); const rational& a = p.coeff();
lpvar j = p.column(); lpvar j = p.j();
SASSERT(!a.is_zero()); SASSERT(!a.is_zero());
if (a.is_neg()) { if (a.is_neg()) {
auto *dep = lra.get_column_lower_bound_witness(j); auto *dep = lra.get_column_lower_bound_witness(j);
@ -602,7 +588,7 @@ std::ostream & core::print_ineqs(const lemma& l, std::ostream & out) const {
print_ineq(in, out); print_ineq(in, out);
if (i + 1 < l.ineqs().size()) out << " or "; if (i + 1 < l.ineqs().size()) out << " or ";
for (lp::lar_term::ival p: in.term()) for (lp::lar_term::ival p: in.term())
vars.insert(p.column()); vars.insert(p.j());
} }
out << std::endl; out << std::endl;
for (lpvar j : vars) { for (lpvar j : vars) {
@ -701,13 +687,13 @@ unsigned core::random() { return lp_settings().random_next(); }
void core::collect_equivs() { void core::collect_equivs() {
const lp::lar_solver& s = lra; const lp::lar_solver& s = lra;
for (unsigned i = 0; i < s.terms().size(); i++) { for (const auto * t : s.terms()) {
if (!s.term_is_used_as_row(i)) if (!s.column_associated_with_row(t->j()))
continue; continue;
lpvar j = s.external_to_local(lp::tv::mask_term(i)); lpvar j = t->j();
if (var_is_fixed_to_zero(j)) { if (var_is_fixed_to_zero(j)) {
TRACE("nla_solver_mons", s.print_term_as_indices(*s.terms()[i], tout << "term = ") << "\n";); TRACE("nla_solver_mons", s.print_term_as_indices(*t, tout << "term = ") << "\n";);
add_equivalence_maybe(s.terms()[i], s.get_column_upper_bound_witness(j), s.get_column_lower_bound_witness(j)); add_equivalence_maybe(t, s.get_column_upper_bound_witness(j), s.get_column_lower_bound_witness(j));
} }
} }
m_emons.ensure_canonized(); m_emons.ensure_canonized();
@ -732,9 +718,9 @@ bool core::is_octagon_term(const lp::lar_term& t, bool & sign, lpvar& i, lpvar &
return false; return false;
} }
if (i == null_lpvar) if (i == null_lpvar)
i = p.column(); i = p.j();
else else
j = p.column(); j = p.j();
} }
SASSERT(j != null_lpvar); SASSERT(j != null_lpvar);
sign = (seen_minus && seen_plus)? false : true; sign = (seen_minus && seen_plus)? false : true;
@ -871,7 +857,7 @@ std::unordered_set<lpvar> core::collect_vars(const lemma& l) const {
for (const auto& i : l.ineqs()) { for (const auto& i : l.ineqs()) {
for (lp::lar_term::ival p : i.term()) { for (lp::lar_term::ival p : i.term()) {
insert_j(p.column()); insert_j(p.j());
} }
} }
for (auto p : l.expl()) { for (auto p : l.expl()) {
@ -1629,17 +1615,9 @@ lbool core::test_check() {
} }
std::ostream& core::print_terms(std::ostream& out) const { std::ostream& core::print_terms(std::ostream& out) const {
for (unsigned i = 0; i < lra.terms().size(); i++) { for (const auto * t: lra.terms()) {
unsigned ext = lp::tv::mask_term(i); out << "term:"; print_term(*t, out) << std::endl;
if (!lra.var_is_registered(ext)) { print_var(t->j(), out);
out << "term is not registered\n";
continue;
}
const lp::lar_term & t = *lra.terms()[i];
out << "term:"; print_term(t, out) << std::endl;
lpvar j = lra.external_to_local(ext);
print_var(j, out);
} }
return out; return out;
} }
@ -1673,12 +1651,12 @@ std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e
} }
for (unsigned i = 0; i < added.size(); ++i) { for (unsigned i = 0; i < added.size(); ++i) {
lpvar j = added[i]; lpvar j = added[i];
if (ls.column_corresponds_to_term(j)) { if (ls.column_has_term(j)) {
const auto& t = lra.get_term(lp::tv::raw(ls.local_to_external(j))); const auto& t = lra.get_term(j);
for (auto p : t) { for (auto p : t) {
if (ret.find(p.column()) == ret.end()) { if (ret.find(p.j()) == ret.end()) {
added.push_back(p.column()); added.push_back(p.j());
ret.insert(p.column()); ret.insert(p.j());
} }
} }
} }
@ -1729,8 +1707,6 @@ void core::set_active_vars_weights(nex_creator& nc) {
} }
bool core::influences_nl_var(lpvar j) const { bool core::influences_nl_var(lpvar j) const {
if (lp::tv::is_term(j))
j = lp::tv::unmask_term(j);
if (is_nl_var(j)) if (is_nl_var(j))
return true; return true;
for (const auto & c : lra.A_r().m_columns[j]) { for (const auto & c : lra.A_r().m_columns[j]) {

View file

@ -135,7 +135,6 @@ public:
rational value(const lp::lar_term& r) const; rational value(const lp::lar_term& r) const;
lp::lar_term subs_terms_to_columns(const lp::lar_term& t) const;
bool ineq_holds(const ineq& n) const; bool ineq_holds(const ineq& n) const;
bool lemma_holds(const lemma& l) const; bool lemma_holds(const lemma& l) const;
bool is_monic_var(lpvar j) const { return m_emons.is_monic_var(j); } bool is_monic_var(lpvar j) const { return m_emons.is_monic_var(j); }
@ -284,10 +283,10 @@ public:
} }
const rational& get_upper_bound(unsigned j) const; const rational& get_upper_bound(unsigned j) const;
const rational& get_lower_bound(unsigned j) const; const rational& get_lower_bound(unsigned j) const;
bool has_lower_bound(lp::var_index var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const { bool has_lower_bound(lp::lpvar var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const {
return lra.has_lower_bound(var, ci, value, is_strict); return lra.has_lower_bound(var, ci, value, is_strict);
} }
bool has_upper_bound(lp::var_index var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const { bool has_upper_bound(lp::lpvar var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const {
return lra.has_upper_bound(var, ci, value, is_strict); return lra.has_upper_bound(var, ci, value, is_strict);
} }

View file

@ -17,7 +17,7 @@ namespace nla {
typedef lp::constraint_index lpci; typedef lp::constraint_index lpci;
typedef lp::lconstraint_kind llc; typedef lp::lconstraint_kind llc;
typedef lp::explanation expl_set; typedef lp::explanation expl_set;
typedef lp::var_index lpvar; typedef unsigned lpvar;
struct from_index_dummy{}; struct from_index_dummy{};
class signed_var { class signed_var {
@ -54,12 +54,12 @@ inline std::ostream& operator<<(std::ostream& out, signed_var const& sv) { retur
* where m_vs = [v1, v2, .., vn] * where m_vs = [v1, v2, .., vn]
*/ */
class monic_coeff { class monic_coeff {
svector<lp::var_index> m_vs; svector<lp::lpvar> m_vs;
rational m_coeff; rational m_coeff;
public: public:
monic_coeff(const svector<lp::var_index>& vs, rational const& coeff): m_vs(vs), m_coeff(coeff) {} monic_coeff(const svector<lp::lpvar>& vs, rational const& coeff): m_vs(vs), m_coeff(coeff) {}
rational const& coeff() const { return m_coeff; } rational const& coeff() const { return m_coeff; }
const svector<lp::var_index> & vars() const { return m_vs; } const svector<lp::lpvar> & vars() const { return m_vs; }
}; };
template <typename T> bool has_zero(const T& product) { template <typename T> bool has_zero(const T& product) {
for (const rational & t : product) { for (const rational & t : product) {

View file

@ -19,15 +19,9 @@ Description:
namespace nla { namespace nla {
void divisions::add_idivision(lpvar q, lpvar x, lpvar y) { void divisions::add_idivision(lpvar q, lpvar x, lpvar y) {
auto& lra = m_core.lra; const auto& lra = m_core.lra;
if (x == null_lpvar || y == null_lpvar || q == null_lpvar) if (x == null_lpvar || y == null_lpvar || q == null_lpvar)
return; return;
if (lp::tv::is_term(x))
x = lra.map_term_index_to_column_index(x);
if (lp::tv::is_term(y))
y = lra.map_term_index_to_column_index(y);
if (lp::tv::is_term(q))
q = lra.map_term_index_to_column_index(q);
m_idivisions.push_back({q, x, y}); m_idivisions.push_back({q, x, y});
m_core.trail().push(push_back_vector(m_idivisions)); m_core.trail().push(push_back_vector(m_idivisions));
} }
@ -36,13 +30,6 @@ namespace nla {
auto& lra = m_core.lra; auto& lra = m_core.lra;
if (x == null_lpvar || y == null_lpvar || q == null_lpvar) if (x == null_lpvar || y == null_lpvar || q == null_lpvar)
return; return;
if (lp::tv::is_term(x))
x = lra.map_term_index_to_column_index(x);
if (lp::tv::is_term(y))
y = lra.map_term_index_to_column_index(y);
if (lp::tv::is_term(q))
q = lra.map_term_index_to_column_index(q);
m_rdivisions.push_back({ q, x, y }); m_rdivisions.push_back({ q, x, y });
m_core.trail().push(push_back_vector(m_rdivisions)); m_core.trail().push(push_back_vector(m_rdivisions));
} }
@ -50,7 +37,7 @@ namespace nla {
void divisions::add_bounded_division(lpvar q, lpvar x, lpvar y) { void divisions::add_bounded_division(lpvar q, lpvar x, lpvar y) {
if (x == null_lpvar || y == null_lpvar || q == null_lpvar) if (x == null_lpvar || y == null_lpvar || q == null_lpvar)
return; return;
if (lp::tv::is_term(x) || lp::tv::is_term(y) || lp::tv::is_term(q)) if (m_core.lra.column_has_term(x) || m_core.lra.column_has_term(y) || m_core.lra.column_has_term(q))
return; return;
m_bounded_divisions.push_back({ q, x, y }); m_bounded_divisions.push_back({ q, x, y });
m_core.trail().push(push_back_vector(m_bounded_divisions)); m_core.trail().push(push_back_vector(m_bounded_divisions));

View file

@ -406,9 +406,8 @@ namespace nla {
coeffs.push_back({lc*coeff, m_mon2var.find(vars)->second}); coeffs.push_back({lc*coeff, m_mon2var.find(vars)->second});
} }
lp::lpvar term_index = c().lra.add_term(coeffs, UINT_MAX); lp::lpvar j = c().lra.add_term(coeffs, UINT_MAX);
term_index = c().lra.map_term_index_to_column_index(term_index); c().lra.update_column_type_and_bound(j, lp::lconstraint_kind::EQ, offset, e.dep());
c().lra.update_column_type_and_bound(term_index, lp::lconstraint_kind::EQ, offset, e.dep());
c().m_check_feasible = true; c().m_check_feasible = true;
return true; return true;
} }

View file

@ -80,12 +80,12 @@ namespace nla {
lbool powers::check(lpvar r, lpvar x, lpvar y, vector<lemma>& lemmas) { lbool powers::check(lpvar r, lpvar x, lpvar y, vector<lemma>& lemmas) {
TRACE("nla", tout << r << " == " << x << "^" << y << "\n"); TRACE("nla", tout << r << " == " << x << "^" << y << "\n");
core& c = m_core;
if (x == null_lpvar || y == null_lpvar || r == null_lpvar) if (x == null_lpvar || y == null_lpvar || r == null_lpvar)
return l_undef; return l_undef;
if (lp::tv::is_term(x) || lp::tv::is_term(y) || lp::tv::is_term(r)) if (c.lra.column_has_term(x) || c.lra.column_has_term(y) || c.lra.column_has_term(r))
return l_undef; return l_undef;
core& c = m_core;
if (c.use_nra_model()) if (c.use_nra_model())
return l_undef; return l_undef;

View file

@ -83,7 +83,7 @@ namespace nla {
nlsat::anum_manager& solver::am() { return m_core->m_nra.am(); } nlsat::anum_manager& solver::am() { return m_core->m_nra.am(); }
nlsat::anum const& solver::am_value(lp::var_index v) const { nlsat::anum const& solver::am_value(lp::lpvar v) const {
SASSERT(use_nra_model()); SASSERT(use_nra_model());
return m_core->m_nra.value(v); return m_core->m_nra.value(v);
} }

View file

@ -46,7 +46,7 @@ namespace nla {
bool use_nra_model() const; bool use_nra_model() const;
core& get_core(); core& get_core();
nlsat::anum_manager& am(); nlsat::anum_manager& am();
nlsat::anum const& am_value(lp::var_index v) const; nlsat::anum const& am_value(lp::lpvar v) const;
scoped_anum& tmp1(); scoped_anum& tmp1();
scoped_anum& tmp2(); scoped_anum& tmp2();
vector<nla::lemma> const& lemmas() const; vector<nla::lemma> const& lemmas() const;

View file

@ -22,7 +22,7 @@ namespace nla {
typedef lp::lconstraint_kind llc; typedef lp::lconstraint_kind llc;
typedef lp::constraint_index lpci; typedef lp::constraint_index lpci;
typedef lp::explanation expl_set; typedef lp::explanation expl_set;
typedef lp::var_index lpvar; typedef lp::lpvar lpvar;
const lpvar null_lpvar = UINT_MAX; const lpvar null_lpvar = UINT_MAX;

View file

@ -71,12 +71,11 @@ struct solver::imp {
} }
} }
for (unsigned i = lra.terms().size(); i-- > 0; ) { for (const auto *t : lra.terms() ) {
auto const& t = lra.term(i); for (auto const iv : *t) {
for (auto const iv : t) { auto v = iv.j();
auto v = iv.column().index();
var2occurs.reserve(v + 1); var2occurs.reserve(v + 1);
var2occurs[v].terms.push_back(i); var2occurs[v].terms.push_back(t->j());
} }
} }
@ -99,17 +98,15 @@ struct solver::imp {
todo.push_back(w); todo.push_back(w);
for (auto ti : var2occurs[v].terms) { for (auto ti : var2occurs[v].terms) {
for (auto iv : lra.term(ti)) for (auto iv : lra.get_term(ti))
todo.push_back(iv.column().index()); todo.push_back(iv.j());
auto vi = lp::tv::mask_term(ti); todo.push_back(ti);
todo.push_back(lra.map_term_index_to_column_index(vi));
} }
if (lra.column_corresponds_to_term(v)) { if (lra.column_has_term(v)) {
m_term_set.insert(v); m_term_set.insert(v);
lp::tv ti = lp::tv::raw(lra.column_to_reported_index(v)); for (auto kv : lra.get_term(v))
for (auto kv : lra.get_term(ti)) todo.push_back(kv.j());
todo.push_back(kv.column().index());
} }
if (m_nla_core.is_monic_var(v)) { if (m_nla_core.is_monic_var(v)) {
@ -517,16 +514,16 @@ struct solver::imp {
bool is_int(lp::var_index v) { bool is_int(lp::lpvar v) {
return lra.var_is_int(v); return lra.var_is_int(v);
} }
polynomial::var lp2nl(lp::var_index v) { polynomial::var lp2nl(lp::lpvar v) {
polynomial::var r; polynomial::var r;
if (!m_lp2nl.find(v, r)) { if (!m_lp2nl.find(v, r)) {
r = m_nlsat->mk_var(is_int(v)); r = m_nlsat->mk_var(is_int(v));
m_lp2nl.insert(v, r); m_lp2nl.insert(v, r);
if (!m_term_set.contains(v) && lra.column_corresponds_to_term(v)) { if (!m_term_set.contains(v) && lra.column_has_term(v)) {
m_term_set.insert(v); m_term_set.insert(v);
} }
} }
@ -534,14 +531,13 @@ struct solver::imp {
} }
// //
void add_term(unsigned term_column) { void add_term(unsigned term_column) {
lp::tv ti = lp::tv::raw(lra.column_to_reported_index(term_column)); const lp::lar_term& t = lra.get_term(term_column);
const lp::lar_term& t = lra.get_term(ti);
// code that creates a polynomial equality between the linear coefficients and // code that creates a polynomial equality between the linear coefficients and
// variable representing the term. // variable representing the term.
svector<polynomial::var> vars; svector<polynomial::var> vars;
rational den(1); rational den(1);
for (lp::lar_term::ival kv : t) { for (lp::lar_term::ival kv : t) {
vars.push_back(lp2nl(kv.column().index())); vars.push_back(lp2nl(kv.j()));
den = lcm(den, denominator(kv.coeff())); den = lcm(den, denominator(kv.coeff()));
} }
vars.push_back(lp2nl(term_column)); vars.push_back(lp2nl(term_column));
@ -559,7 +555,7 @@ struct solver::imp {
m_nlsat->mk_clause(1, &lit, nullptr); m_nlsat->mk_clause(1, &lit, nullptr);
} }
nlsat::anum const& value(lp::var_index v) { nlsat::anum const& value(lp::lpvar v) {
polynomial::var pv; polynomial::var pv;
if (m_lp2nl.find(v, pv)) if (m_lp2nl.find(v, pv))
return m_nlsat->value(pv); return m_nlsat->value(pv);
@ -636,7 +632,7 @@ std::ostream& solver::display(std::ostream& out) const {
return m_imp->display(out); return m_imp->display(out);
} }
nlsat::anum const& solver::value(lp::var_index v) { nlsat::anum const& solver::value(lp::lpvar v) {
return m_imp->value(v); return m_imp->value(v);
} }

View file

@ -55,7 +55,7 @@ namespace nra {
/* /*
\brief Access model. \brief Access model.
*/ */
nlsat::anum const& value(lp::var_index v); nlsat::anum const& value(lp::lpvar v);
nlsat::anum_manager& am(); nlsat::anum_manager& am();

View file

@ -346,14 +346,14 @@ public:
// we use the form -it + 1 = 0 // we use the form -it + 1 = 0
m_work_vector.set_value(one_of_type<T>(), bj); m_work_vector.set_value(one_of_type<T>(), bj);
for (auto p : row) { for (auto p : row) {
m_work_vector.set_value(-p.coeff(), p.column().index()); m_work_vector.set_value(-p.coeff(), p.j());
// but take care of the basis 1 later // but take care of the basis 1 later
} }
// now iterate with pivoting // now iterate with pivoting
fill_last_row_with_pivoting_loop_block(bj, basis_heading); fill_last_row_with_pivoting_loop_block(bj, basis_heading);
for (auto p : row) { for (auto p : row) {
fill_last_row_with_pivoting_loop_block(p.column().index(), basis_heading); fill_last_row_with_pivoting_loop_block(p.j(), basis_heading);
} }
unsigned last_row = row_count() - 1; unsigned last_row = row_count() - 1;

View file

@ -41,10 +41,7 @@ public:
class var_register { class var_register {
vector<ext_var_info> m_local_to_external; vector<ext_var_info> m_local_to_external;
std::unordered_map<unsigned, unsigned> m_external_to_local; std::unordered_map<unsigned, unsigned> m_external_to_local;
unsigned m_locals_mask;
unsigned m_locals_mask_inverted;
public: public:
var_register(bool mask_locals): m_locals_mask(mask_locals? tv::left_most_bit: 0), m_locals_mask_inverted(~m_locals_mask) {}
void set_name(unsigned j, std::string name) { void set_name(unsigned j, std::string name) {
m_local_to_external[j].set_name(name); m_local_to_external[j].set_name(name);
@ -63,7 +60,7 @@ public:
} }
m_local_to_external.push_back(ext_var_info(user_var, is_int)); m_local_to_external.push_back(ext_var_info(user_var, is_int));
unsigned local = ( size() - 1 ) | m_locals_mask; unsigned local = size() - 1;
if (user_var != UINT_MAX) if (user_var != UINT_MAX)
m_external_to_local[user_var] = local; m_external_to_local[user_var] = local;
@ -79,7 +76,7 @@ public:
// returns UINT_MAX if // returns UINT_MAX if
unsigned local_to_external(unsigned local_var) const { unsigned local_to_external(unsigned local_var) const {
unsigned k = local_var & m_locals_mask_inverted; unsigned k = local_var;
if (k >= m_local_to_external.size()) if (k >= m_local_to_external.size())
return UINT_MAX; return UINT_MAX;
return m_local_to_external[k].external_j(); return m_local_to_external[k].external_j();
@ -119,7 +116,7 @@ public:
local_j = UINT_MAX; local_j = UINT_MAX;
return false; return false;
} }
local_j = it->second & m_locals_mask_inverted; local_j = it->second;
is_int = m_local_to_external[local_j].is_integer(); is_int = m_local_to_external[local_j].is_integer();
return true; return true;
} }
@ -129,7 +126,7 @@ public:
} }
bool local_is_int(unsigned j) const { bool local_is_int(unsigned j) const {
return m_local_to_external[j & m_locals_mask_inverted].is_integer(); return m_local_to_external[j].is_integer();
} }
void shrink(unsigned shrunk_size) { void shrink(unsigned shrunk_size) {

View file

@ -45,8 +45,7 @@ namespace arith {
} }
unsigned nv = get_num_vars(); unsigned nv = get_num_vars();
for (unsigned v = 0; v < nv; ++v) { for (unsigned v = 0; v < nv; ++v) {
auto t = get_tv(v); auto vi = lp().external_to_local(v);
auto vi = lp().external_to_column_index(v);
out << "v" << v << " "; out << "v" << v << " ";
if (is_bool(v)) { if (is_bool(v)) {
euf::enode* n = var2enode(v); euf::enode* n = var2enode(v);
@ -57,10 +56,10 @@ namespace arith {
} }
} }
else { else {
if (t.is_null()) if (vi == lp::null_lpvar)
out << "null"; out << "null";
else else
out << (t.is_term() ? "t" : "j") << vi; out << (lp().column_has_term(vi) ? "t" : "j") << vi;
if (m_nla && m_nla->use_nra_model() && is_registered_var(v)) { if (m_nla && m_nla->use_nra_model() && is_registered_var(v)) {
scoped_anum an(m_nla->am()); scoped_anum an(m_nla->am());
m_nla->am().display(out << " = ", nl_value(v, an)); m_nla->am().display(out << " = ", nl_value(v, an));

View file

@ -507,11 +507,11 @@ namespace arith {
} }
else { else {
vi = lp().add_term(m_left_side, v); vi = lp().add_term(m_left_side, v);
SASSERT(lp::tv::is_term(vi)); SASSERT(lp().column_has_term(vi));
TRACE("arith_verbose", TRACE("arith_verbose",
tout << "v" << v << " := " << mk_pp(term, m) tout << "v" << v << " := " << mk_pp(term, m)
<< " slack: " << vi << " scopes: " << m_scopes.size() << "\n"; << " slack: " << vi << " scopes: " << m_scopes.size() << "\n";
lp().print_term(lp().get_term(lp::tv::raw(vi)), tout) << "\n";); lp().print_term(lp().get_term(vi), tout) << "\n";);
} }
} }
return v; return v;
@ -541,8 +541,6 @@ namespace arith {
rational const& r = m_columns[var]; rational const& r = m_columns[var];
if (!r.is_zero()) { if (!r.is_zero()) {
auto vi = register_theory_var_in_lar_solver(var); auto vi = register_theory_var_in_lar_solver(var);
if (lp::tv::is_term(vi))
vi = lp().map_term_index_to_column_index(vi);
m_left_side.push_back(std::make_pair(r, vi)); m_left_side.push_back(std::make_pair(r, vi));
m_columns[var].reset(); m_columns[var].reset();
} }
@ -625,9 +623,6 @@ namespace arith {
return lp().external_to_local(v); return lp().external_to_local(v);
} }
lp::tv solver::get_tv(theory_var v) const {
return lp::tv::raw(get_lpvar(v));
}
/** /**
\brief We must redefine this method, because theory of arithmetic contains \brief We must redefine this method, because theory of arithmetic contains

View file

@ -59,18 +59,10 @@ namespace arith {
int64_t val = 0; int64_t val = 0;
lp::lar_term const& term = s.lp().get_term(t); lp::lar_term const& term = s.lp().get_term(t);
for (lp::lar_term::ival const& arg : term) { for (lp::lar_term::ival const& arg : term) {
auto t2 = s.lp().column2tv(arg.column()); auto t2 = arg.j();
auto w = s.lp().local_to_external(t2.id()); auto w = s.lp().local_to_external(t2);
val += to_numeral(arg.coeff()) * m_vars[w].m_best_value; val += to_numeral(arg.coeff()) * m_vars[w].m_best_value;
} }
if (v == 52) {
verbose_stream() << "update v" << v << " := " << val << "\n";
for (lp::lar_term::ival const& arg : term) {
auto t2 = s.lp().column2tv(arg.column());
auto w = s.lp().local_to_external(t2.id());
verbose_stream() << "v" << w << " := " << m_vars[w].m_best_value << " * " << to_numeral(arg.coeff()) << "\n";
}
}
m_vars[v].m_best_value = val; m_vars[v].m_best_value = val;
} }
@ -81,12 +73,12 @@ namespace arith {
continue; continue;
int64_t new_value = m_vars[v].m_best_value; int64_t new_value = m_vars[v].m_best_value;
s.ensure_column(v); s.ensure_column(v);
lp::column_index vj = s.lp().to_column_index(v); lp::lpvar vj = s.lp().external_to_local(v);
SASSERT(!vj.is_null()); SASSERT(vj != lp::null_lpvar);
if (!s.lp().is_base(vj.index())) { if (!s.lp().is_base(vj)) {
rational new_value_(new_value, rational::i64()); rational new_value_(new_value, rational::i64());
lp::impq val(new_value_, rational::zero()); lp::impq val(new_value_, rational::zero());
s.lp().set_value_for_nbasic_column(vj.index(), val); s.lp().set_value_for_nbasic_column(vj, val);
} }
} }
@ -460,18 +452,18 @@ namespace arith {
return 0; return 0;
} }
void sls::add_args(sat::bool_var bv, ineq& ineq, lp::tv t, theory_var v, int64_t sign) { void sls::add_args(sat::bool_var bv, ineq& ineq, lp::lpvar t, theory_var v, int64_t sign) {
if (t.is_term()) { if (s.lp().column_has_term(t)) {
lp::lar_term const& term = s.lp().get_term(t); lp::lar_term const& term = s.lp().get_term(t);
m_terms.push_back({t,v}); m_terms.push_back({t,v});
for (lp::lar_term::ival arg : term) { for (lp::lar_term::ival arg : term) {
auto t2 = s.lp().column2tv(arg.column()); auto t2 = arg.j();
auto w = s.lp().local_to_external(t2.id()); auto w = s.lp().local_to_external(t2);
add_arg(bv, ineq, sign * to_numeral(arg.coeff()), w); add_arg(bv, ineq, sign * to_numeral(arg.coeff()), w);
} }
} }
else else
add_arg(bv, ineq, sign, s.lp().local_to_external(t.id())); add_arg(bv, ineq, sign, s.lp().local_to_external(t));
} }
void sls::init_bool_var(sat::bool_var bv) { void sls::init_bool_var(sat::bool_var bv) {
@ -480,7 +472,7 @@ namespace arith {
api_bound* b = nullptr; api_bound* b = nullptr;
s.m_bool_var2bound.find(bv, b); s.m_bool_var2bound.find(bv, b);
if (b) { if (b) {
auto t = b->tv(); auto t = b->column_index();
rational bound = b->get_value(); rational bound = b->get_value();
bool should_minus = false; bool should_minus = false;
sls::ineq_kind op; sls::ineq_kind op;
@ -503,8 +495,8 @@ namespace arith {
if (e && m.is_eq(e, l, r) && s.a.is_int_real(l)) { if (e && m.is_eq(e, l, r) && s.a.is_int_real(l)) {
theory_var u = s.get_th_var(l); theory_var u = s.get_th_var(l);
theory_var v = s.get_th_var(r); theory_var v = s.get_th_var(r);
lp::tv tu = s.get_tv(u); lp::lpvar tu = s.get_column(u);
lp::tv tv = s.get_tv(v); lp::lpvar tv = s.get_column(v);
auto& ineq = new_ineq(sls::ineq_kind::EQ, 0); auto& ineq = new_ineq(sls::ineq_kind::EQ, 0);
add_args(bv, ineq, tu, u, 1); add_args(bv, ineq, tu, u, 1);
add_args(bv, ineq, tv, v, -1); add_args(bv, ineq, tv, v, -1);

View file

@ -105,7 +105,7 @@ namespace arith {
config m_config; config m_config;
scoped_ptr_vector<ineq> m_bool_vars; scoped_ptr_vector<ineq> m_bool_vars;
vector<var_info> m_vars; vector<var_info> m_vars;
svector<std::pair<lp::tv, euf::theory_var>> m_terms; svector<std::pair<lp::lpvar, euf::theory_var>> m_terms;
bool m_dscore_mode = false; bool m_dscore_mode = false;
@ -140,7 +140,7 @@ namespace arith {
void add_vars(); void add_vars();
sls::ineq& new_ineq(ineq_kind op, int64_t const& bound); sls::ineq& new_ineq(ineq_kind op, int64_t const& bound);
void add_arg(sat::bool_var bv, ineq& ineq, int64_t const& c, var_t v); void add_arg(sat::bool_var bv, ineq& ineq, int64_t const& c, var_t v);
void add_args(sat::bool_var bv, ineq& ineq, lp::tv t, euf::theory_var v, int64_t sign); void add_args(sat::bool_var bv, ineq& ineq, lp::lpvar j, euf::theory_var v, int64_t sign);
void init_bool_var(sat::bool_var v); void init_bool_var(sat::bool_var v);
void init_bool_var_assignment(sat::bool_var v); void init_bool_var_assignment(sat::bool_var v);

View file

@ -370,7 +370,7 @@ namespace arith {
void solver::refine_bound(theory_var v, const lp::implied_bound& be) { void solver::refine_bound(theory_var v, const lp::implied_bound& be) {
lpvar vi = be.m_j; lpvar vi = be.m_j;
if (lp::tv::is_term(vi)) if (lp().column_has_term(vi))
return; return;
expr_ref w(var2expr(v), m); expr_ref w(var2expr(v), m);
if (a.is_add(w) || a.is_numeral(w) || m.is_ite(w)) if (a.is_add(w) || a.is_numeral(w) || m.is_ite(w))
@ -418,7 +418,7 @@ namespace arith {
++m_stats.m_assert_upper; ++m_stats.m_assert_upper;
inf_rational value = b.get_value(is_true); inf_rational value = b.get_value(is_true);
if (propagate_eqs() && value.is_rational()) if (propagate_eqs() && value.is_rational())
propagate_eqs(b.tv(), ci, k, b, value.get_rational()); propagate_eqs(b.column_index(), ci, k, b, value.get_rational());
#if 0 #if 0
if (propagation_mode() != BP_NONE) if (propagation_mode() != BP_NONE)
lp().add_column_rows_to_touched_rows(b.tv().id()); lp().add_column_rows_to_touched_rows(b.tv().id());
@ -426,30 +426,29 @@ namespace arith {
} }
void solver::propagate_eqs(lp::tv t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) { void solver::propagate_eqs(lp::lpvar t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) {
u_dependency* dep; u_dependency* dep;
auto& dm = lp().dep_manager(); auto& dm = lp().dep_manager();
if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t.index(), dep, value)) { if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t, dep, value)) {
fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value); fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value);
} }
else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t.index(), dep, value)) { else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t, dep, value)) {
fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value); fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value);
} }
} }
bool solver::set_bound(lp::tv tv, lp::constraint_index ci, rational const& v, bool is_lower) { bool solver::set_bound(lp::lpvar tv, lp::constraint_index ci, rational const& v, bool is_lower) {
if (tv.is_term()) { if (lp().column_has_term(tv)) {
lpvar ti = tv.id();
auto& vec = is_lower ? m_lower_terms : m_upper_terms; auto& vec = is_lower ? m_lower_terms : m_upper_terms;
if (vec.size() <= ti) { if (vec.size() <= tv) {
vec.resize(ti + 1, constraint_bound(UINT_MAX, rational())); vec.resize(tv + 1, constraint_bound(UINT_MAX, rational()));
} }
constraint_bound& b = vec[ti]; constraint_bound& b = vec[tv];
if (b.first == UINT_MAX || (is_lower ? b.second < v : b.second > v)) { if (b.first == UINT_MAX || (is_lower ? b.second < v : b.second > v)) {
TRACE("arith", tout << "tighter bound " << tv.to_string() << "\n";); TRACE("arith", tout << "tighter bound " << tv << "\n";);
m_history.push_back(vec[ti]); m_history.push_back(vec[tv]);
ctx.push(history_trail<constraint_bound>(vec, ti, m_history)); ctx.push(history_trail<constraint_bound>(vec, tv, m_history));
b.first = ci; b.first = ci;
b.second = v; b.second = v;
} }
@ -461,10 +460,10 @@ namespace arith {
rational b; rational b;
u_dependency* dep = nullptr; u_dependency* dep = nullptr;
if (is_lower) { if (is_lower) {
return lp().has_lower_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; return lp().has_lower_bound(tv, dep, b, is_strict) && !is_strict && b == v;
} }
else { else {
return lp().has_upper_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; return lp().has_upper_bound(tv, dep, b, is_strict) && !is_strict && b == v;
} }
} }
} }
@ -772,7 +771,7 @@ namespace arith {
bool solver::has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } bool solver::has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); }
bool solver::has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) { bool solver::has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) {
if (lp::tv::is_term(vi)) { if (lp().column_has_term(vi)) {
theory_var v = lp().local_to_external(vi); theory_var v = lp().local_to_external(vi);
rational val; rational val;
TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";); TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";);
@ -782,9 +781,8 @@ namespace arith {
} }
auto& vec = is_lower ? m_lower_terms : m_upper_terms; auto& vec = is_lower ? m_lower_terms : m_upper_terms;
lpvar ti = lp::tv::unmask_term(vi); if (vec.size() > vi) {
if (vec.size() > ti) { auto& [ci, coeff] = vec[vi];
auto& [ci, coeff] = vec[ti];
if (ci == UINT_MAX) if (ci == UINT_MAX)
return false; return false;
dep = lp().dep_manager().mk_leaf(ci); dep = lp().dep_manager().mk_leaf(ci);
@ -876,11 +874,16 @@ namespace arith {
lp::impq solver::get_ivalue(theory_var v) const { lp::impq solver::get_ivalue(theory_var v) const {
SASSERT(is_registered_var(v)); SASSERT(is_registered_var(v));
return m_solver->get_tv_ivalue(get_tv(v)); return m_solver->get_column_value(get_column(v));
} }
lp::lpvar solver::get_column(theory_var v) const {
SASSERT(is_registered_var(v));
return m_solver->external_to_local(v);
}
rational solver::get_value(theory_var v) const { rational solver::get_value(theory_var v) const {
return is_registered_var(v) ? m_solver->get_tv_value(get_tv(v)) : rational::zero(); return is_registered_var(v) ? m_solver->get_value(get_column(v)) : rational::zero();
} }
void solver::random_update() { void solver::random_update() {
@ -895,18 +898,18 @@ namespace arith {
if (is_bool(v)) if (is_bool(v))
continue; continue;
ensure_column(v); ensure_column(v);
lp::column_index vj = lp().to_column_index(v); lp::lpvar vj = lp().external_to_local(v);
SASSERT(!vj.is_null()); SASSERT(vj != lp::null_lpvar);
theory_var other = m_model_eqs.insert_if_not_there(v); theory_var other = m_model_eqs.insert_if_not_there(v);
if (is_equal(v, other)) if (is_equal(v, other))
continue; continue;
if (!lp().is_fixed(vj)) if (!lp().column_is_fixed(vj))
vars.push_back(vj.index()); vars.push_back(vj);
else if (!m_tmp_var_set.contains(other)) { else if (!m_tmp_var_set.contains(other)) {
lp::column_index other_j = lp().to_column_index(other); lp::lpvar other_j = lp().external_to_local(other);
if (!lp().is_fixed(other_j)) { if (!lp().column_is_fixed(other_j)) {
m_tmp_var_set.insert(other); m_tmp_var_set.insert(other);
vars.push_back(other_j.index()); vars.push_back(other_j);
} }
} }
} }
@ -1068,14 +1071,14 @@ namespace arith {
nlsat::anum const& solver::nl_value(theory_var v, scoped_anum& r) const { nlsat::anum const& solver::nl_value(theory_var v, scoped_anum& r) const {
SASSERT(m_nla); SASSERT(m_nla);
SASSERT(m_nla->use_nra_model()); SASSERT(m_nla->use_nra_model());
auto t = get_tv(v); auto t = get_column(v);
if (!t.is_term()) { if (!lp().column_has_term(t)) {
m_nla->am().set(r, m_nla->am_value(t.id())); m_nla->am().set(r, m_nla->am_value(t));
} }
else { else {
m_todo_terms.push_back(std::make_pair(t, rational::one())); m_todo_terms.push_back(std::make_pair(t, rational::one()));
TRACE("nl_value", tout << "v" << v << " " << t.to_string() << "\n";); TRACE("nl_value", tout << "v" << v << " " << t << "\n";);
TRACE("nl_value", tout << "v" << v << " := w" << t.to_string() << "\n"; TRACE("nl_value", tout << "v" << v << " := w" << t << "\n";
lp().print_term(lp().get_term(t), tout) << "\n";); lp().print_term(lp().get_term(t), tout) << "\n";);
m_nla->am().set(r, 0); m_nla->am().set(r, 0);
@ -1090,14 +1093,14 @@ namespace arith {
m_nla->am().set(r1, c1.to_mpq()); m_nla->am().set(r1, c1.to_mpq());
m_nla->am().add(r, r1, r); m_nla->am().add(r, r1, r);
for (lp::lar_term::ival arg : term) { for (lp::lar_term::ival arg : term) {
auto wi = lp().column2tv(arg.column()); auto wi = arg.j();
c1 = arg.coeff() * wcoeff; c1 = arg.coeff() * wcoeff;
if (wi.is_term()) { if (lp().column_has_term(wi)) {
m_todo_terms.push_back(std::make_pair(wi, c1)); m_todo_terms.push_back(std::make_pair(wi, c1));
} }
else { else {
m_nla->am().set(r1, c1.to_mpq()); m_nla->am().set(r1, c1.to_mpq());
m_nla->am().mul(m_nla->am_value(wi.id()), r1, r1); m_nla->am().mul(m_nla->am_value(wi), r1, r1);
m_nla->am().add(r1, r, r); m_nla->am().add(r1, r, r);
} }
} }
@ -1393,17 +1396,17 @@ namespace arith {
TRACE("arith", lp().print_term(term, tout) << "\n";); TRACE("arith", lp().print_term(term, tout) << "\n";);
for (lp::lar_term::ival ti : term) { for (lp::lar_term::ival ti : term) {
theory_var w; theory_var w;
auto tv = lp().column2tv(ti.column()); auto tv = ti.j();
if (tv.is_term()) { if (lp().column_has_term(tv)) {
lp::lar_term const& term1 = lp().get_term(tv); lp::lar_term const& term1 = lp().get_term(tv);
rational coeff2 = coeff * ti.coeff(); rational coeff2 = coeff * ti.coeff();
term2coeffs(term1, coeffs, coeff2); term2coeffs(term1, coeffs, coeff2);
continue; continue;
} }
else { else {
w = lp().local_to_external(tv.id()); w = lp().local_to_external(tv);
SASSERT(w >= 0); SASSERT(w >= 0);
TRACE("arith", tout << (tv.id()) << ": " << w << "\n";); TRACE("arith", tout << tv << ": " << w << "\n";);
} }
rational c0(0); rational c0(0);
coeffs.find(w, c0); coeffs.find(w, c0);

View file

@ -38,7 +38,7 @@ namespace euf {
namespace arith { namespace arith {
typedef ptr_vector<lp_api::bound<sat::literal>> lp_bounds; typedef ptr_vector<lp_api::bound<sat::literal>> lp_bounds;
typedef lp::var_index lpvar; typedef lp::lpvar lpvar;
typedef euf::theory_var theory_var; typedef euf::theory_var theory_var;
typedef euf::theory_id theory_id; typedef euf::theory_id theory_id;
typedef euf::enode enode; typedef euf::enode enode;
@ -245,7 +245,7 @@ namespace arith {
symbol m_farkas; symbol m_farkas;
std_vector<lp::implied_bound> m_implied_bounds; std_vector<lp::implied_bound> m_implied_bounds;
lp::lp_bound_propagator<solver> m_bp; lp::lp_bound_propagator<solver> m_bp;
mutable vector<std::pair<lp::tv, rational>> m_todo_terms; mutable vector<std::pair<lp::lpvar, rational>> m_todo_terms;
// lemmas // lemmas
lp::explanation m_explanation; lp::explanation m_explanation;
@ -306,7 +306,7 @@ namespace arith {
bool reflect(expr* n) const; bool reflect(expr* n) const;
lpvar get_lpvar(theory_var v) const; lpvar get_lpvar(theory_var v) const;
lp::tv get_tv(theory_var v) const; lp::lpvar get_column(theory_var v) const;
// axioms // axioms
void mk_div_axiom(expr* p, expr* q); void mk_div_axiom(expr* p, expr* q);
@ -348,7 +348,7 @@ namespace arith {
iterator end, iterator end,
bool& found_compatible); bool& found_compatible);
void propagate_eqs(lp::tv t, lp::constraint_index ci, lp::lconstraint_kind k, api_bound& b, rational const& value); void propagate_eqs(lp::lpvar t, lp::constraint_index ci, lp::lconstraint_kind k, api_bound& b, rational const& value);
void propagate_basic_bounds(unsigned qhead); void propagate_basic_bounds(unsigned qhead);
void propagate_bounds_with_lp_solver(); void propagate_bounds_with_lp_solver();
void propagate_bound(literal lit, api_bound& b); void propagate_bound(literal lit, api_bound& b);
@ -362,9 +362,9 @@ namespace arith {
api_bound* mk_var_bound(sat::literal lit, theory_var v, lp_api::bound_kind bk, rational const& bound); api_bound* mk_var_bound(sat::literal lit, theory_var v, lp_api::bound_kind bk, rational const& bound);
lp::lconstraint_kind bound2constraint_kind(bool is_int, lp_api::bound_kind bk, bool is_true); lp::lconstraint_kind bound2constraint_kind(bool is_int, lp_api::bound_kind bk, bool is_true);
void fixed_var_eh(theory_var v1, u_dependency* dep, rational const& bound); void fixed_var_eh(theory_var v1, u_dependency* dep, rational const& bound);
bool set_upper_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, false); } bool set_upper_bound(lp::lpvar t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, false); }
bool set_lower_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, true); } bool set_lower_bound(lp::lpvar t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, true); }
bool set_bound(lp::tv tv, lp::constraint_index ci, rational const& v, bool is_lower); bool set_bound(lp::lpvar tv, lp::constraint_index ci, rational const& v, bool is_lower);
typedef std::pair<lp::constraint_index, rational> constraint_bound; typedef std::pair<lp::constraint_index, rational> constraint_bound;
vector<constraint_bound> m_lower_terms; vector<constraint_bound> m_lower_terms;

View file

@ -47,7 +47,7 @@
#include "util/scoped_timer.h" #include "util/scoped_timer.h"
#include "util/distribution.h" #include "util/distribution.h"
typedef lp::var_index lpvar; typedef lp::lpvar lpvar;
namespace smt { namespace smt {
@ -790,10 +790,6 @@ class theory_lra::imp {
return v == null_theory_var ? lp::null_lpvar : lp().external_to_local(v); return v == null_theory_var ? lp::null_lpvar : lp().external_to_local(v);
} }
lp::tv get_tv(theory_var v) const {
return lp::tv::raw(get_lpvar(v));
}
theory_var internalize_linearized_def(app* term, scoped_internalize_state& st) { theory_var internalize_linearized_def(app* term, scoped_internalize_state& st) {
theory_var v = mk_var(term); theory_var v = mk_var(term);
TRACE("arith_internalize", tout << "v" << v << " " << bpp(term) << "\n";); TRACE("arith_internalize", tout << "v" << v << " " << bpp(term) << "\n";);
@ -812,11 +808,11 @@ class theory_lra::imp {
} }
else { else {
vi = lp().add_term(m_left_side, v); vi = lp().add_term(m_left_side, v);
SASSERT(lp::tv::is_term(vi)); SASSERT(lp().column_has_term(vi));
TRACE("arith_verbose", TRACE("arith_verbose",
tout << "v" << v << " := " << mk_pp(term, m) tout << "v" << v << " := " << mk_pp(term, m)
<< " slack: " << vi << " scopes: " << m_scopes.size() << "\n"; << " slack: " << vi << " scopes: " << m_scopes.size() << "\n";
lp().print_term(lp().get_term(lp::tv::raw(vi)), tout) << "\n";); lp().print_term(lp().get_term(vi), tout) << "\n";);
} }
} }
@ -1432,15 +1428,15 @@ public:
register_theory_var_in_lar_solver(v); register_theory_var_in_lar_solver(v);
} }
mutable vector<std::pair<lp::tv, rational>> m_todo_terms; mutable vector<std::pair<lp::lpvar, rational>> m_todo_terms;
lp::impq get_ivalue(theory_var v) const { lp::impq get_ivalue(theory_var v) const {
SASSERT(is_registered_var(v)); SASSERT(is_registered_var(v));
return lp().get_tv_ivalue(get_tv(v)); return lp().get_column_value(get_lpvar(v));
} }
rational get_value(theory_var v) const { rational get_value(theory_var v) const {
return is_registered_var(v) ? lp().get_tv_value(get_tv(v)) : rational::zero(); return is_registered_var(v) ? lp().get_value(get_lpvar(v)) : rational::zero();
} }
bool m_model_is_initialized{ false }; bool m_model_is_initialized{ false };
@ -1467,8 +1463,8 @@ public:
continue; continue;
} }
ensure_column(v); ensure_column(v);
lp::column_index vj = lp().to_column_index(v); lp::lpvar vj = lp().external_to_local(v);
SASSERT(!vj.is_null()); SASSERT(vj != lp::null_lpvar);
theory_var other = m_model_eqs.insert_if_not_there(v); theory_var other = m_model_eqs.insert_if_not_there(v);
if (other == v) { if (other == v) {
continue; continue;
@ -1476,14 +1472,14 @@ public:
enode * n2 = get_enode(other); enode * n2 = get_enode(other);
if (n1->get_root() == n2->get_root()) if (n1->get_root() == n2->get_root())
continue; continue;
if (!lp().is_fixed(vj)) { if (!lp().column_is_fixed(vj)) {
vars.push_back(vj.index()); vars.push_back(vj);
} }
else if (!m_tmp_var_set.contains(other) ) { else if (!m_tmp_var_set.contains(other) ) {
lp::column_index other_j = lp().to_column_index(other); lp::lpvar other_j = lp().external_to_local(other);
if (!lp().is_fixed(other_j)) { if (!lp().column_is_fixed(other_j)) {
m_tmp_var_set.insert(other); m_tmp_var_set.insert(other);
vars.push_back(other_j.index()); vars.push_back(other_j);
} }
} }
} }
@ -1794,12 +1790,12 @@ public:
expr_ref t(m); expr_ref t(m);
expr_ref_vector ts(m); expr_ref_vector ts(m);
for (lp::lar_term::ival p : term) { for (lp::lar_term::ival p : term) {
auto ti = lp().column2tv(p.column()); auto ti = p.j();
if (ti.is_term()) { if (lp().column_has_term(ti)) {
ts.push_back(multerm(p.coeff(), term2expr(lp().get_term(ti)))); ts.push_back(multerm(p.coeff(), term2expr(lp().get_term(ti))));
} }
else { else {
ts.push_back(multerm(p.coeff(), var2expr(ti.id()))); ts.push_back(multerm(p.coeff(), var2expr(ti)));
} }
} }
if (ts.size() == 1) { if (ts.size() == 1) {
@ -1836,13 +1832,13 @@ public:
lp().print_term(term, out << "bound: "); lp().print_term(term, out << "bound: ");
out << (upper?" <= ":" >= ") << k << "\n"; out << (upper?" <= ":" >= ") << k << "\n";
for (lp::lar_term::ival p : term) { for (lp::lar_term::ival p : term) {
auto ti = lp().column2tv(p.column()); auto ti = p.j();
out << p.coeff() << " * "; out << p.coeff() << " * ";
if (ti.is_term()) { if (lp().column_has_term(ti)) {
lp().print_term(lp().get_term(ti), out) << "\n"; lp().print_term(lp().get_term(ti), out) << "\n";
} }
else { else {
out << "v" << lp().local_to_external(ti.id()) << "\n"; out << "v" << lp().local_to_external(ti) << "\n";
} }
} }
for (auto ev : ex) { for (auto ev : ex) {
@ -2324,7 +2320,7 @@ public:
void refine_bound(theory_var v, const lp::implied_bound& be) { void refine_bound(theory_var v, const lp::implied_bound& be) {
lpvar vi = be.m_j; lpvar vi = be.m_j;
if (lp::tv::is_term(vi)) if (lp().column_has_term(vi))
return; return;
expr_ref w(get_enode(v)->get_expr(), m); expr_ref w(get_enode(v)->get_expr(), m);
if (a.is_add(w) || a.is_numeral(w) || m.is_ite(w)) if (a.is_add(w) || a.is_numeral(w) || m.is_ite(w))
@ -2747,27 +2743,27 @@ public:
++m_stats.m_bounds_propagations; ++m_stats.m_bounds_propagations;
} }
svector<lp::tv> m_todo_vars; svector<lp::lpvar> m_todo_vars;
void add_use_lists(api_bound* b) { void add_use_lists(api_bound* b) {
theory_var v = b->get_var(); theory_var v = b->get_var();
lpvar vi = register_theory_var_in_lar_solver(v); lpvar vi = register_theory_var_in_lar_solver(v);
if (!lp::tv::is_term(vi)) { if (!lp().column_has_term(vi)) {
return; return;
} }
m_todo_vars.push_back(lp::tv::raw(vi)); m_todo_vars.push_back(vi);
while (!m_todo_vars.empty()) { while (!m_todo_vars.empty()) {
auto ti = m_todo_vars.back(); auto ti = m_todo_vars.back();
SASSERT(ti.is_term()); SASSERT(lp().column_has_term(ti));
m_todo_vars.pop_back(); m_todo_vars.pop_back();
lp::lar_term const& term = lp().get_term(ti); lp::lar_term const& term = lp().get_term(ti);
for (auto p : term) { for (auto p : term) {
lp::tv wi = lp().column2tv(p.column()); lp::lpvar wi = p.j();
if (wi.is_term()) { if (lp().column_has_term(wi)) {
m_todo_vars.push_back(wi); m_todo_vars.push_back(wi);
} }
else { else {
unsigned w = lp().local_to_external(wi.id()); unsigned w = lp().local_to_external(wi);
m_use_list.reserve(w + 1, ptr_vector<api_bound>()); m_use_list.reserve(w + 1, ptr_vector<api_bound>());
m_use_list[w].push_back(b); m_use_list[w].push_back(b);
} }
@ -2778,22 +2774,22 @@ public:
void del_use_lists(api_bound* b) { void del_use_lists(api_bound* b) {
theory_var v = b->get_var(); theory_var v = b->get_var();
lpvar vi = get_lpvar(v); lpvar vi = get_lpvar(v);
if (!lp::tv::is_term(vi)) { if (!lp().column_has_term(vi)) {
return; return;
} }
m_todo_vars.push_back(lp::tv::raw(vi)); m_todo_vars.push_back(vi);
while (!m_todo_vars.empty()) { while (!m_todo_vars.empty()) {
auto ti = m_todo_vars.back(); auto ti = m_todo_vars.back();
SASSERT(ti.is_term()); SASSERT(lp().column_has_term(ti));
m_todo_vars.pop_back(); m_todo_vars.pop_back();
lp::lar_term const& term = lp().get_term(ti); lp::lar_term const& term = lp().get_term(ti);
for (auto coeff : term) { for (auto coeff : term) {
auto wi = lp().column2tv(coeff.column()); auto wi = coeff.j();
if (wi.is_term()) { if (lp().column_has_term(wi)) {
m_todo_vars.push_back(wi); m_todo_vars.push_back(wi);
} }
else { else {
unsigned w = lp().local_to_external(wi.id()); unsigned w = lp().local_to_external(wi);
SASSERT(m_use_list[w].back() == b); SASSERT(m_use_list[w].back() == b);
m_use_list[w].pop_back(); m_use_list[w].pop_back();
} }
@ -2872,20 +2868,20 @@ public:
reset_evidence(); reset_evidence();
r.reset(); r.reset();
theory_var v = b.get_var(); theory_var v = b.get_var();
auto ti = get_tv(v); lp::lpvar ti = get_lpvar(v);
SASSERT(ti.is_term()); SASSERT(lp().column_has_term(ti));
lp::lar_term const& term = lp().get_term(ti); lp::lar_term const& term = lp().get_term(ti);
for (auto const mono : term) { for (auto const mono : term) {
auto wi = lp().column2tv(mono.column()); auto wi = mono.j();
u_dependency* ci = nullptr; u_dependency* ci = nullptr;
rational value; rational value;
bool is_strict; bool is_strict;
if (wi.is_term()) { if (lp().column_has_term(wi)) {
return false; return false;
} }
if (mono.coeff().is_neg() == is_lub) { if (mono.coeff().is_neg() == is_lub) {
// -3*x ... <= lub based on lower bound for x. // -3*x ... <= lub based on lower bound for x.
if (!lp().has_lower_bound(wi.id(), ci, value, is_strict)) { if (!lp().has_lower_bound(wi, ci, value, is_strict)) {
return false; return false;
} }
if (is_strict) { if (is_strict) {
@ -2893,7 +2889,7 @@ public:
} }
} }
else { else {
if (!lp().has_upper_bound(wi.id(), ci, value, is_strict)) { if (!lp().has_upper_bound(wi, ci, value, is_strict)) {
return false; return false;
} }
if (is_strict) { if (is_strict) {
@ -2933,7 +2929,7 @@ public:
} }
inf_rational value = b.get_value(is_true); inf_rational value = b.get_value(is_true);
if (propagate_eqs() && value.is_rational()) if (propagate_eqs() && value.is_rational())
propagate_eqs(b.tv(), ci, k, b, value.get_rational()); propagate_eqs(b.column_index(), ci, k, b, value.get_rational());
return true; return true;
#if 0 #if 0
if (should_propagate()) if (should_propagate())
@ -2978,13 +2974,13 @@ public:
vector<constraint_bound> m_lower_terms; vector<constraint_bound> m_lower_terms;
vector<constraint_bound> m_upper_terms; vector<constraint_bound> m_upper_terms;
void propagate_eqs(lp::tv t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) { void propagate_eqs(lp::lpvar t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) {
u_dependency* ci2 = nullptr; u_dependency* ci2 = nullptr;
auto pair = [&]() { return lp().dep_manager().mk_join(lp().dep_manager().mk_leaf(ci1), ci2); }; auto pair = [&]() { return lp().dep_manager().mk_join(lp().dep_manager().mk_leaf(ci1), ci2); };
if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t.index(), ci2, value)) { if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t, ci2, value)) {
fixed_var_eh(b.get_var(), t, pair(), value); fixed_var_eh(b.get_var(), t, pair(), value);
} }
else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t.index(), ci2, value)) { else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t, ci2, value)) {
fixed_var_eh(b.get_var(), t, pair(), value); fixed_var_eh(b.get_var(), t, pair(), value);
} }
} }
@ -2998,24 +2994,23 @@ public:
bool proofs_enabled() const { return m.proofs_enabled(); } bool proofs_enabled() const { return m.proofs_enabled(); }
bool set_upper_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, false); } bool set_upper_bound(lp::lpvar t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, false); }
bool set_lower_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, true); } bool set_lower_bound(lp::lpvar t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, true); }
vector<constraint_bound> m_history; vector<constraint_bound> m_history;
bool set_bound(lp::tv tv, lp::constraint_index ci, rational const& v, bool is_lower) { bool set_bound(lp::lpvar tv, lp::constraint_index ci, rational const& v, bool is_lower) {
if (tv.is_term()) { if (lp().column_has_term(tv)) {
lpvar ti = tv.id();
auto& vec = is_lower ? m_lower_terms : m_upper_terms; auto& vec = is_lower ? m_lower_terms : m_upper_terms;
if (vec.size() <= ti) { if (vec.size() <= tv) {
vec.resize(ti + 1, constraint_bound(UINT_MAX, rational())); vec.resize(tv + 1, constraint_bound(UINT_MAX, rational()));
} }
constraint_bound& b = vec[ti]; constraint_bound& b = vec[tv];
if (b.first == UINT_MAX || (is_lower? b.second < v : b.second > v)) { if (b.first == UINT_MAX || (is_lower? b.second < v : b.second > v)) {
TRACE("arith", tout << "tighter bound " << tv.to_string() << "\n";); TRACE("arith", tout << "tighter bound " << tv << "\n";);
m_history.push_back(vec[ti]); m_history.push_back(vec[tv]);
ctx().push_trail(history_trail<constraint_bound>(vec, ti, m_history)); ctx().push_trail(history_trail<constraint_bound>(vec, tv, m_history));
b.first = ci; b.first = ci;
b.second = v; b.second = v;
} }
@ -3027,10 +3022,10 @@ public:
rational b; rational b;
u_dependency* dep = nullptr; u_dependency* dep = nullptr;
if (is_lower) { if (is_lower) {
return lp().has_lower_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; return lp().has_lower_bound(tv, dep, b, is_strict) && !is_strict && b == v;
} }
else { else {
return lp().has_upper_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; return lp().has_upper_bound(tv, dep, b, is_strict) && !is_strict && b == v;
} }
} }
} }
@ -3052,7 +3047,7 @@ public:
bool has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } bool has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); }
bool has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) { bool has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) {
if (lp::tv::is_term(vi)) { if (lp().column_has_term(vi)) {
theory_var v = lp().local_to_external(vi); theory_var v = lp().local_to_external(vi);
rational val; rational val;
TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";); TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";);
@ -3062,9 +3057,8 @@ public:
} }
auto& vec = is_lower ? m_lower_terms : m_upper_terms; auto& vec = is_lower ? m_lower_terms : m_upper_terms;
lpvar ti = lp::tv::unmask_term(vi); if (vec.size() > vi) {
if (vec.size() > ti) { auto const& [ci, coeff] = vec[vi];
auto const& [ci, coeff] = vec[ti];
if (ci == UINT_MAX) if (ci == UINT_MAX)
return false; return false;
dep = lp().dep_manager().mk_leaf(ci); dep = lp().dep_manager().mk_leaf(ci);
@ -3145,7 +3139,7 @@ public:
ctx().assign_eq(x, y, eq_justification(js)); ctx().assign_eq(x, y, eq_justification(js));
} }
void fixed_var_eh(theory_var v, lp::tv t, u_dependency* dep, rational const& bound) { void fixed_var_eh(theory_var v, lp::lpvar t, u_dependency* dep, rational const& bound) {
theory_var w = null_theory_var; theory_var w = null_theory_var;
enode* x = get_enode(v); enode* x = get_enode(v);
if (m_value2var.find(bound, w)) if (m_value2var.find(bound, w))
@ -3314,14 +3308,14 @@ public:
nlsat::anum const& nl_value(theory_var v, scoped_anum& r) const { nlsat::anum const& nl_value(theory_var v, scoped_anum& r) const {
SASSERT(use_nra_model()); SASSERT(use_nra_model());
auto t = get_tv(v); auto t = get_lpvar(v);
if (!t.is_term()) if (!lp().column_has_term(t))
m_nla->am().set(r, m_nla->am_value(t.id())); m_nla->am().set(r, m_nla->am_value(t));
else { else {
m_todo_terms.push_back({t, rational::one()}); m_todo_terms.push_back({t, rational::one()});
TRACE("nl_value", tout << "v" << v << " " << t.to_string() << "\n";); TRACE("nl_value", tout << "v" << v << " " << t << "\n";);
TRACE("nl_value", tout << "v" << v << " := w" << t.to_string() << "\n"; TRACE("nl_value", tout << "v" << v << " := w" << t << "\n";
lp().print_term(lp().get_term(t), tout) << "\n";); lp().print_term(lp().get_term(t), tout) << "\n";);
m_nla->am().set(r, 0); m_nla->am().set(r, 0);
@ -3336,14 +3330,14 @@ public:
m_nla->am().set(r1, c1.to_mpq()); m_nla->am().set(r1, c1.to_mpq());
m_nla->am().add(r, r1, r); m_nla->am().add(r, r1, r);
for (lp::lar_term::ival arg : term) { for (lp::lar_term::ival arg : term) {
auto wi = lp().column2tv(arg.column()); auto wi = arg.j();
c1 = arg.coeff() * wcoeff; c1 = arg.coeff() * wcoeff;
if (wi.is_term()) { if (lp().column_has_term(wi)) {
m_todo_terms.push_back({wi, c1}); m_todo_terms.push_back({wi, c1});
} }
else { else {
m_nla->am().set(r1, c1.to_mpq()); m_nla->am().set(r1, c1.to_mpq());
m_nla->am().mul(m_nla->am_value(wi.id()), r1, r1); m_nla->am().mul(m_nla->am_value(wi), r1, r1);
m_nla->am().add(r1, r, r); m_nla->am().add(r1, r, r);
} }
} }
@ -3619,17 +3613,17 @@ public:
TRACE("arith", lp().print_term(term, tout) << "\n";); TRACE("arith", lp().print_term(term, tout) << "\n";);
for (lp::lar_term::ival ti : term) { for (lp::lar_term::ival ti : term) {
theory_var w; theory_var w;
auto tv = lp().column2tv(ti.column()); auto tv = ti.j();
if (tv.is_term()) { if (lp().column_has_term(tv)) {
lp::lar_term const& term1 = lp().get_term(tv); lp::lar_term const& term1 = lp().get_term(tv);
rational coeff2 = coeff * ti.coeff(); rational coeff2 = coeff * ti.coeff();
term2coeffs(term1, coeffs, coeff2); term2coeffs(term1, coeffs, coeff2);
continue; continue;
} }
else { else {
w = lp().local_to_external(tv.id()); w = lp().local_to_external(tv);
SASSERT(w >= 0); SASSERT(w >= 0);
TRACE("arith", tout << (tv.id()) << ": " << w << "\n";); TRACE("arith", tout << tv << ": " << w << "\n";);
} }
rational c0(0); rational c0(0);
coeffs.find(w, c0); coeffs.find(w, c0);
@ -3686,9 +3680,9 @@ public:
} }
app_ref mk_obj(theory_var v) { app_ref mk_obj(theory_var v) {
auto t = get_tv(v); auto t = get_lpvar(v);
bool is_int = a.is_int(get_enode(v)->get_expr()); bool is_int = a.is_int(get_enode(v)->get_expr());
if (t.is_term()) { if (lp().column_has_term(t)) {
return mk_term(lp().get_term(t), is_int); return mk_term(lp().get_term(t), is_int);
} }
else { else {
@ -3744,11 +3738,10 @@ public:
} }
unsigned nv = th.get_num_vars(); unsigned nv = th.get_num_vars();
for (unsigned v = 0; v < nv; ++v) { for (unsigned v = 0; v < nv; ++v) {
auto t = get_tv(v); auto vi = get_lpvar(v);
auto vi = lp().external_to_column_index(v);
if (!ctx().is_relevant(get_enode(v))) out << "irr: "; if (!ctx().is_relevant(get_enode(v))) out << "irr: ";
out << "v" << v << " "; out << "v" << v << " ";
if (t.is_null()) out << "null"; else out << (t.is_term() ? "t":"j") << vi; if (vi == lp::null_lpvar) out << "null"; else out << (lp().column_has_term(vi) ? "t":"j") << vi;
if (use_nra_model() && is_registered_var(v)) m_nla->am().display(out << " = ", nl_value(v, m_nla->tmp1())); if (use_nra_model() && is_registered_var(v)) m_nla->am().display(out << " = ", nl_value(v, m_nla->tmp1()));
else if (can_get_value(v)) out << " = " << get_value(v); else if (can_get_value(v)) out << " = " << get_value(v);
if (is_int(v)) out << ", int"; if (is_int(v)) out << ", int";

View file

@ -189,7 +189,7 @@ struct gomory_test {
void print_term(lar_term & t, std::ostream & out) { void print_term(lar_term & t, std::ostream & out) {
vector<std::pair<mpq, unsigned>> row; vector<std::pair<mpq, unsigned>> row;
for (auto p : t) for (auto p : t)
row.push_back(std::make_pair(p.coeff(), p.column().index())); row.push_back(std::make_pair(p.coeff(), p.j()));
print_row(out, row); print_row(out, row);
} }

View file

@ -786,25 +786,25 @@ void test_term() {
lar_solver solver; lar_solver solver;
unsigned _x = 0; unsigned _x = 0;
unsigned _y = 1; unsigned _y = 1;
var_index x = solver.add_named_var(_x, true, "x"); lpvar x = solver.add_named_var(_x, true, "x");
var_index y = solver.add_named_var(_y, true, "y"); lpvar y = solver.add_named_var(_y, true, "y");
enable_trace("lar_solver"); enable_trace("lar_solver");
enable_trace("cube"); enable_trace("cube");
vector<std::pair<mpq, var_index>> pairs; vector<std::pair<mpq, lpvar>> pairs;
pairs.push_back(std::pair<mpq, var_index>(mpq(2), x)); pairs.push_back(std::pair<mpq, lpvar>(mpq(2), x));
pairs.push_back(std::pair<mpq, var_index>(mpq(1), y)); pairs.push_back(std::pair<mpq, lpvar>(mpq(1), y));
int ti = 0; int ti = 0;
unsigned x_plus_y = solver.add_term(pairs, ti++); unsigned x_plus_y = solver.add_term(pairs, ti++);
solver.add_var_bound(x_plus_y, lconstraint_kind::GE, mpq(5, 3)); solver.add_var_bound(x_plus_y, lconstraint_kind::GE, mpq(5, 3));
solver.add_var_bound(x_plus_y, lconstraint_kind::LE, mpq(14, 3)); solver.add_var_bound(x_plus_y, lconstraint_kind::LE, mpq(14, 3));
pairs.pop_back(); pairs.pop_back();
pairs.push_back(std::pair<mpq, var_index>(mpq(-1), y)); pairs.push_back(std::pair<mpq, lpvar>(mpq(-1), y));
unsigned x_minus_y = solver.add_term(pairs, ti++); unsigned x_minus_y = solver.add_term(pairs, ti++);
solver.add_var_bound(x_minus_y, lconstraint_kind::GE, mpq(5, 3)); solver.add_var_bound(x_minus_y, lconstraint_kind::GE, mpq(5, 3));
solver.add_var_bound(x_minus_y, lconstraint_kind::LE, mpq(14, 3)); solver.add_var_bound(x_minus_y, lconstraint_kind::LE, mpq(14, 3));
auto status = solver.solve(); auto status = solver.solve();
std::cout << lp_status_to_string(status) << std::endl; std::cout << lp_status_to_string(status) << std::endl;
std::unordered_map<var_index, mpq> model; std::unordered_map<lpvar, mpq> model;
if (status != lp_status::OPTIMAL) { if (status != lp_status::OPTIMAL) {
std::cout << "non optimal" << std::endl; std::cout << "non optimal" << std::endl;
return; return;
@ -834,24 +834,24 @@ void test_term() {
void test_evidence_for_total_inf_simple(argument_parser &args_parser) { void test_evidence_for_total_inf_simple(argument_parser &args_parser) {
lar_solver solver; lar_solver solver;
var_index x = solver.add_var(0, false); lpvar x = solver.add_var(0, false);
var_index y = solver.add_var(1, false); lpvar y = solver.add_var(1, false);
solver.add_var_bound(x, LE, mpq(-1)); solver.add_var_bound(x, LE, mpq(-1));
solver.add_var_bound(y, GE, mpq(0)); solver.add_var_bound(y, GE, mpq(0));
vector<std::pair<mpq, var_index>> ls; vector<std::pair<mpq, lpvar>> ls;
ls.push_back(std::pair<mpq, var_index>(mpq(1), x)); ls.push_back(std::pair<mpq, lpvar>(mpq(1), x));
ls.push_back(std::pair<mpq, var_index>(mpq(1), y)); ls.push_back(std::pair<mpq, lpvar>(mpq(1), y));
unsigned j = solver.add_term(ls, 1); unsigned j = solver.add_term(ls, 1);
solver.add_var_bound(j, GE, mpq(1)); solver.add_var_bound(j, GE, mpq(1));
ls.pop_back(); ls.pop_back();
ls.push_back(std::pair<mpq, var_index>(-mpq(1), y)); ls.push_back(std::pair<mpq, lpvar>(-mpq(1), y));
j = solver.add_term(ls, 2); j = solver.add_term(ls, 2);
solver.add_var_bound(j, GE, mpq(0)); solver.add_var_bound(j, GE, mpq(0));
auto status = solver.solve(); auto status = solver.solve();
std::cout << lp_status_to_string(status) << std::endl; std::cout << lp_status_to_string(status) << std::endl;
std::unordered_map<var_index, mpq> model; std::unordered_map<lpvar, mpq> model;
lp_assert(solver.get_status() == lp_status::INFEASIBLE); lp_assert(solver.get_status() == lp_status::INFEASIBLE);
} }
void test_bound_propagation_one_small_sample1() { void test_bound_propagation_one_small_sample1() {
@ -873,20 +873,20 @@ void test_bound_propagation_one_small_sample1() {
unsigned a = ls.add_var(0, false); unsigned a = ls.add_var(0, false);
unsigned b = ls.add_var(1, false); unsigned b = ls.add_var(1, false);
unsigned c = ls.add_var(2, false); unsigned c = ls.add_var(2, false);
vector<std::pair<mpq, var_index>> coeffs; vector<std::pair<mpq, lpvar>> coeffs;
coeffs.push_back(std::pair<mpq, var_index>(mpq(1), a)); coeffs.push_back(std::pair<mpq, lpvar>(mpq(1), a));
coeffs.push_back(std::pair<mpq, var_index>(mpq(-1), c)); coeffs.push_back(std::pair<mpq, lpvar>(mpq(-1), c));
ls.add_term(coeffs, -1); ls.add_term(coeffs, -1);
coeffs.pop_back(); coeffs.pop_back();
coeffs.push_back(std::pair<mpq, var_index>(mpq(-1), b)); coeffs.push_back(std::pair<mpq, lpvar>(mpq(-1), b));
ls.add_term(coeffs, -1); ls.add_term(coeffs, -1);
coeffs.clear(); coeffs.clear();
coeffs.push_back(std::pair<mpq, var_index>(mpq(1), a)); coeffs.push_back(std::pair<mpq, lpvar>(mpq(1), a));
coeffs.push_back(std::pair<mpq, var_index>(mpq(-1), b)); coeffs.push_back(std::pair<mpq, lpvar>(mpq(-1), b));
// ls.add_constraint(coeffs, LE, zero_of_type<mpq>()); // ls.add_constraint(coeffs, LE, zero_of_type<mpq>());
// coeffs.clear(); // coeffs.clear();
// coeffs.push_back(std::pair<mpq, var_index>(mpq(1), b)); // coeffs.push_back(std::pair<mpq, lpvar>(mpq(1), b));
// coeffs.push_back(std::pair<mpq, var_index>(mpq(-1), c)); // coeffs.push_back(std::pair<mpq, lpvar>(mpq(-1), c));
// ls.add_constraint(coeffs, LE, zero_of_type<mpq>()); // ls.add_constraint(coeffs, LE, zero_of_type<mpq>());
// vector<implied_bound> ev; // vector<implied_bound> ev;
// ls.add_var_bound(a, LE, mpq(1)); // ls.add_var_bound(a, LE, mpq(1));
@ -942,9 +942,9 @@ void test_bound_propagation_one_row() {
lar_solver ls; lar_solver ls;
unsigned x0 = ls.add_var(0, false); unsigned x0 = ls.add_var(0, false);
unsigned x1 = ls.add_var(1, false); unsigned x1 = ls.add_var(1, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x0)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x0));
c.push_back(std::pair<mpq, var_index>(mpq(-1), x1)); c.push_back(std::pair<mpq, lpvar>(mpq(-1), x1));
// todo : restore test // todo : restore test
// ls.add_constraint(c, EQ, one_of_type<mpq>()); // ls.add_constraint(c, EQ, one_of_type<mpq>());
// vector<implied_bound> ev; // vector<implied_bound> ev;
@ -957,9 +957,9 @@ void test_bound_propagation_one_row_with_bounded_vars() {
lar_solver ls; lar_solver ls;
unsigned x0 = ls.add_var(0, false); unsigned x0 = ls.add_var(0, false);
unsigned x1 = ls.add_var(1, false); unsigned x1 = ls.add_var(1, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x0)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x0));
c.push_back(std::pair<mpq, var_index>(mpq(-1), x1)); c.push_back(std::pair<mpq, lpvar>(mpq(-1), x1));
// todo: restore test // todo: restore test
// ls.add_constraint(c, EQ, one_of_type<mpq>()); // ls.add_constraint(c, EQ, one_of_type<mpq>());
// vector<implied_bound> ev; // vector<implied_bound> ev;
@ -974,9 +974,9 @@ void test_bound_propagation_one_row_mixed() {
lar_solver ls; lar_solver ls;
unsigned x0 = ls.add_var(0, false); unsigned x0 = ls.add_var(0, false);
unsigned x1 = ls.add_var(1, false); unsigned x1 = ls.add_var(1, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x0)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x0));
c.push_back(std::pair<mpq, var_index>(mpq(-1), x1)); c.push_back(std::pair<mpq, lpvar>(mpq(-1), x1));
// todo: restore test // todo: restore test
// ls.add_constraint(c, EQ, one_of_type<mpq>()); // ls.add_constraint(c, EQ, one_of_type<mpq>());
// vector<implied_bound> ev; // vector<implied_bound> ev;
@ -991,16 +991,16 @@ void test_bound_propagation_two_rows() {
unsigned x = ls.add_var(0, false); unsigned x = ls.add_var(0, false);
unsigned y = ls.add_var(1, false); unsigned y = ls.add_var(1, false);
unsigned z = ls.add_var(2, false); unsigned z = ls.add_var(2, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x));
c.push_back(std::pair<mpq, var_index>(mpq(2), y)); c.push_back(std::pair<mpq, lpvar>(mpq(2), y));
c.push_back(std::pair<mpq, var_index>(mpq(3), z)); c.push_back(std::pair<mpq, lpvar>(mpq(3), z));
// todo: restore test // todo: restore test
// ls.add_constraint(c, GE, one_of_type<mpq>()); // ls.add_constraint(c, GE, one_of_type<mpq>());
// c.clear(); // c.clear();
// c.push_back(std::pair<mpq, var_index>(mpq(3), x)); // c.push_back(std::pair<mpq, lpvar>(mpq(3), x));
// c.push_back(std::pair<mpq, var_index>(mpq(2), y)); // c.push_back(std::pair<mpq, lpvar>(mpq(2), y));
// c.push_back(std::pair<mpq, var_index>(mpq(y), z)); // c.push_back(std::pair<mpq, lpvar>(mpq(y), z));
// ls.add_constraint(c, GE, one_of_type<mpq>()); // ls.add_constraint(c, GE, one_of_type<mpq>());
// ls.add_var_bound(x, LE, mpq(2)); // ls.add_var_bound(x, LE, mpq(2));
// vector<implied_bound> ev; // vector<implied_bound> ev;
@ -1016,10 +1016,10 @@ void test_total_case_u() {
unsigned x = ls.add_var(0, false); unsigned x = ls.add_var(0, false);
unsigned y = ls.add_var(1, false); unsigned y = ls.add_var(1, false);
unsigned z = ls.add_var(2, false); unsigned z = ls.add_var(2, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x));
c.push_back(std::pair<mpq, var_index>(mpq(2), y)); c.push_back(std::pair<mpq, lpvar>(mpq(2), y));
c.push_back(std::pair<mpq, var_index>(mpq(3), z)); c.push_back(std::pair<mpq, lpvar>(mpq(3), z));
// todo: restore test // todo: restore test
// ls.add_constraint(c, LE, one_of_type<mpq>()); // ls.add_constraint(c, LE, one_of_type<mpq>());
// ls.add_var_bound(x, GE, zero_of_type<mpq>()); // ls.add_var_bound(x, GE, zero_of_type<mpq>());
@ -1044,10 +1044,10 @@ void test_total_case_l() {
unsigned x = ls.add_var(0, false); unsigned x = ls.add_var(0, false);
unsigned y = ls.add_var(1, false); unsigned y = ls.add_var(1, false);
unsigned z = ls.add_var(2, false); unsigned z = ls.add_var(2, false);
vector<std::pair<mpq, var_index>> c; vector<std::pair<mpq, lpvar>> c;
c.push_back(std::pair<mpq, var_index>(mpq(1), x)); c.push_back(std::pair<mpq, lpvar>(mpq(1), x));
c.push_back(std::pair<mpq, var_index>(mpq(2), y)); c.push_back(std::pair<mpq, lpvar>(mpq(2), y));
c.push_back(std::pair<mpq, var_index>(mpq(3), z)); c.push_back(std::pair<mpq, lpvar>(mpq(3), z));
// todo: restore test // todo: restore test
// ls.add_constraint(c, GE, one_of_type<mpq>()); // ls.add_constraint(c, GE, one_of_type<mpq>());
// ls.add_var_bound(x, LE, one_of_type<mpq>()); // ls.add_var_bound(x, LE, one_of_type<mpq>());
@ -1611,15 +1611,15 @@ void test_maximize_term() {
int_solver i_solver(solver); // have to create it too int_solver i_solver(solver); // have to create it too
unsigned _x = 0; unsigned _x = 0;
unsigned _y = 1; unsigned _y = 1;
var_index x = solver.add_var(_x, false); lpvar x = solver.add_var(_x, false);
var_index y = solver.add_var(_y, true); lpvar y = solver.add_var(_y, true);
vector<std::pair<mpq, var_index>> term_ls; vector<std::pair<mpq, lpvar>> term_ls;
term_ls.push_back(std::pair<mpq, var_index>(mpq(1), x)); term_ls.push_back(std::pair<mpq, lpvar>(mpq(1), x));
term_ls.push_back(std::pair<mpq, var_index>(mpq(-1), y)); term_ls.push_back(std::pair<mpq, lpvar>(mpq(-1), y));
unsigned term_x_min_y = solver.add_term(term_ls, -1); unsigned term_x_min_y = solver.add_term(term_ls, -1);
term_ls.clear(); term_ls.clear();
term_ls.push_back(std::pair<mpq, var_index>(mpq(2), x)); term_ls.push_back(std::pair<mpq, lpvar>(mpq(2), x));
term_ls.push_back(std::pair<mpq, var_index>(mpq(2), y)); term_ls.push_back(std::pair<mpq, lpvar>(mpq(2), y));
unsigned term_2x_pl_2y = solver.add_term(term_ls, -1); unsigned term_2x_pl_2y = solver.add_term(term_ls, -1);
solver.add_var_bound(term_x_min_y, LE, zero_of_type<mpq>()); solver.add_var_bound(term_x_min_y, LE, zero_of_type<mpq>());
@ -1627,7 +1627,7 @@ void test_maximize_term() {
solver.find_feasible_solution(); solver.find_feasible_solution();
lp_assert(solver.get_status() == lp_status::OPTIMAL); lp_assert(solver.get_status() == lp_status::OPTIMAL);
std::cout << solver.constraints(); std::cout << solver.constraints();
std::unordered_map<var_index, mpq> model; std::unordered_map<lpvar, mpq> model;
solver.get_model(model); solver.get_model(model);
for (auto p : model) { for (auto p : model) {
std::cout << "v[" << p.first << "] = " << p.second << std::endl; std::cout << "v[" << p.first << "] = " << p.second << std::endl;

View file

@ -28,7 +28,7 @@ Revision History:
#include <fstream> #include <fstream>
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
#include "math/lp/ul_pair.h" #include "math/lp/column.h"
#include "math/lp/lar_constraints.h" #include "math/lp/lar_constraints.h"
#include <sstream> #include <sstream>
#include <cstdlib> #include <cstdlib>
@ -383,7 +383,7 @@ namespace lp {
} }
void add_constraint_to_solver(lar_solver * solver, formula_constraint & fc, unsigned i) { void add_constraint_to_solver(lar_solver * solver, formula_constraint & fc, unsigned i) {
vector<std::pair<mpq, var_index>> ls; vector<std::pair<mpq, lpvar>> ls;
for (auto & it : fc.m_coeffs) { for (auto & it : fc.m_coeffs) {
ls.push_back(std::make_pair(it.first, solver->add_var(register_name(it.second), false))); ls.push_back(std::make_pair(it.first, solver->add_var(register_name(it.second), false)));
} }