3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-14 21:08:46 +00:00

extract gomory cut functionality in one method

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

work on hnf

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

work in hnf

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

work in hnf

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

work in hnf

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

work in hnf

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

work on hnf

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

work on hnf

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

prepare calculate U in hnf

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

naive algorithm for HNF and m <= n

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

naive algorithm for HNF

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

introduces reverse matrix into Hermite Normal Form calculation

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

work on more efficient hnf

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

work on hnf

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

use smarter templates in lu.h

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

the new lu scheme compiles

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

simple test passes with the modified lu

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

fix the build on windows

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

playing with the example from cutting the mix

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

work on hnf, add extended_gcd_minimal_uv()

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

work on extended_gcd_minimal_uv

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

work on hnf, add extended_gcd_minimal_uv()

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

more tests and bug fixes in hnf

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

work on hnf modulo version

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

work on hnf modulo version, more tests pass

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

a rough version of hnf passed the tests

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

fix build in release

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

fixes in determinant calculations

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

work on hnf

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

work on hnf

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

work on hnf

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

work on hnf

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

create a stub for hnf_cuts

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

create a stub for hnf_cuts

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

create a stub for hnf_cuts

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

general_matrix etc.

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

general_matrix etc.

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

rename cut_solver to chase_cut_solver

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

rename cut_solver to chase_cut_solver

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

hnf_cutter

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2018-04-20 11:24:20 -07:00
parent c04bcb411d
commit 3b5337823a
35 changed files with 2178 additions and 760 deletions

View file

@ -308,7 +308,7 @@ class theory_lra::imp {
m_solver->set_track_pivoted_rows(lp.bprop_on_pivoted_rows());
m_solver->settings().m_int_gomory_cut_period = ctx().get_fparams().m_arith_branch_cut_ratio;
m_solver->settings().m_int_cuts_etc_period = ctx().get_fparams().m_arith_branch_cut_ratio;
m_solver->settings().m_int_cut_solver_period = std::max(8u, ctx().get_fparams().m_arith_branch_cut_ratio);
m_solver->settings().m_int_chase_cut_solver_period = std::max(8u, ctx().get_fparams().m_arith_branch_cut_ratio);
m_solver->settings().m_int_run_gcd_test = ctx().get_fparams().m_arith_gcd_test;
m_solver->settings().set_random_seed(ctx().get_fparams().m_random_seed);
@ -2812,10 +2812,10 @@ public:
st.update("arith-make-feasible", m_solver->settings().st().m_make_feasible);
st.update("arith-max-columns", m_solver->settings().st().m_max_cols);
st.update("arith-max-rows", m_solver->settings().st().m_max_rows);
st.update("cut-solver-calls", m_solver->settings().st().m_cut_solver_calls);
st.update("cut-solver-true", m_solver->settings().st().m_cut_solver_true);
st.update("cut-solver-false", m_solver->settings().st().m_cut_solver_false);
st.update("cut-solver-undef", m_solver->settings().st().m_cut_solver_undef);
st.update("cut-solver-calls", m_solver->settings().st().m_chase_cut_solver_calls);
st.update("cut-solver-true", m_solver->settings().st().m_chase_cut_solver_true);
st.update("cut-solver-false", m_solver->settings().st().m_chase_cut_solver_false);
st.update("cut-solver-undef", m_solver->settings().st().m_chase_cut_solver_undef);
st.update("gcd-calls", m_solver->settings().st().m_gcd_calls);
st.update("gcd-conflict", m_solver->settings().st().m_gcd_conflicts);
st.update("cube-calls", m_solver->settings().st().m_cube_calls);

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ z3_add_component(lp
binary_heap_priority_queue.cpp
binary_heap_upair_queue.cpp
bound_propagator.cpp
cut_solver.cpp
chase_cut_solver.cpp
core_solver_pretty_printer.cpp
dense_matrix.cpp
eta_matrix.cpp
@ -25,7 +25,7 @@ z3_add_component(lp
permutation_matrix.cpp
row_eta_matrix.cpp
scaler.cpp
sparse_matrix.cpp
square_sparse_matrix.cpp
square_dense_submatrix.cpp
static_matrix.cpp
random_updater.cpp

View file

@ -2,7 +2,7 @@
Copyright (c) 2017 Microsoft Corporation
Author: Nikolaj Bjorner, Lev Nachmanson
*/
#include "util/lp/cut_solver.h"
#include "util/lp/chase_cut_solver.h"
namespace lp {
mpq polynomial::m_local_zero = zero_of_type<mpq>();

View file

@ -35,24 +35,24 @@
#include "util/lp/indexer_of_constraints.h"
#include "util/lp/lar_term.h"
namespace lp {
class cut_solver; //forward definition
class chase_cut_solver; //forward definition
struct pp_poly {
cut_solver const& s;
chase_cut_solver const& s;
polynomial const& p;
pp_poly(cut_solver const& s, polynomial const& p): s(s), p(p) {}
pp_poly(chase_cut_solver const& s, polynomial const& p): s(s), p(p) {}
};
struct pp_constraint {
cut_solver const& s;
chase_cut_solver const& s;
constraint const& c;
pp_constraint(cut_solver const& s, constraint const& c): s(s), c(c) {}
pp_constraint(chase_cut_solver const& s, constraint const& c): s(s), c(c) {}
};
std::ostream& operator<<(std::ostream& out, pp_poly const& p);
std::ostream& operator<<(std::ostream& out, pp_constraint const& p);
class cut_solver : public column_namer {
class chase_cut_solver : public column_namer {
public:
enum class lbool { l_false, l_true, l_undef };
inline std::string lbool_to_string(lbool l) {
@ -356,7 +356,7 @@ public:
}
~cut_solver() {
~chase_cut_solver() {
for (constraint * c : m_asserts)
delete c;
for (constraint * c : m_lemmas_container.m_lemmas)
@ -386,7 +386,7 @@ public:
unsigned m_bounded_search_calls;
unsigned m_number_of_conflicts;
vector<scope> m_scopes;
std::unordered_map<unsigned, unsigned> m_user_vars_to_cut_solver_vars;
std::unordered_map<unsigned, unsigned> m_user_vars_to_chase_cut_solver_vars;
std::unordered_set<constraint_index> m_explanation; // if this collection is not empty we have a conflict
// the number of decisions in the current trail
unsigned m_decision_level;
@ -846,7 +846,7 @@ public:
}
bool too_many_propagations_for_var(const var_info& vi) const {
return vi.number_of_bound_propagations() > m_settings.m_cut_solver_cycle_on_var * vi.number_of_asserts();
return vi.number_of_bound_propagations() > m_settings.m_chase_cut_solver_cycle_on_var * vi.number_of_asserts();
}
bool new_upper_bound_is_relevant(unsigned j, const mpq & v) const {
@ -1591,7 +1591,7 @@ public:
unsigned find_unused_index() const {
for (unsigned j = m_var_infos.size(); ; j++)
if (m_user_vars_to_cut_solver_vars.find(j) == m_user_vars_to_cut_solver_vars.end())
if (m_user_vars_to_chase_cut_solver_vars.find(j) == m_user_vars_to_chase_cut_solver_vars.end())
return j;
}
@ -1715,7 +1715,7 @@ public:
m_cancelled = true;
return true;
}
unsigned bound = m_asserts.size() * 200 / (1 + m_settings.m_int_cut_solver_period);
unsigned bound = m_asserts.size() * 200 / (1 + m_settings.m_int_chase_cut_solver_period);
if (m_trail.size() > bound || m_number_of_conflicts > bound) {
m_cancelled = true;
return true;
@ -1745,7 +1745,7 @@ public:
if (c != nullptr) {
m_number_of_conflicts++;
TRACE("propagate_and_backjump_step_int", tout << "incostistent_constraint "; trace_print_constraint(tout, c); tout << "m_number_of_conflicts = " << m_number_of_conflicts << std::endl; tout << "cut_solver_calls " << m_settings.st().m_cut_solver_calls << std::endl;);
TRACE("propagate_and_backjump_step_int", tout << "incostistent_constraint "; trace_print_constraint(tout, c); tout << "m_number_of_conflicts = " << m_number_of_conflicts << std::endl; tout << "chase_cut_solver_calls " << m_settings.st().m_chase_cut_solver_calls << std::endl;);
if (at_base_lvl()) {
fill_conflict_explanation(c);
return lbool::l_false;
@ -2223,7 +2223,7 @@ public:
public:
void pop() { pop(1); }
cut_solver(std::function<std::string (unsigned)> var_name_function,
chase_cut_solver(std::function<std::string (unsigned)> var_name_function,
std::function<void (unsigned, std::ostream &)> print_constraint_function,
std::function<unsigned ()> number_of_variables_function,
std::function<const impq &(unsigned)> var_value_function,
@ -2343,7 +2343,7 @@ public:
bool consistent(const_constr * i) const {
// an option could be to check that upper(i.poly()) <= 0
bool ret = value(i->poly()) <= zero_of_type<mpq>();
CTRACE("cut_solver_state_inconsistent", !ret,
CTRACE("chase_cut_solver_state_inconsistent", !ret,
tout << "inconsistent constraint " << pp_constraint(*this, *i) << "\n";
tout << "value = " << value(i->poly()) << '\n';);
return ret;
@ -2517,7 +2517,7 @@ public:
constraint *c = short_lemmas[m_settings.random_next() % n];
k = - c->poly().m_a;
copy_poly_coeffs_to_term(c->poly(), t);
TRACE("cut_solver_cuts", trace_print_constraint(tout, *c););
TRACE("chase_cut_solver_cuts", trace_print_constraint(tout, *c););
return true;
}
};

View file

@ -0,0 +1,195 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
namespace lp {
class general_matrix {
// fields
permutation_matrix<mpq, mpq> m_row_permutation;
permutation_matrix<mpq, mpq> m_column_permutation;
vector<vector<mpq>> m_data;
public:
unsigned adjust_row(unsigned row) const{
return m_row_permutation[row];
}
void push_row(vector<mpq> & v) {
m_data.push_back(v);
m_row_permutation.resize(m_data.size());
m_column_permutation.resize(v.size());
}
unsigned adjust_column(unsigned col) const{
return m_column_permutation.apply_reverse(col);
}
unsigned adjust_row_inverse(unsigned row) const{
return m_row_permutation.apply_reverse(row);
}
unsigned adjust_column_inverse(unsigned col) const{
return m_column_permutation[col];
}
unsigned row_count() const { return m_data.size(); }
unsigned column_count() const { return m_data[0].size(); }
class ref_row {
general_matrix& m_matrix;
vector<mpq>& m_row_data;
public:
ref_row(general_matrix& m, vector<mpq>& row_data) : m_matrix(m), m_row_data(row_data) {}
mpq & operator[](unsigned col) { return m_row_data[m_matrix.adjust_column(col)]; }
};
class ref_row_const {
const general_matrix& m_matrix;
const vector<mpq>& m_row_data;
public:
ref_row_const(const general_matrix& m, const vector<mpq>& row_data) : m_matrix(m), m_row_data(row_data) {}
const mpq& operator[](unsigned col) const { return m_row_data[m_matrix.adjust_column(col)]; }
};
ref_row operator[](unsigned i) { return ref_row(*this, m_data[adjust_row(i)]); }
ref_row_const operator[](unsigned i) const { return ref_row_const(*this, m_data[adjust_row(i)]); }
void print(std::ostream & out, unsigned blanks = 0) const {
print_matrix<mpq>(m_data, out, blanks);
}
void clear() { m_data.clear(); }
void print_submatrix(std::ostream & out, unsigned k, unsigned blanks = 0) const {
general_matrix m(row_count() - k, column_count() - k);
for (unsigned i = k; i < row_count(); i++) {
for (unsigned j = k; j < column_count(); j++)
m[i-k][j-k] = (*this)[i][j];
}
print_matrix<mpq>(m.m_data, out, blanks);
}
void copy_column_to_indexed_vector(unsigned entering, indexed_vector<mpq> &w ) const {
lp_assert(false); //
}
general_matrix operator*(const general_matrix & m) const {
lp_assert(m.row_count() == column_count());
general_matrix ret(row_count(), m.column_count());
for (unsigned i = 0; i < row_count(); i ++) {
for (unsigned j = 0; j < m.column_count(); j++) {
mpq a(0);
for (unsigned k = 0; k < column_count(); k++)
a += ((*this)[i][k])*m[k][j];
ret[i][j] = a;
}
}
return ret;
}
bool elements_are_equal(const general_matrix& m) const {
for (unsigned i = 0; i < row_count(); i++)
for (unsigned j = 0; j < column_count(); j++)
if ( (*this)[i][j] != m[i][j])
return false;
return true;
}
bool elements_are_equal_modulo(const general_matrix& m, const mpq & d) const {
for (unsigned i = 0; i < row_count(); i++)
for (unsigned j = 0; j < column_count(); j++)
if (!is_zero(((*this)[i][j] - m[i][j]) % d))
return false;
return true;
}
bool operator==(const general_matrix& m) const {
return row_count() == m.row_count() && column_count() == m.column_count() && elements_are_equal(m);
}
bool operator!=(const general_matrix& m) const {
return !(*this == m);
}
bool equal_modulo(const general_matrix& m, const mpq & d) const {
return row_count() == m.row_count() && column_count() == m.column_count() && elements_are_equal_modulo(m, d);
}
vector<mpq> operator*(const vector<mpq> & x) const {
vector<mpq> r;
lp_assert(x.size() == column_count());
for (unsigned i = 0; i < row_count(); i++) {
mpq v(0);
for (unsigned j = 0; j < column_count(); j++) {
v += (*this)[i][j] * x[j];
}
r.push_back(v);
}
return r;
}
// bool create_upper_triangle(general_matrix& m, vector<mpq>& x) {
// for (unsigned i = 1; i < m.row_count(); i++) {
// lp_assert(false); // to be continued
// }
// }
// bool solve_A_x_equal_b(const general_matrix& m, vector<mpq>& x, const vector<mpq>& b) const {
// auto m_copy = m;
// // for square matrices
// lp_assert(row_count() == b.size());
// lp_assert(x.size() == column_count());
// lp_assert(row_count() == column_count());
// x = b;
// create_upper_triangle(copy_of_m, x);
// solve_on_triangle(copy_of_m, x);
// }
//
void transpose_rows(unsigned i, unsigned l) {
lp_assert(i != l);
m_row_permutation.transpose_from_right(i, l);
}
void transpose_columns(unsigned j, unsigned k) {
lp_assert(j != k);
m_column_permutation.transpose_from_left(j, k);
}
general_matrix(){}
general_matrix(unsigned n) :
m_row_permutation(n),
m_column_permutation(n),
m_data(n)
{
for (auto& v : m_data){
v.resize(n);
}
}
general_matrix(unsigned m, unsigned n) :
m_row_permutation(m),
m_column_permutation(n),
m_data(m) {
for (auto& v : m_data){
v.resize(n);
}
}
};
}

634
src/util/lp/hnf.h Normal file
View file

@ -0,0 +1,634 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Creates the Hermite Normal Form of a matrix in place.
We suppose that $A$ is an integral $m$ by $n$ matrix or rank $m$, where $n >= m$.
The paragraph below is applicable to the usage of HNF.
We have $H = AU$ where $H$ is in Hermite Normal Form
and $U$ is a unimodular matrix. We do not have an explicit
representation of $U$. For a given $i$ we need to find the $i$-th
row of $U^{-1}$.
Let $e_i$ be a vector of length $m$ with all elements equal to $0$ and
$1$ at $i$-th position. Then we need to find the row vector $e_iU^{-1}=t$. Noticing that $U^{-1} = H^{-1}A$, we have $e_iH^{-1}A=t$.
We find $e_iH^{-1} = f$ by solving $e_i = fH$ and then $fA$ gives us $t$.
Author:
Nikolaj Bjorner (nbjorner)
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include "util/lp/numeric_pair.h"
#include "util/ext_gcd.h"
namespace lp {
namespace hnf_calc {
// d = u * a + b * b and the sum of abs(u) + abs(v) is minimal, d is positive
inline
void extended_gcd_minimal_uv(const mpq & a, const mpq & b, mpq & d, mpq & u, mpq & v) {
if (is_zero(a)) {
u = zero_of_type<mpq>();
v = one_of_type<mpq>();
d = b;
return;
}
if (is_zero(b)) {
u = one_of_type<mpq>();
v = zero_of_type<mpq>();
d = a;
return;
}
extended_gcd(a, b, d, u, v);
if (is_neg(d)) {
d = -d;
u = -u;
v = -v;
}
if (d == a) {
u = one_of_type<mpq>();
v = zero_of_type<mpq>();
return;
}
if (d == -a) {
u = - one_of_type<mpq>();
v = zero_of_type<mpq>();
return;
}
mpq a_over_d = abs(a) / d;
mpq r;
mpq k = machine_div_rem(v, a_over_d, r);
if (is_neg(r)) {
r += a_over_d;
k -= one_of_type<mpq>();
}
lp_assert(v == k * a_over_d + r);
if (is_pos(b)) {
v = r - a_over_d; // v -= (k + 1) * a_over_d;
lp_assert(- a_over_d < v && v <= zero_of_type<mpq>());
if (is_pos(a)) {
u += (k + 1) * (b / d);
lp_assert( one_of_type<mpq>() <= u && u <= abs(b)/d);
} else {
u -= (k + 1) * (b / d);
lp_assert( one_of_type<mpq>() <= -u && -u <= abs(b)/d);
}
} else {
v = r; // v -= k * a_over_d;
lp_assert(- a_over_d < -v && -v <= zero_of_type<mpq>());
if (is_pos(a)) {
u += k * (b / d);
lp_assert( one_of_type<mpq>() <= u && u <= abs(b)/d);
} else {
u -= k * (b / d);
lp_assert( one_of_type<mpq>() <= -u && -u <= abs(b)/d);
}
}
lp_assert(d == u * a + v * b);
}
template <typename M> bool prepare_pivot_for_lower_triangle(M &m, unsigned r) {
lp_assert(m.row_count() <= m.column_count());
for (unsigned i = r; i < m.row_count(); i++) {
for (unsigned j = r; j < m.column_count(); j++) {
if (!is_zero(m[i][j])) {
if (i != r) {
m.transpose_rows(i, r);
}
if (j != r) {
m.transpose_columns(j, r);
}
return true;
}
}
}
return false;
}
template <typename M> void pivot_column_non_fractional(M &m, unsigned & r) {
lp_assert(m.row_count() <= m.column_count());
for (unsigned j = r + 1; j < m.column_count(); j++) {
for (unsigned i = r + 1; i < m.row_count(); i++) {
m[i][j] =
(r > 0 )?
(m[r][r]*m[i][j] - m[i][r]*m[r][j]) / m[r-1][r-1] :
(m[r][r]*m[i][j] - m[i][r]*m[r][j]);
lp_assert(is_int(m[i][j]));
}
}
}
// returns the rank of the matrix
template <typename M> unsigned to_lower_triangle_non_fractional(M &m) {
lp_assert(m.row_count() <= m.column_count());
unsigned i = 0;
for (; i < m.row_count() - 1; i++) {
if (!prepare_pivot_for_lower_triangle(m, i)) {
return i;
}
pivot_column_non_fractional(m, i);
}
lp_assert(i == m.row_count() - 1);
// go over the last row and try to find a non-zero in the row to the right of diagonal
for (unsigned j = i; j < m.column_count(); j++) {
if (!is_zero(m[i][j])) {
return m.row_count();
}
}
return i;
}
template <typename M>
mpq gcd_of_row_starting_from_diagonal(const M& m, unsigned i) {
mpq g = zero_of_type<mpq>();
unsigned j = i;
for (; j < m.column_count() && is_zero(j); j++) {
const auto & t = m[i][j];
if (!is_zero(t))
g = t;
}
for (; j < m.column_count(); j++) {
const auto & t = m[i][j];
if (!is_zero(t))
g = gcd(g, t);
}
return g;
}
// it returns "r" - the rank of the matrix and the gcd of r-minors
template <typename M> mpq determinant_of_rectangular_matrix(const M& m, unsigned & r) {
if (m.column_count() < m.row_count())
throw "not implemented"; // consider working with the transposed m, or create a "transposed" version if needed
// The plan is to transform m to the lower triangular form by using non-fractional Gaussian Elimination by columns.
// Then the elements of the following elements of the last non-zero row of the matrix
// m[r-1][r-1], m[r-1][r], ..., m[r-1]m[m.column_count() - 1] give the determinants of all minors of rank r.
// The gcd of these minors is the return value
auto mc = m;
r = to_lower_triangle_non_fractional(mc);
if (r == 0)
return one_of_type<mpq>();
lp_assert(!is_zero(gcd_of_row_starting_from_diagonal(mc, r - 1)));
return gcd_of_row_starting_from_diagonal(mc, r - 1);
}
template <typename M> mpq determinant(const M& m) {
lp_assert(m.row_count() == m.column_count());
auto mc = m;
unsigned r;
mpq d = determinant_of_rectangular_matrix(mc, r);
return r < m.row_count() ? zero_of_type<mpq>() : d;
}
} // end of namespace hnf_calc
template <typename M> // M is the matrix type
class hnf {
// fields
#ifdef Z3DEBUG
M & m_H;
M m_U;
M m_U_reverse;
#endif
M m_A_orig;
M m_W;
vector<mpq> m_buffer;
unsigned m_m;
unsigned m_n;
mpq m_d; // it is a positive number and a multiple of gcd of r-minors of m_A_orig, where r is the rank of m_A_orig
mpq m_r; // the rank of m_A
unsigned m_i;
unsigned m_j;
mpq m_R;
mpq m_half_R;
mpq mod_R_balanced(const mpq & a) const {
mpq t = a % m_R;
return t > m_half_R? t - m_R : (t < - m_half_R? t + m_R : t);
}
mpq mod_R(const mpq & a) const {
mpq t = a % m_R;
t = is_neg(t) ? t + m_R : t;
if(is_neg(t)){
std::cout << "a=" << a << ", m_R= " << m_R << std::endl;
}
return t;
}
#ifdef Z3DEBUG
void buffer_p_col_i_plus_q_col_j_H(const mpq & p, unsigned i, const mpq & q, unsigned j) {
for (unsigned k = i; k < m_m; k++) {
m_buffer[k] = p * m_H[k][i] + q * m_H[k][j];
}
}
#endif
bool zeros_in_column_W_above(unsigned i) {
for (unsigned k = 0; k < i; k++)
if (!is_zero(m_W[k][i]))
return false;
return true;
}
void buffer_p_col_i_plus_q_col_j_W_modulo(const mpq & p, const mpq & q) {
lp_assert(zeros_in_column_W_above(m_i));
for (unsigned k = m_i; k < m_m; k++) {
m_buffer[k] = mod_R_balanced(mod_R_balanced(p * m_W[k][m_i]) + mod_R_balanced(q * m_W[k][m_j]));
}
}
#ifdef Z3DEBUG
void buffer_p_col_i_plus_q_col_j_U(const mpq & p, unsigned i, const mpq & q, unsigned j) {
for (unsigned k = 0; k < m_n; k++) {
m_buffer[k] = p * m_U[k][i] + q * m_U[k][j];
}
}
void pivot_column_i_to_column_j_H(mpq u, unsigned i, mpq v, unsigned j) {
lp_assert(is_zero(u * m_H[i][i] + v * m_H[i][j]));
m_H[i][j] = zero_of_type<mpq>();
for (unsigned k = i + 1; k < m_m; k ++)
m_H[k][j] = u * m_H[k][i] + v * m_H[k][j];
}
#endif
void pivot_column_i_to_column_j_W_modulo(mpq u, mpq v) {
lp_assert(is_zero((u * m_W[m_i][m_i] + v * m_W[m_i][m_j]) % m_R));
m_W[m_i][m_j] = zero_of_type<mpq>();
for (unsigned k = m_i + 1; k < m_m; k ++)
m_W[k][m_j] = mod_R_balanced(mod_R_balanced(u * m_W[k][m_i]) + mod_R_balanced(v * m_W[k][m_j]));
}
#ifdef Z3DEBUG
void pivot_column_i_to_column_j_U(mpq u, unsigned i, mpq v, unsigned j) {
for (unsigned k = 0; k < m_n; k ++)
m_U[k][j] = u * m_U[k][i] + v * m_U[k][j];
}
void copy_buffer_to_col_i_H(unsigned i) {
for (unsigned k = i; k < m_m; k++) {
m_H[k][i] = m_buffer[k];
}
}
void copy_buffer_to_col_i_U(unsigned i) {
for (unsigned k = 0; k < m_n; k++)
m_U[k][i] = m_buffer[k];
}
// multiply by (a, b)
// (c, d)
// from the left where i and j are the modified columns
// the [i][i] = a, and [i][j] = b for the matrix we multiply by
void multiply_U_reverse_from_left_by(unsigned i, unsigned j, const mpq & a, const mpq & b, const mpq & c, const mpq d) {
// the new i-th row goes to the buffer
for (unsigned k = 0; k < m_n; k++) {
m_buffer[k] = a * m_U_reverse[i][k] + b * m_U_reverse[j][k];
}
// calculate the new j-th row in place
for (unsigned k = 0; k < m_n; k++) {
m_U_reverse[j][k] = c * m_U_reverse[i][k] + d * m_U_reverse[j][k];
}
// copy the buffer into i-th row
for (unsigned k = 0; k < m_n; k++) {
m_U_reverse[i][k] = m_buffer[k];
}
}
void handle_column_ij_in_row_i(unsigned i, unsigned j) {
lp_assert(is_correct_modulo());
const mpq& aii = m_H[i][i];
const mpq& aij = m_H[i][j];
mpq p,q,r;
extended_gcd(aii, aij, r, p, q);
mpq aii_over_r = aii / r;
mpq aij_over_r = aij / r;
buffer_p_col_i_plus_q_col_j_H(p, i, q, j);
pivot_column_i_to_column_j_H(- aij_over_r, i, aii_over_r, j);
copy_buffer_to_col_i_H(i);
buffer_p_col_i_plus_q_col_j_U(p, i, q, j);
pivot_column_i_to_column_j_U(- aij_over_r, i, aii_over_r, j);
copy_buffer_to_col_i_U(i);
// U was multiplied from the right by (p, - aij_over_r)
// (q, aii_over_r )
// We need to multiply U_reverse by (aii_over_r, aij_over_r)
// (-q , p)
// from the left
multiply_U_reverse_from_left_by(i, j, aii_over_r, aij_over_r, -q, p);
lp_assert(is_correct_modulo());
}
void switch_sign_for_column(unsigned i) {
for (unsigned k = i; k < m_m; k++)
m_H[k][i].neg();
for (unsigned k = 0; k < m_n; k++)
m_U[k][i].neg();
// switch sign for the i-th row in the reverse m_U_reverse
for (unsigned k = 0; k < m_n; k++)
m_U_reverse[i][k].neg();
}
void process_row_column(unsigned i, unsigned j){
if (is_zero(m_H[i][j]))
return;
handle_column_ij_in_row_i(i, j);
}
void replace_column_j_by_j_minus_u_col_i_H(unsigned i, unsigned j, const mpq & u) {
lp_assert(j < i);
for (unsigned k = i; k < m_m; k++) {
m_H[k][j] -= u * m_H[k][i];
}
}
void replace_column_j_by_j_minus_u_col_i_U(unsigned i, unsigned j, const mpq & u) {
lp_assert(j < i);
for (unsigned k = 0; k < m_n; k++) {
m_U[k][j] -= u * m_U[k][i];
}
// Here we multiply from m_U from the right by the matrix ( 1, 0)
// ( -u, 1).
// To adjust the reverse we multiply it from the left by (1, 0)
// (u, 1)
for (unsigned k = 0; k < m_n; k++) {
m_U_reverse[i][k] += u * m_U_reverse[j][k];
}
}
void work_on_columns_less_than_i_in_the_triangle(unsigned i) {
const mpq & mii = m_H[i][i];
lp_assert(is_pos(mii));
for (unsigned j = 0; j < i; j++) {
const mpq & mij = m_H[i][j];
if (!is_pos(mij) && - mij < mii)
continue;
mpq u = ceil(mij / mii);
replace_column_j_by_j_minus_u_col_i_H(i, j, u);
replace_column_j_by_j_minus_u_col_i_U(i, j, u);
}
}
void process_row(unsigned i) {
lp_assert(is_correct_modulo());
for (unsigned j = i + 1; j < m_n; j++) {
process_row_column(i, j);
}
if (i >= m_n) {
lp_assert(m_H == m_A_orig * m_U);
return;
}
if (is_neg(m_H[i][i]))
switch_sign_for_column(i);
work_on_columns_less_than_i_in_the_triangle(i);
lp_assert(is_correct_modulo());
}
void calculate() {
for (unsigned i = 0; i < m_m; i++) {
process_row(i);
}
}
void prepare_U_and_U_reverse() {
m_U = M(m_H.column_count());
for (unsigned i = 0; i < m_U.column_count(); i++)
m_U[i][i] = 1;
m_U_reverse = m_U;
lp_assert(m_H == m_A_orig * m_U);
}
bool row_is_correct_form(unsigned i) const {
if (i >= m_n)
return true;
const mpq& hii = m_H[i][i];
if (is_neg(hii))
return false;
for (unsigned j = 0; j < i; j++) {
const mpq & hij = m_H[i][j];
if (is_pos(hij))
return false;
if (- hij >= hii)
return false;
}
return true;
}
bool is_correct_form() const {
for (unsigned i = 0; i < m_m; i++)
if (!row_is_correct_form(i))
return false;
return true;
}
bool is_correct() const {
return m_H == m_A_orig * m_U && is_unit_matrix(m_U * m_U_reverse);
}
bool is_correct_modulo() const {
return m_H.equal_modulo(m_A_orig * m_U, m_d) && is_unit_matrix(m_U * m_U_reverse);
}
bool is_correct_final() const {
if (!is_correct()) {
std::cout << "m_H = "; m_H.print(std::cout, 17);
std::cout << "\nm_A_orig * m_U = "; (m_A_orig * m_U).print(std::cout, 17);
std::cout << "is_correct() does not hold" << std::endl;
return false;
}
if (!is_correct_form()) {
std::cout << "is_correct_form() does not hold" << std::endl;
return false;
}
return true;
}
public:
const M& H() const { return m_H;}
const M& U() const { return m_U;}
const M& U_reverse() const { return m_U_reverse; }
private:
#endif
void copy_buffer_to_col_i_W_modulo() {
for (unsigned k = m_i; k < m_m; k++) {
m_W[k][m_i] = m_buffer[k];
}
}
void replace_column_j_by_j_minus_u_col_i_W(unsigned j, const mpq & u) {
lp_assert(j < m_i);
for (unsigned k = m_i; k < m_m; k++) {
m_W[k][j] -= u * m_W[k][m_i];
// m_W[k][j] = mod_R_balanced(m_W[k][j]);
}
}
bool is_unit_matrix(const M& u) const {
unsigned m = u.row_count();
unsigned n = u.column_count();
if (m != n) return false;
for (unsigned i = 0; i < m; i ++)
for (unsigned j = 0; j < n; j++) {
if (i == j) {
if (one_of_type<mpq>() != u[i][j])
return false;
} else {
if (!is_zero(u[i][j]))
return false;
}
}
return true;
}
// follows Algorithm 2.4.8 of Henri Cohen's "A course on computational algebraic number theory",
// with some changes related to that we create a low triangle matrix
// with non-positive elements under the diagonal
void process_column_in_row_modulo() {
mpq& aii = m_W[m_i][m_i];
const mpq& aij = m_W[m_i][m_j];
mpq d, p,q;
hnf_calc::extended_gcd_minimal_uv(aii, aij, d, p, q);
if (is_zero(d))
return;
mpq aii_over_d = aii / d;
mpq aij_over_d = aij / d;
buffer_p_col_i_plus_q_col_j_W_modulo(p, q);
pivot_column_i_to_column_j_W_modulo(- aij_over_d, aii_over_d);
copy_buffer_to_col_i_W_modulo();
}
void endl() const {
std::cout << std::endl;
}
void fix_row_under_diagonal_W_modulo() {
mpq d, u, v;
if (is_zero(m_W[m_i][m_i])) {
m_W[m_i][m_i] = m_R;
u = one_of_type<mpq>();
d = m_R;
} else {
hnf_calc::extended_gcd_minimal_uv(m_W[m_i][m_i], m_R, d, u, v);
}
auto & mii = m_W[m_i][m_i];
mii *= u;
mii = mod_R(mii);
if (is_zero(mii))
mii = d;
lp_assert(is_pos(mii));
// adjust column m_i
for (unsigned k = m_i + 1; k < m_m; k++) {
m_W[k][m_i] *= u;
m_W[k][m_i] = mod_R_balanced(m_W[k][m_i]);
}
lp_assert(is_pos(mii));
for (unsigned j = 0; j < m_i; j++) {
const mpq & mij = m_W[m_i][j];
if (!is_pos(mij) && - mij < mii)
continue;
mpq q = ceil(mij / mii);
replace_column_j_by_j_minus_u_col_i_W(j, q);
}
}
void process_row_modulo() {
for (m_j = m_i + 1; m_j < m_n; m_j++) {
process_column_in_row_modulo();
}
fix_row_under_diagonal_W_modulo();
}
void calculate_by_modulo() {
for (m_i = 0; m_i < m_m; m_i ++) {
process_row_modulo();
lp_assert(is_pos(m_W[m_i][m_i]));
m_R /= m_W[m_i][m_i];
lp_assert(is_int(m_R));
m_half_R = floor(m_R / 2);
}
}
public:
hnf(M & A, const mpq & d, unsigned r) :
#ifdef Z3DEBUG
m_H(A),
#endif
m_A_orig(A),
m_W(A),
m_buffer(std::max(A.row_count(), A.column_count())),
m_m(A.row_count()),
m_n(A.column_count()),
m_d(d),
m_r(r),
m_R(m_d),
m_half_R(floor(m_R / 2))
{
lp_assert(m_m > 0 && m_n > 0);
if (is_zero(m_d))
return;
#ifdef Z3DEBUG
prepare_U_and_U_reverse();
calculate();
lp_assert(is_correct_final());
#endif
calculate_by_modulo();
#ifdef Z3DEBUG
if (m_H != m_W) {
std::cout << "A = "; m_A_orig.print(std::cout, 4); endl();
std::cout << "H = "; m_H.print(std::cout, 4); endl();
std::cout << "W = "; m_W.print(std::cout, 4); endl();
lp_assert(false);
}
#endif
}
};
}

46
src/util/lp/hnf_cutter.h Normal file
View file

@ -0,0 +1,46 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Nikolaj Bjorner (nbjorner)
Revision History:
--*/
#pragma once
#include "util/lp/lar_term.h"
#include "util/lp/hnf.h"
#include "util/lp/general_matrix.h"
#include "util/lp/var_register.h"
namespace lp {
class hnf_cutter {
var_register m_var_register;
general_matrix m_A;
vector<const lar_term*> m_terms;
public:
void clear() {
m_A.clear();
m_var_register.clear();
m_terms.clear();
}
void add_term_to_A_for_hnf(const lar_term* t, const mpq &) {
m_terms.push_back(t);
for (const auto &p : *t) {
m_var_register.register_user_var(p.var());
}
}
void print(std::ostream & out) {
out << "terms = " << m_terms.size() << ", var = " << m_var_register.size() << std::endl;
}
};
}

View file

@ -50,3 +50,4 @@ template void lp::indexed_vector<double>::resize(unsigned int);
template void lp::print_vector< lp::mpq>(vector< lp::mpq> const &, std::basic_ostream<char, std::char_traits<char> > &);
template void lp::print_vector<std::pair<lp::mpq, unsigned int> >(vector<std::pair<lp::mpq, unsigned int>> const&, std::ostream&);
template void lp::indexed_vector<lp::numeric_pair<lp::mpq> >::erase_from_index(unsigned int);

View file

@ -32,7 +32,7 @@ template <typename T> void print_vector(const vector<T> & t, std::ostream & out)
template <typename T> void print_vector(const buffer<T> & t, std::ostream & out);
template <typename T> void print_sparse_vector(const vector<T> & t, std::ostream & out);
void print_vector(const vector<mpq> & t, std::ostream & out);
void print_vector_as_doubles(const vector<mpq> & t, std::ostream & out);
template <typename T>
class indexed_vector {
public:

View file

@ -46,7 +46,7 @@ void print_sparse_vector(const vector<T> & t, std::ostream & out) {
out << std::endl;
}
void print_vector(const vector<mpq> & t, std::ostream & out) {
void print_vector_as_doubles(const vector<mpq> & t, std::ostream & out) {
for (unsigned i = 0; i < t.size(); i++)
out << t[i].get_double() << std::setprecision(3) << " ";
out << std::endl;

View file

@ -5,7 +5,7 @@
#include "util/lp/int_solver.h"
#include "util/lp/lar_solver.h"
#include "util/lp/cut_solver.h"
#include "util/lp/chase_cut_solver.h"
#include "util/lp/lp_utils.h"
#include <utility>
namespace lp {
@ -414,7 +414,7 @@ unsigned int_solver::row_of_basic_column(unsigned j) const {
// }
typedef cut_solver::monomial mono;
typedef chase_cut_solver::monomial mono;
// it produces an inequality coeff*x <= rs
template <typename T>
@ -456,33 +456,33 @@ struct pivoted_rows_tracking_control {
}
};
void int_solver::copy_explanations_from_cut_solver() {
void int_solver::copy_explanations_from_chase_cut_solver() {
TRACE("propagate_and_backjump_step_int",
for (unsigned j: m_cut_solver.m_explanation)
for (unsigned j: m_chase_cut_solver.m_explanation)
m_lar_solver->print_constraint(m_lar_solver->constraints()[j], tout););
for (unsigned j : m_cut_solver.m_explanation) {
for (unsigned j : m_chase_cut_solver.m_explanation) {
m_ex->push_justification(j);
}
m_cut_solver.m_explanation.clear();
m_chase_cut_solver.m_explanation.clear();
}
void int_solver::copy_values_from_cut_solver() {
for (unsigned j = 0; j < m_lar_solver->A_r().column_count() && j < m_cut_solver.number_of_vars(); j++) {
if (!m_cut_solver.var_is_active(j))
void int_solver::copy_values_from_chase_cut_solver() {
for (unsigned j = 0; j < m_lar_solver->A_r().column_count() && j < m_chase_cut_solver.number_of_vars(); j++) {
if (!m_chase_cut_solver.var_is_active(j))
continue;
if (!is_int(j)) {
continue;
}
m_lar_solver->m_mpq_lar_core_solver.m_r_x[j] = m_cut_solver.var_value(j);
m_lar_solver->m_mpq_lar_core_solver.m_r_x[j] = m_chase_cut_solver.var_value(j);
lp_assert(m_lar_solver->column_value_is_int(j));
}
}
void int_solver::catch_up_in_adding_constraints_to_cut_solver() {
lp_assert(m_cut_solver.number_of_asserts() <= m_lar_solver->constraints().size());
for (unsigned j = m_cut_solver.number_of_asserts(); j < m_lar_solver->constraints().size(); j++) {
add_constraint_to_cut_solver(j, m_lar_solver->constraints()[j]);
void int_solver::catch_up_in_adding_constraints_to_chase_cut_solver() {
lp_assert(m_chase_cut_solver.number_of_asserts() <= m_lar_solver->constraints().size());
for (unsigned j = m_chase_cut_solver.number_of_asserts(); j < m_lar_solver->constraints().size(); j++) {
add_constraint_to_chase_cut_solver(j, m_lar_solver->constraints()[j]);
}
}
@ -536,7 +536,7 @@ bool int_solver::tighten_terms_for_cube() {
}
bool int_solver::find_cube() {
if (m_branch_cut_counter % settings().m_int_find_cube_period != 0)
if (m_branch_cut_counter % settings().m_int_find_cube_period != 0)
return false;
settings().st().m_cube_calls++;
@ -557,13 +557,13 @@ bool int_solver::find_cube() {
m_lar_solver->pop();
move_non_basic_columns_to_bounds();
find_feasible_solution();
lp_assert(m_cut_solver.cancel() || is_feasible());
lp_assert(m_chase_cut_solver.cancel() || is_feasible());
// it can happen that we found an integer solution here
return !m_lar_solver->r_basis_has_inf_int();
}
m_lar_solver->pop();
m_lar_solver->round_to_integer_solution();
lp_assert(m_cut_solver.cancel() || is_feasible());
lp_assert(m_chase_cut_solver.cancel() || is_feasible());
return true;
}
@ -583,29 +583,29 @@ lia_move int_solver::run_gcd_test() {
return lia_move::undef;
}
lia_move int_solver::call_cut_solver() {
if ((m_branch_cut_counter) % settings().m_int_cut_solver_period != 0 || !all_columns_are_bounded())
lia_move int_solver::call_chase_cut_solver() {
if ((m_branch_cut_counter) % settings().m_int_chase_cut_solver_period != 0 || !all_columns_are_bounded())
return lia_move::undef;
TRACE("check_main_int", tout<<"cut_solver";);
catch_up_in_adding_constraints_to_cut_solver();
auto check_res = m_cut_solver.check();
settings().st().m_cut_solver_calls++;
TRACE("check_main_int", tout<<"chase_cut_solver";);
catch_up_in_adding_constraints_to_chase_cut_solver();
auto check_res = m_chase_cut_solver.check();
settings().st().m_chase_cut_solver_calls++;
switch (check_res) {
case cut_solver::lbool::l_false:
copy_explanations_from_cut_solver();
settings().st().m_cut_solver_false++;
case chase_cut_solver::lbool::l_false:
copy_explanations_from_chase_cut_solver();
settings().st().m_chase_cut_solver_false++;
return lia_move::conflict;
case cut_solver::lbool::l_true:
settings().st().m_cut_solver_true++;
copy_values_from_cut_solver();
case chase_cut_solver::lbool::l_true:
settings().st().m_chase_cut_solver_true++;
copy_values_from_chase_cut_solver();
lp_assert(m_lar_solver->all_constraints_hold());
return lia_move::sat;
case cut_solver::lbool::l_undef:
settings().st().m_cut_solver_undef++;
if (m_cut_solver.try_getting_cut(*m_t, *m_k, m_lar_solver->m_mpq_lar_core_solver.m_r_x)) {
case chase_cut_solver::lbool::l_undef:
settings().st().m_chase_cut_solver_undef++;
if (m_chase_cut_solver.try_getting_cut(*m_t, *m_k, m_lar_solver->m_mpq_lar_core_solver.m_r_x)) {
m_lar_solver->subs_term_columns(*m_t);
TRACE("cut_solver_cuts",
tout<<"precut from cut_solver:"; m_lar_solver->print_term(*m_t, tout); tout << " <= " << *m_k << std::endl;);
TRACE("chase_cut_solver_cuts",
tout<<"precut from chase_cut_solver:"; m_lar_solver->print_term(*m_t, tout); tout << " <= " << *m_k << std::endl;);
return lia_move::cut;
}
@ -614,6 +614,63 @@ lia_move int_solver::call_cut_solver() {
}
}
lia_move int_solver::gomory_cut() {
TRACE("check_main_int", tout << "gomory";);
if (move_non_basic_columns_to_bounds()) {
lp_status st = m_lar_solver->find_feasible_solution();
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
TRACE("arith_int", tout << "give_up\n";);
return lia_move::undef;
}
}
int j = find_inf_int_base_column();
if (j == -1) {
j = find_inf_int_nbasis_column();
return j == -1? lia_move::sat : create_branch_on_column(j);
}
lia_move r = proceed_with_gomory_cut(j);
if (r != lia_move::undef)
return r;
return create_branch_on_column(j);
}
void int_solver::try_add_term_to_A_for_hnf(unsigned i) {
mpq rs;
const lar_term* t = m_lar_solver->terms()[i];
for (const auto & p : *t) {
if (!is_int(p.var()))
return; // todo : the mix case!
}
if (!m_lar_solver->get_equality_for_term_on_corrent_x(i, rs))
return;
m_hnf_cutter.add_term_to_A_for_hnf(t, rs);
}
bool int_solver::hnf_matrix_is_empty() const { return true; }
bool int_solver::prepare_matrix_A_for_hnf_cut() {
m_hnf_cutter.clear();
for (unsigned i = 0; i < m_lar_solver->terms().size(); i++)
try_add_term_to_A_for_hnf(i);
m_hnf_cutter.print(std::cout);
return ! hnf_matrix_is_empty();
}
lia_move int_solver::make_hnf_cut() {
if( !prepare_matrix_A_for_hnf_cut())
return lia_move::undef;
return lia_move::undef;
}
lia_move int_solver::hnf_cut() {
if ((m_branch_cut_counter) % settings().m_hnf_cut_period == 0) {
return make_hnf_cut();
}
return lia_move::undef;
}
lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex, bool & upper) {
if (!has_inf_int())
return lia_move::sat;
@ -634,35 +691,17 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex, bool & upper) {
return lia_move::sat;
}
lia_move r = call_cut_solver();
lia_move r = call_chase_cut_solver();
if (r != lia_move::undef)
return r;
r = hnf_cut();
if (r != lia_move::undef)
return r;
if ((m_branch_cut_counter) % settings().m_int_gomory_cut_period == 0) {
TRACE("check_main_int", tout << "gomory";);
if (move_non_basic_columns_to_bounds()) {
lp_status st = m_lar_solver->find_feasible_solution();
lp_assert(non_basic_columns_are_at_bounds());
if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
TRACE("arith_int", tout << "give_up\n";);
return lia_move::undef;
}
}
int j = find_inf_int_base_column();
if (j == -1) {
j = find_inf_int_nbasis_column();
return j == -1? lia_move::sat : create_branch_on_column(j);
}
TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";);
r = proceed_with_gomory_cut(j);
if (r != lia_move::undef)
return r;
return create_branch_on_column(j);
return gomory_cut();
}
TRACE("check_main_int", tout << "branch"; );
int j = find_inf_int_base_column();
if (j == -1) {
j = find_inf_int_nbasis_column();
@ -969,7 +1008,7 @@ linear_combination_iterator<mpq> * int_solver::get_column_iterator(unsigned j) {
int_solver::int_solver(lar_solver* lar_slv) :
m_lar_solver(lar_slv),
m_branch_cut_counter(0),
m_cut_solver([this](unsigned j) {return m_lar_solver->get_column_name(j);},
m_chase_cut_solver([this](unsigned j) {return m_lar_solver->get_column_name(j);},
[this](unsigned j, std::ostream &o) {m_lar_solver->print_constraint(j, o);},
[this]() {return m_lar_solver->A_r().column_count();},
[this](unsigned j) {return get_value(j);},
@ -1328,21 +1367,21 @@ bool int_solver::is_term(unsigned j) const {
return m_lar_solver->column_corresponds_to_term(j);
}
void int_solver::add_constraint_to_cut_solver(unsigned ci, const lar_base_constraint * c) {
void int_solver::add_constraint_to_chase_cut_solver(unsigned ci, const lar_base_constraint * c) {
vector<mono> coeffs;
mpq rs;
get_int_coeffs_from_constraint<mpq>(c, coeffs, rs);
m_cut_solver.add_ineq(coeffs, -rs, ci);
m_chase_cut_solver.add_ineq(coeffs, -rs, ci);
}
void int_solver::pop(unsigned k) {
m_cut_solver.pop_trail(k);
while (m_cut_solver.number_of_asserts() > m_lar_solver->constraints().size())
m_cut_solver.pop_last_assert();
m_cut_solver.pop_constraints();
m_chase_cut_solver.pop_trail(k);
while (m_chase_cut_solver.number_of_asserts() > m_lar_solver->constraints().size())
m_chase_cut_solver.pop_last_assert();
m_chase_cut_solver.pop_constraints();
}
void int_solver::push() { m_cut_solver.push(); }
void int_solver::push() { m_chase_cut_solver.push(); }
unsigned int_solver::column_count() const { return m_lar_solver->column_count(); }

View file

@ -22,8 +22,9 @@ Revision History:
#include "util/lp/static_matrix.h"
#include "util/lp/int_set.h"
#include "util/lp/lar_term.h"
#include "util/lp/cut_solver.h"
#include "util/lp/chase_cut_solver.h"
#include "util/lp/lar_constraints.h"
#include "util/lp/hnf_cutter.h"
namespace lp {
class lar_solver;
@ -54,11 +55,12 @@ public:
// fields
lar_solver * m_lar_solver;
unsigned m_branch_cut_counter;
cut_solver m_cut_solver;
chase_cut_solver m_chase_cut_solver;
lar_term* m_t; // the term to return in the cut
mpq *m_k; // the right side of the cut
explanation *m_ex; // the conflict explanation
bool *m_upper; // we have a cut m_t*x <= k if m_upper is true nad m_t*x >= k otherwise
hnf_cutter m_hnf_cutter;
// methods
int_solver(lar_solver* lp);
@ -152,18 +154,18 @@ private:
unsigned random();
bool has_inf_int() const;
lia_move create_branch_on_column(int j);
void catch_up_in_adding_constraints_to_cut_solver();
void catch_up_in_adding_constraints_to_chase_cut_solver();
public:
template <typename T>
void fill_cut_solver_vars();
void fill_chase_cut_solver_vars();
template <typename T>
void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<cut_solver::monomial>& coeff, T & rs);
void get_int_coeffs_from_constraint(const lar_base_constraint* c, vector<chase_cut_solver::monomial>& coeff, T & rs);
bool is_term(unsigned j) const;
void add_constraint_to_cut_solver(unsigned,const lar_base_constraint*);
void copy_explanations_from_cut_solver();
void add_constraint_to_chase_cut_solver(unsigned,const lar_base_constraint*);
void copy_explanations_from_chase_cut_solver();
void pop(unsigned);
void push();
void copy_values_from_cut_solver();
void copy_values_from_chase_cut_solver();
bool left_branch_is_more_narrow_than_right(unsigned);
bool find_cube();
bool tighten_terms_for_cube();
@ -174,6 +176,12 @@ public:
void find_feasible_solution();
int find_inf_int_nbasis_column() const;
lia_move run_gcd_test();
lia_move call_cut_solver();
lia_move call_chase_cut_solver();
lia_move gomory_cut();
lia_move hnf_cut();
lia_move make_hnf_cut();
bool prepare_matrix_A_for_hnf_cut();
bool hnf_matrix_is_empty() const;
void try_add_term_to_A_for_hnf(unsigned term_index);
};
}

View file

@ -1478,7 +1478,7 @@ bool lar_solver::strategy_is_undecided() const {
void lar_solver::catch_up_in_updating_int_solver() {
for (unsigned i = 0; i < constraints().size(); i++) {
m_int_solver->add_constraint_to_cut_solver(i, constraints()[i]);
m_int_solver->add_constraint_to_chase_cut_solver(i, constraints()[i]);
}
}
@ -2217,6 +2217,40 @@ void lar_solver::round_to_integer_solution() {
}
}
bool lar_solver::get_equality_for_term_on_corrent_x(unsigned term_index, mpq & rs) const {
unsigned tj = term_index + m_terms_start_index;
auto it = m_ext_vars_to_columns.find(tj);
if (it == m_ext_vars_to_columns.end())
return false;
unsigned j = it->second.internal_j();
auto & slv = m_mpq_lar_core_solver.m_r_solver;
impq term_val;
bool term_val_ready = false;
if (slv.column_has_upper_bound(j)) {
const impq & b = slv.m_upper_bounds[j];
lp_assert(is_zero(b.y) && is_int(b.x));
term_val = terms()[term_index]->apply(m_mpq_lar_core_solver.m_r_x);
term_val_ready = true;
if (term_val == b) {
rs = b.x;
return true;
}
}
if (slv.column_has_lower_bound(j)) {
if (!term_val_ready)
term_val = terms()[term_index]->apply(m_mpq_lar_core_solver.m_r_x);
const impq & b = slv.m_lower_bounds[j];
lp_assert(is_zero(b.y) && is_int(b.x));
if (term_val == b) {
rs = b.x;
return true;
}
}
return false;
}
} // namespace lp

View file

@ -579,5 +579,6 @@ public:
unsigned column_count() const { return A_r().column_count(); }
const vector<unsigned> & r_basis() const { return m_mpq_lar_core_solver.r_basis(); }
const vector<unsigned> & r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); }
bool get_equality_for_term_on_corrent_x(unsigned i, mpq &rs) const;
};
}

View file

@ -69,7 +69,7 @@ public:
lp_settings & m_settings;
vector<T> m_y; // the buffer for yB = cb
// a device that is able to solve Bx=c, xB=d, and change the basis
lu<T, X> * m_factorization;
lu<static_matrix<T, X>> * m_factorization;
const column_namer & m_column_names;
indexed_vector<T> m_w; // the vector featuring in 24.3 of the Chvatal book
vector<T> m_d; // the vector of reduced costs
@ -607,9 +607,9 @@ public:
std:: cout << "m_d = " << m_d[j] << std::endl;*/
}
bool column_is_free(unsigned j) { return this->m_column_type[j] == free; }
bool column_is_free(unsigned j) const { return this->m_column_type[j] == free; }
bool column_has_upper_bound(unsigned j) {
bool column_has_upper_bound(unsigned j) const {
switch(m_column_types[j]) {
case column_type::free_column:
case column_type::lower_bound:
@ -628,7 +628,7 @@ public:
return true;
}
bool column_has_lower_bound(unsigned j) {
bool column_has_lower_bound(unsigned j) const {
switch(m_column_types[j]) {
case column_type::free_column:
case column_type::upper_bound:

View file

@ -419,7 +419,7 @@ public:
// returns the number of iterations
unsigned solve();
lu<T, X> * factorization() {return this->m_factorization;}
lu<static_matrix<T, X>> * factorization() {return this->m_factorization;}
void delete_factorization();

View file

@ -102,10 +102,10 @@ struct stats {
unsigned m_need_to_solve_inf;
unsigned m_max_cols;
unsigned m_max_rows;
unsigned m_cut_solver_calls;
unsigned m_cut_solver_true;
unsigned m_cut_solver_false;
unsigned m_cut_solver_undef;
unsigned m_chase_cut_solver_calls;
unsigned m_chase_cut_solver_true;
unsigned m_chase_cut_solver_false;
unsigned m_chase_cut_solver_undef;
unsigned m_gcd_calls;
unsigned m_gcd_conflicts;
unsigned m_cube_calls;
@ -232,11 +232,12 @@ public:
backup_costs(true),
column_number_threshold_for_using_lu_in_lar_solver(4000),
m_int_gomory_cut_period(4),
m_int_cut_solver_period(8),
m_int_chase_cut_solver_period(8),
m_int_find_cube_period(4),
m_int_cuts_etc_period(4),
m_hnf_cut_period(4),
m_int_run_gcd_test(true),
m_cut_solver_cycle_on_var(10),
m_chase_cut_solver_cycle_on_var(10),
m_int_pivot_fixed_vars_from_basis(false),
m_int_patch_only_integer_values(true)
{}
@ -346,11 +347,12 @@ public:
bool backup_costs;
unsigned column_number_threshold_for_using_lu_in_lar_solver;
unsigned m_int_gomory_cut_period;
unsigned m_int_cut_solver_period;
unsigned m_int_chase_cut_solver_period;
unsigned m_int_find_cube_period;
unsigned m_int_cuts_etc_period;
unsigned m_hnf_cut_period;
bool m_int_run_gcd_test;
unsigned m_cut_solver_cycle_on_var;
unsigned m_chase_cut_solver_cycle_on_var;
bool m_int_pivot_fixed_vars_from_basis;
bool m_int_patch_only_integer_values;
}; // end of lp_settings class

View file

@ -23,56 +23,62 @@ Revision History:
#include "util/vector.h"
#include "util/debug.h"
#include "util/lp/lu_def.h"
template double lp::dot_product<double, double>(vector<double> const&, vector<double> const&);
template lp::lu<double, double>::lu(lp::static_matrix<double, double> const&, vector<unsigned int>&, lp::lp_settings&);
template void lp::lu<double, double>::push_matrix_to_tail(lp::tail_matrix<double, double>*);
template void lp::lu<double, double>::replace_column(double, lp::indexed_vector<double>&, unsigned);
template void lp::lu<double, double>::solve_Bd(unsigned int, lp::indexed_vector<double>&, lp::indexed_vector<double>&);
template lp::lu<double, double>::~lu();
template void lp::lu<lp::mpq, lp::mpq>::push_matrix_to_tail(lp::tail_matrix<lp::mpq, lp::mpq>*);
template void lp::lu<lp::mpq, lp::mpq>::solve_Bd(unsigned int, lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&);
template lp::lu<lp::mpq, lp::mpq>::~lu();
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::push_matrix_to_tail(lp::tail_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >*);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Bd(unsigned int, lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&);
template lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::~lu();
template lp::mpq lp::dot_product<lp::mpq, lp::mpq>(vector<lp::mpq > const&, vector<lp::mpq > const&);
template void lp::init_factorization<double, double>(lp::lu<double, double>*&, lp::static_matrix<double, double>&, vector<unsigned int>&, lp::lp_settings&);
template void lp::init_factorization<lp::mpq, lp::mpq>(lp::lu<lp::mpq, lp::mpq>*&, lp::static_matrix<lp::mpq, lp::mpq>&, vector<unsigned int>&, lp::lp_settings&);
template void lp::init_factorization<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >*&, lp::static_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, vector<unsigned int>&, lp::lp_settings&);
namespace lp {
template double dot_product<double, double>(vector<double> const&, vector<double> const&);
template lu<static_matrix<double, double>>::lu(static_matrix<double, double> const&, vector<unsigned int>&, lp_settings&);
template void lu<static_matrix<double, double>>::push_matrix_to_tail(tail_matrix<double, double>*);
template void lu<static_matrix<double, double>>::replace_column(double, indexed_vector<double>&, unsigned);
template void lu<static_matrix<double, double>>::solve_Bd(unsigned int, indexed_vector<double>&, indexed_vector<double>&);
template lu<static_matrix<double, double>>::~lu();
template void lu<static_matrix<mpq, mpq>>::push_matrix_to_tail(tail_matrix<mpq, mpq>*);
template void lu<static_matrix<mpq, mpq>>::solve_Bd(unsigned int, indexed_vector<mpq>&, indexed_vector<mpq>&);
template lu<static_matrix<mpq, mpq>>::~lu();
template void lu<static_matrix<mpq, impq>>::push_matrix_to_tail(tail_matrix<mpq, impq >*);
template void lu<static_matrix<mpq, impq>>::solve_Bd(unsigned int, indexed_vector<mpq>&, indexed_vector<mpq>&);
template lu<static_matrix<mpq, impq>>::~lu();
template mpq dot_product<mpq, mpq>(vector<mpq > const&, vector<mpq > const&);
template void init_factorization<static_matrix<double, double>>
(lu<static_matrix<double, double>>*&, static_matrix<double, double>&, vector<unsigned int>&, lp_settings&);
template void init_factorization<static_matrix<mpq, mpq>>
(lu<static_matrix<mpq,mpq>>*&, static_matrix<mpq, mpq>&, vector<unsigned int>&, lp_settings&);
template void init_factorization<static_matrix<mpq, impq>>(lu<static_matrix<mpq, impq> >*&, static_matrix<mpq, impq >&, vector<unsigned int>&, lp_settings&);
#ifdef Z3DEBUG
template void lp::print_matrix<double, double>(lp::sparse_matrix<double, double>&, std::ostream & out);
template void lp::print_matrix<lp::mpq, lp::mpq>(lp::static_matrix<lp::mpq, lp::mpq>&, std::ostream&);
template void lp::print_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::static_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, std::ostream&);
template void lp::print_matrix<double, double>(lp::static_matrix<double, double>&, std::ostream & out);
template bool lp::lu<double, double>::is_correct(const vector<unsigned>& basis);
template bool lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::is_correct( vector<unsigned int> const &);
template lp::dense_matrix<double, double> lp::get_B<double, double>(lp::lu<double, double>&, const vector<unsigned>& basis);
template lp::dense_matrix<lp::mpq, lp::mpq> lp::get_B<lp::mpq, lp::mpq>(lp::lu<lp::mpq, lp::mpq>&, vector<unsigned int> const&);
template void print_matrix<square_sparse_matrix<double, double>>(square_sparse_matrix<double, double>&, std::ostream & out);
template void print_matrix<static_matrix<mpq,mpq>>(static_matrix<mpq, mpq>&, std::ostream&);
template void print_matrix<static_matrix<mpq, impq> >(static_matrix<mpq, impq >&, std::ostream&);
template void print_matrix<static_matrix<double, double>>(static_matrix<double, double>&, std::ostream & out);
template bool lu<static_matrix<double, double>>::is_correct(const vector<unsigned>& basis);
template bool lu<static_matrix<mpq, impq>>::is_correct( vector<unsigned int> const &);
template dense_matrix<double, double> get_B<static_matrix<double, double>>(lu<static_matrix<double, double>>&, const vector<unsigned>& basis);
template dense_matrix<mpq, mpq> get_B<static_matrix<mpq, mpq>>(lu<static_matrix<mpq, mpq>>&, vector<unsigned int> const&);
#endif
template bool lp::lu<double, double>::pivot_the_row(int); // NOLINT
template void lp::lu<double, double>::init_vector_w(unsigned int, lp::indexed_vector<double>&);
template void lp::lu<double, double>::solve_By(vector<double>&);
template void lp::lu<double, double>::solve_By_when_y_is_ready_for_X(vector<double>&);
template void lp::lu<double, double>::solve_yB_with_error_check(vector<double>&, const vector<unsigned>& basis);
template void lp::lu<double, double>::solve_yB_with_error_check_indexed(lp::indexed_vector<double>&, vector<int> const&, const vector<unsigned> & basis, const lp_settings&);
template void lp::lu<lp::mpq, lp::mpq>::replace_column(lp::mpq, lp::indexed_vector<lp::mpq>&, unsigned);
template void lp::lu<lp::mpq, lp::mpq>::solve_By(vector<lp::mpq >&);
template void lp::lu<lp::mpq, lp::mpq>::solve_By_when_y_is_ready_for_X(vector<lp::mpq >&);
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_with_error_check(vector<lp::mpq >&, const vector<unsigned>& basis);
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_with_error_check_indexed(lp::indexed_vector<lp::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_with_error_check_indexed(lp::indexed_vector<lp::mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::init_vector_w(unsigned int, lp::indexed_vector<lp::mpq>&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::replace_column(lp::mpq, lp::indexed_vector<lp::mpq>&, unsigned);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_Bd_faster(unsigned int, lp::indexed_vector<lp::mpq>&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_By(vector<lp::numeric_pair<lp::mpq> >&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_By_when_y_is_ready_for_X(vector<lp::numeric_pair<lp::mpq> >&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_with_error_check(vector<lp::mpq >&, const vector<unsigned>& basis);
template void lp::lu<lp::mpq, lp::mpq>::solve_By(lp::indexed_vector<lp::mpq>&);
template void lp::lu<double, double>::solve_By(lp::indexed_vector<double>&);
template void lp::lu<double, double>::solve_yB_indexed(lp::indexed_vector<double>&);
template void lp::lu<lp::mpq, lp::mpq>::solve_yB_indexed(lp::indexed_vector<lp::mpq>&);
template void lp::lu<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_yB_indexed(lp::indexed_vector<lp::mpq>&);
template void lp::lu<lp::mpq, lp::mpq>::solve_By_for_T_indexed_only(lp::indexed_vector<lp::mpq>&, lp::lp_settings const&);
template void lp::lu<double, double>::solve_By_for_T_indexed_only(lp::indexed_vector<double>&, lp::lp_settings const&);
template bool lu<static_matrix<double, double>>::pivot_the_row(int); // NOLINT
template void lu<static_matrix<double, double>>::init_vector_w(unsigned int, indexed_vector<double>&);
template void lu<static_matrix<double, double>>::solve_By(vector<double>&);
template void lu<static_matrix<double, double>>::solve_By_when_y_is_ready_for_X(vector<double>&);
template void lu<static_matrix<double, double>>::solve_yB_with_error_check(vector<double>&, const vector<unsigned>& basis);
template void lu<static_matrix<double, double>>::solve_yB_with_error_check_indexed(indexed_vector<double>&, vector<int> const&, const vector<unsigned> & basis, const lp_settings&);
template void lu<static_matrix<mpq, mpq>>::replace_column(mpq, indexed_vector<mpq>&, unsigned);
template void lu<static_matrix<mpq, mpq>>::solve_By(vector<mpq >&);
template void lu<static_matrix<mpq, mpq>>::solve_By_when_y_is_ready_for_X(vector<mpq >&);
template void lu<static_matrix<mpq, mpq>>::solve_yB_with_error_check(vector<mpq >&, const vector<unsigned>& basis);
template void lu<static_matrix<mpq, mpq>>::solve_yB_with_error_check_indexed(indexed_vector<mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
template void lu<static_matrix<mpq, impq> >::solve_yB_with_error_check_indexed(indexed_vector<mpq>&, vector< int > const&, const vector<unsigned> & basis, const lp_settings&);
template void lu<static_matrix<mpq, impq> >::init_vector_w(unsigned int, indexed_vector<mpq>&);
template void lu<static_matrix<mpq, impq> >::replace_column(mpq, indexed_vector<mpq>&, unsigned);
template void lu<static_matrix<mpq, impq> >::solve_Bd_faster(unsigned int, indexed_vector<mpq>&);
template void lu<static_matrix<mpq, impq> >::solve_By(vector<impq >&);
template void lu<static_matrix<mpq, impq> >::solve_By_when_y_is_ready_for_X(vector<impq >&);
template void lu<static_matrix<mpq, impq> >::solve_yB_with_error_check(vector<mpq >&, const vector<unsigned>& basis);
template void lu<static_matrix<mpq, mpq>>::solve_By(indexed_vector<mpq>&);
template void lu<static_matrix<double, double>>::solve_By(indexed_vector<double>&);
template void lu<static_matrix<double, double>>::solve_yB_indexed(indexed_vector<double>&);
template void lu<static_matrix<mpq, impq> >::solve_yB_indexed(indexed_vector<mpq>&);
template void lu<static_matrix<mpq, mpq>>::solve_By_for_T_indexed_only(indexed_vector<mpq>&, lp_settings const&);
template void lu<static_matrix<double, double>>::solve_By_for_T_indexed_only(indexed_vector<double>&, lp_settings const&);
#ifdef Z3DEBUG
template void print_matrix<tail_matrix<double, double>>(tail_matrix<double, double>&, std::ostream&);
#endif
}

View file

@ -8,7 +8,12 @@ Module Name:
Abstract:
<abstract>
for matrix B we have
t0*...*tn-1*B = Q*U*R
here ti are matrices corresponding to pivot operations,
including columns and rows swaps,
or a multiplication matrix row by a number
Q, R - permutations and U is an upper triangular matrix
Author:
Lev Nachmanson (levnach)
@ -24,7 +29,7 @@ Revision History:
#include "util/debug.h"
#include <algorithm>
#include <set>
#include "util/lp/sparse_matrix.h"
#include "util/lp/square_sparse_matrix.h"
#include "util/lp/static_matrix.h"
#include <string>
#include "util/lp/numeric_pair.h"
@ -36,13 +41,11 @@ Revision History:
namespace lp {
#ifdef Z3DEBUG
template <typename T, typename X> // print the nr x nc submatrix at the top left corner
void print_submatrix(sparse_matrix<T, X> & m, unsigned mr, unsigned nc);
void print_submatrix(square_sparse_matrix<T, X> & m, unsigned mr, unsigned nc);
template<typename T, typename X>
void print_matrix(static_matrix<T, X> &m, std::ostream & out);
template <typename M>
void print_matrix(M &m, std::ostream & out);
template <typename T, typename X>
void print_matrix(sparse_matrix<T, X>& m, std::ostream & out);
#endif
template <typename T, typename X>
@ -123,17 +126,20 @@ enum class LU_status { OK, Degenerated};
// This class supports updates of the columns of B, and solves systems Bx=b,and yB=c
// Using Suhl-Suhl method described in the dissertation of Achim Koberstein, Chapter 5
template <typename T, typename X>
template <typename M>
class lu {
LU_status m_status;
public:
typedef typename M::coefftype T;
typedef typename M::argtype X;
// the fields
unsigned m_dim;
static_matrix<T, X> const &m_A;
const M & m_A;
permutation_matrix<T, X> m_Q;
permutation_matrix<T, X> m_R;
permutation_matrix<T, X> m_r_wave;
sparse_matrix<T, X> m_U;
square_sparse_matrix<T, X> m_U;
square_dense_submatrix<T, X>* m_dense_LU;
vector<tail_matrix<T, X> *> m_tail;
@ -147,10 +153,11 @@ public:
// constructor
// if A is an m by n matrix then basis has length m and values in [0,n); the values are all different
// they represent the set of m columns
lu(static_matrix<T, X> const & A,
lu(const M & A,
vector<unsigned>& basis,
lp_settings & settings);
void debug_test_of_basis(static_matrix<T, X> const & A, vector<unsigned> & basis);
lu(const M & A, lp_settings&);
void debug_test_of_basis(const M & A, vector<unsigned> & basis);
void solve_Bd_when_w_is_ready(vector<T> & d, indexed_vector<T>& w );
void solve_By(indexed_vector<X> & y);
@ -222,7 +229,7 @@ public:
eta_matrix<T, X> * get_eta_matrix_for_pivot(unsigned j);
// we're processing the column j now
eta_matrix<T, X> * get_eta_matrix_for_pivot(unsigned j, sparse_matrix<T, X>& copy_of_U);
eta_matrix<T, X> * get_eta_matrix_for_pivot(unsigned j, square_sparse_matrix<T, X>& copy_of_U);
// see page 407 of Chvatal
unsigned transform_U_to_V_by_replacing_column(indexed_vector<T> & w, unsigned leaving_column_of_U);
@ -245,7 +252,7 @@ public:
}
T B_(unsigned i, unsigned j, const vector<unsigned>& basis) {
return m_A.get_elem(i, basis[j]);
return m_A[i][basis[j]];
}
unsigned dimension() { return m_dim; }
@ -261,11 +268,13 @@ public:
void process_column(int j);
bool is_correct(const vector<unsigned>& basis);
bool is_correct();
#ifdef Z3DEBUG
dense_matrix<T, X> tail_product();
dense_matrix<T, X> get_left_side(const vector<unsigned>& basis);
dense_matrix<T, X> get_left_side();
dense_matrix<T, X> get_right_side();
#endif
@ -364,11 +373,14 @@ public:
}; // end of lu
template <typename T, typename X>
void init_factorization(lu<T, X>* & factorization, static_matrix<T, X> & m_A, vector<unsigned> & m_basis, lp_settings &m_settings);
template <typename M>
void init_factorization(lu<M>* & factorization, M & m_A, vector<unsigned> & m_basis, lp_settings &m_settings);
#ifdef Z3DEBUG
template <typename T, typename X>
dense_matrix<T, X> get_B(lu<T, X>& f, const vector<unsigned>& basis);
template <typename T, typename X, typename M>
dense_matrix<T, X> get_B(lu<M>& f, const vector<unsigned>& basis);
template <typename T, typename X, typename M>
dense_matrix<T, X> get_B(lu<M>& f);
#endif
}

View file

@ -26,8 +26,8 @@ Revision History:
#include "util/lp/lu.h"
namespace lp {
#ifdef Z3DEBUG
template <typename T, typename X> // print the nr x nc submatrix at the top left corner
void print_submatrix(sparse_matrix<T, X> & m, unsigned mr, unsigned nc, std::ostream & out) {
template <typename T, typename X, typename M> // print the nr x nc submatrix at the top left corner
void print_submatrix(square_sparse_matrix<T, X> & m, unsigned mr, unsigned nc, std::ostream & out) {
vector<vector<std::string>> A;
vector<unsigned> widths;
for (unsigned i = 0; i < m.row_count() && i < mr ; i++) {
@ -44,15 +44,14 @@ void print_submatrix(sparse_matrix<T, X> & m, unsigned mr, unsigned nc, std::ost
print_matrix_with_widths(A, widths, out);
}
template<typename T, typename X>
void print_matrix(static_matrix<T, X> &m, std::ostream & out) {
template<typename M>
void print_matrix(M &m, std::ostream & out) {
vector<vector<std::string>> A;
vector<unsigned> widths;
std::set<std::pair<unsigned, unsigned>> domain = m.get_domain();
for (unsigned i = 0; i < m.row_count(); i++) {
A.push_back(vector<std::string>());
for (unsigned j = 0; j < m.column_count(); j++) {
A[i].push_back(T_to_string(static_cast<T>(m(i, j))));
A[i].push_back(T_to_string(m[i][j]));
}
}
@ -63,23 +62,6 @@ void print_matrix(static_matrix<T, X> &m, std::ostream & out) {
print_matrix_with_widths(A, widths, out);
}
template <typename T, typename X>
void print_matrix(sparse_matrix<T, X>& m, std::ostream & out) {
vector<vector<std::string>> A;
vector<unsigned> widths;
for (unsigned i = 0; i < m.row_count(); i++) {
A.push_back(vector<std::string>());
for (unsigned j = 0; j < m.column_count(); j++) {
A[i].push_back(T_to_string(static_cast<T>(m(i, j))));
}
}
for (unsigned j = 0; j < m.column_count(); j++) {
widths.push_back(get_width_of_column(j, A));
}
print_matrix_with_widths(A, widths, out);
}
#endif
@ -122,10 +104,10 @@ void one_elem_on_diag<T, X>::apply_from_left_to_T(indexed_vector<T> & w, lp_sett
// This class supports updates of the columns of B, and solves systems Bx=b,and yB=c
// Using Suhl-Suhl method described in the dissertation of Achim Koberstein, Chapter 5
template <typename T, typename X>
lu<T, X>::lu(static_matrix<T, X> const & A,
vector<unsigned>& basis,
lp_settings & settings):
template <typename M>
lu<M>::lu(const M& A,
vector<unsigned>& basis,
lp_settings & settings):
m_status(LU_status::OK),
m_dim(A.row_count()),
m_A(A),
@ -147,8 +129,30 @@ lu<T, X>::lu(static_matrix<T, X> const & A,
// lp_assert(check_correctness());
#endif
}
template <typename T, typename X>
void lu<T, X>::debug_test_of_basis(static_matrix<T, X> const & A, vector<unsigned> & basis) {
template <typename M>
lu<M>::lu(const M& A,
lp_settings & settings):
m_status(LU_status::OK),
m_dim(A.row_count()),
m_A(A),
m_Q(m_dim),
m_R(m_dim),
m_r_wave(m_dim),
m_U(A), // create the square matrix that eventually will be factorized
m_settings(settings),
m_failure(false),
m_row_eta_work_vector(A.row_count()),
m_refactor_counter(0) {
lp_assert(A.row_count() == A.column_count());
std::cout << "m_U = \n";
print_matrix(&m_U, std::cout);
create_initial_factorization();
#ifdef Z3DEBUG
lp_assert(is_correct());
#endif
}
template <typename M>
void lu<M>::debug_test_of_basis( M const & A, vector<unsigned> & basis) {
std::set<unsigned> set;
for (unsigned i = 0; i < A.row_count(); i++) {
lp_assert(basis[i]< A.column_count());
@ -157,22 +161,22 @@ void lu<T, X>::debug_test_of_basis(static_matrix<T, X> const & A, vector<unsigne
lp_assert(set.size() == A.row_count());
}
template <typename T, typename X>
void lu<T, X>::solve_By(indexed_vector<X> & y) {
template <typename M>
void lu<M>::solve_By(indexed_vector<X> & y) {
lp_assert(false); // not implemented
// init_vector_y(y);
// solve_By_when_y_is_ready(y);
}
template <typename T, typename X>
void lu<T, X>::solve_By(vector<X> & y) {
template <typename M>
void lu<M>::solve_By(vector<X> & y) {
init_vector_y(y);
solve_By_when_y_is_ready_for_X(y);
}
template <typename T, typename X>
void lu<T, X>::solve_By_when_y_is_ready_for_X(vector<X> & y) {
template <typename M>
void lu<M>::solve_By_when_y_is_ready_for_X(vector<X> & y) {
if (numeric_traits<T>::precise()) {
m_U.solve_U_y(y);
m_R.apply_reverse_from_left_to_X(y); // see 24.3 from Chvatal
@ -189,8 +193,8 @@ void lu<T, X>::solve_By_when_y_is_ready_for_X(vector<X> & y) {
}
}
template <typename T, typename X>
void lu<T, X>::solve_By_when_y_is_ready_for_T(vector<T> & y, vector<unsigned> & index) {
template <typename M>
void lu<M>::solve_By_when_y_is_ready_for_T(vector<T> & y, vector<unsigned> & index) {
if (numeric_traits<T>::precise()) {
m_U.solve_U_y(y);
m_R.apply_reverse_from_left_to_T(y); // see 24.3 from Chvatal
@ -214,8 +218,8 @@ void lu<T, X>::solve_By_when_y_is_ready_for_T(vector<T> & y, vector<unsigned> &
}
}
template <typename T, typename X>
void lu<T, X>::solve_By_for_T_indexed_only(indexed_vector<T> & y, const lp_settings & settings) {
template <typename M>
void lu<M>::solve_By_for_T_indexed_only(indexed_vector<T> & y, const lp_settings & settings) {
if (numeric_traits<T>::precise()) {
vector<unsigned> active_rows;
m_U.solve_U_y_indexed_only(y, settings, active_rows);
@ -226,8 +230,8 @@ void lu<T, X>::solve_By_for_T_indexed_only(indexed_vector<T> & y, const lp_setti
m_R.apply_reverse_from_left(y); // see 24.3 from Chvatal
}
template <typename T, typename X>
void lu<T, X>::print_matrix_compact(std::ostream & f) {
template <typename M>
void lu<M>::print_matrix_compact(std::ostream & f) {
f << "matrix_start" << std::endl;
f << "nrows " << m_A.row_count() << std::endl;
f << "ncolumns " << m_A.column_count() << std::endl;
@ -241,8 +245,8 @@ void lu<T, X>::print_matrix_compact(std::ostream & f) {
}
f << "matrix_end" << std::endl;
}
template <typename T, typename X>
void lu<T, X>::print(indexed_vector<T> & w, const vector<unsigned>& basis) {
template <typename M>
void lu< M>::print(indexed_vector<T> & w, const vector<unsigned>& basis) {
std::string dump_file_name("/tmp/lu");
remove(dump_file_name.c_str());
std::ofstream f(dump_file_name);
@ -256,8 +260,8 @@ void lu<T, X>::print(indexed_vector<T> & w, const vector<unsigned>& basis) {
print_indexed_vector(w, f);
f.close();
}
template <typename T, typename X>
void lu<T, X>::solve_Bd(unsigned a_column, indexed_vector<T> & d, indexed_vector<T> & w) {
template <typename M>
void lu< M>::solve_Bd(unsigned a_column, indexed_vector<T> & d, indexed_vector<T> & w) {
init_vector_w(a_column, w);
if (w.m_index.size() * ratio_of_index_size_to_all_size<T>() < d.m_data.size()) { // this const might need some tuning
@ -270,14 +274,14 @@ void lu<T, X>::solve_Bd(unsigned a_column, indexed_vector<T> & d, indexed_vector
}
}
template <typename T, typename X>
void lu<T, X>::solve_Bd_faster(unsigned a_column, indexed_vector<T> & d) { // puts the a_column into d
template <typename M>
void lu< M>::solve_Bd_faster(unsigned a_column, indexed_vector<T> & d) { // puts the a_column into d
init_vector_w(a_column, d);
solve_By_for_T_indexed_only(d, m_settings);
}
template <typename T, typename X>
void lu<T, X>::solve_yB(vector<T>& y) {
template <typename M>
void lu< M>::solve_yB(vector<T>& y) {
// first solve yU = cb*R(-1)
m_R.apply_reverse_from_right_to_T(y); // got y = cb*R(-1)
m_U.solve_y_U(y); // got y*U=cb*R(-1)
@ -290,8 +294,8 @@ void lu<T, X>::solve_yB(vector<T>& y) {
}
}
template <typename T, typename X>
void lu<T, X>::solve_yB_indexed(indexed_vector<T>& y) {
template <typename M>
void lu< M>::solve_yB_indexed(indexed_vector<T>& y) {
lp_assert(y.is_OK());
// first solve yU = cb*R(-1)
m_R.apply_reverse_from_right_to_T(y); // got y = cb*R(-1)
@ -309,15 +313,15 @@ void lu<T, X>::solve_yB_indexed(indexed_vector<T>& y) {
}
}
template <typename T, typename X>
void lu<T, X>::add_delta_to_solution(const vector<T>& yc, vector<T>& y){
template <typename M>
void lu< M>::add_delta_to_solution(const vector<T>& yc, vector<T>& y){
unsigned i = static_cast<unsigned>(y.size());
while (i--)
y[i]+=yc[i];
}
template <typename T, typename X>
void lu<T, X>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
template <typename M>
void lu< M>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
// the delta sits in m_y_copy, put result into y
lp_assert(y.is_OK());
lp_assert(m_y_copy.is_OK());
@ -344,16 +348,16 @@ void lu<T, X>::add_delta_to_solution_indexed(indexed_vector<T>& y) {
lp_assert(y.is_OK());
}
template <typename T, typename X>
void lu<T, X>::find_error_of_yB(vector<T>& yc, const vector<T>& y, const vector<unsigned>& m_basis) {
template <typename M>
void lu< M>::find_error_of_yB(vector<T>& yc, const vector<T>& y, const vector<unsigned>& m_basis) {
unsigned i = m_dim;
while (i--) {
yc[i] -= m_A.dot_product_with_column(y, m_basis[i]);
}
}
template <typename T, typename X>
void lu<T, X>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector<int>& heading, const lp_settings& settings) {
template <typename M>
void lu< M>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector<int>& heading, const lp_settings& settings) {
#if 0 == 1
// it is a non efficient version
indexed_vector<T> yc = m_y_copy;
@ -423,8 +427,8 @@ void lu<T, X>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector
// solves y*B = y
// y is the input
template <typename T, typename X>
void lu<T, X>::solve_yB_with_error_check_indexed(indexed_vector<T> & y, const vector<int>& heading, const vector<unsigned> & basis, const lp_settings & settings) {
template <typename M>
void lu< M>::solve_yB_with_error_check_indexed(indexed_vector<T> & y, const vector<int>& heading, const vector<unsigned> & basis, const lp_settings & settings) {
if (numeric_traits<T>::precise()) {
if (y.m_index.size() * ratio_of_index_size_to_all_size<T>() * 3 < m_A.column_count()) {
solve_yB_indexed(y);
@ -461,8 +465,8 @@ void lu<T, X>::solve_yB_with_error_check_indexed(indexed_vector<T> & y, const ve
// solves y*B = y
// y is the input
template <typename T, typename X>
void lu<T, X>::solve_yB_with_error_check(vector<T> & y, const vector<unsigned>& basis) {
template <typename M>
void lu< M>::solve_yB_with_error_check(vector<T> & y, const vector<unsigned>& basis) {
if (numeric_traits<T>::precise()) {
solve_yB(y);
return;
@ -475,8 +479,8 @@ void lu<T, X>::solve_yB_with_error_check(vector<T> & y, const vector<unsigned>&
add_delta_to_solution(yc, y);
m_y_copy.clear_all();
}
template <typename T, typename X>
void lu<T, X>::apply_Q_R_to_U(permutation_matrix<T, X> & r_wave) {
template <typename M>
void lu< M>::apply_Q_R_to_U(permutation_matrix<T, X> & r_wave) {
m_U.multiply_from_right(r_wave);
m_U.multiply_from_left_with_reverse(r_wave);
}
@ -488,62 +492,62 @@ void lu<T, X>::apply_Q_R_to_U(permutation_matrix<T, X> & r_wave) {
// solving Bd = a ( to find the column d of B^{-1} A_N corresponding to the entering
// variable
template <typename T, typename X>
lu<T, X>::~lu(){
template <typename M>
lu< M>::~lu(){
for (auto t : m_tail) {
delete t;
}
}
template <typename T, typename X>
void lu<T, X>::init_vector_y(vector<X> & y) {
template <typename M>
void lu< M>::init_vector_y(vector<X> & y) {
apply_lp_list_to_y(y);
m_Q.apply_reverse_from_left_to_X(y);
}
template <typename T, typename X>
void lu<T, X>::perform_transformations_on_w(indexed_vector<T>& w) {
template <typename M>
void lu< M>::perform_transformations_on_w(indexed_vector<T>& w) {
apply_lp_list_to_w(w);
m_Q.apply_reverse_from_left(w);
// TBD does not compile: lp_assert(numeric_traits<T>::precise() || check_vector_for_small_values(w, m_settings));
}
// see Chvatal 24.3
template <typename T, typename X>
void lu<T, X>::init_vector_w(unsigned entering, indexed_vector<T> & w) {
template <typename M>
void lu< M>::init_vector_w(unsigned entering, indexed_vector<T> & w) {
w.clear();
m_A.copy_column_to_indexed_vector(entering, w); // w = a, the column
perform_transformations_on_w(w);
}
template <typename T, typename X>
void lu<T, X>::apply_lp_list_to_w(indexed_vector<T> & w) {
template <typename M>
void lu< M>::apply_lp_list_to_w(indexed_vector<T> & w) {
for (unsigned i = 0; i < m_tail.size(); i++) {
m_tail[i]->apply_from_left_to_T(w, m_settings);
// TBD does not compile: lp_assert(check_vector_for_small_values(w, m_settings));
}
}
template <typename T, typename X>
void lu<T, X>::apply_lp_list_to_y(vector<X>& y) {
template <typename M>
void lu< M>::apply_lp_list_to_y(vector<X>& y) {
for (unsigned i = 0; i < m_tail.size(); i++) {
m_tail[i]->apply_from_left(y, m_settings);
}
}
template <typename T, typename X>
void lu<T, X>::swap_rows(int j, int k) {
template <typename M>
void lu< M>::swap_rows(int j, int k) {
if (j != k) {
m_Q.transpose_from_left(j, k);
m_U.swap_rows(j, k);
}
}
template <typename T, typename X>
void lu<T, X>::swap_columns(int j, int pivot_column) {
template <typename M>
void lu< M>::swap_columns(int j, int pivot_column) {
if (j == pivot_column)
return;
m_R.transpose_from_right(j, pivot_column);
m_U.swap_columns(j, pivot_column);
}
template <typename T, typename X>
bool lu<T, X>::pivot_the_row(int row) {
template <typename M>
bool lu< M>::pivot_the_row(int row) {
eta_matrix<T, X> * eta_matrix = get_eta_matrix_for_pivot(row);
if (get_status() != LU_status::OK) {
return false;
@ -560,8 +564,8 @@ bool lu<T, X>::pivot_the_row(int row) {
return true;
}
// we're processing the column j now
template <typename T, typename X>
eta_matrix<T, X> * lu<T, X>::get_eta_matrix_for_pivot(unsigned j) {
template <typename M>
eta_matrix<typename M::coefftype, typename M::argtype> * lu< M>::get_eta_matrix_for_pivot(unsigned j) {
eta_matrix<T, X> *ret;
if(!m_U.fill_eta_matrix(j, &ret)) {
set_status(LU_status::Degenerated);
@ -569,16 +573,16 @@ eta_matrix<T, X> * lu<T, X>::get_eta_matrix_for_pivot(unsigned j) {
return ret;
}
// we're processing the column j now
template <typename T, typename X>
eta_matrix<T, X> * lu<T, X>::get_eta_matrix_for_pivot(unsigned j, sparse_matrix<T, X>& copy_of_U) {
template <typename M>
eta_matrix<typename M::coefftype, typename M::argtype> * lu<M>::get_eta_matrix_for_pivot(unsigned j, square_sparse_matrix<T, X>& copy_of_U) {
eta_matrix<T, X> *ret;
copy_of_U.fill_eta_matrix(j, &ret);
return ret;
}
// see page 407 of Chvatal
template <typename T, typename X>
unsigned lu<T, X>::transform_U_to_V_by_replacing_column(indexed_vector<T> & w,
template <typename M>
unsigned lu<M>::transform_U_to_V_by_replacing_column(indexed_vector<T> & w,
unsigned leaving_column) {
unsigned column_to_replace = m_R.apply_reverse(leaving_column);
m_U.replace_column(column_to_replace, w, m_settings);
@ -586,15 +590,15 @@ unsigned lu<T, X>::transform_U_to_V_by_replacing_column(indexed_vector<T> & w,
}
#ifdef Z3DEBUG
template <typename T, typename X>
void lu<T, X>::check_vector_w(unsigned entering) {
template <typename M>
void lu<M>::check_vector_w(unsigned entering) {
T * w = new T[m_dim];
m_A.copy_column_to_vector(entering, w);
check_apply_lp_lists_to_w(w);
delete [] w;
}
template <typename T, typename X>
void lu<T, X>::check_apply_matrix_to_vector(matrix<T, X> *lp, T *w) {
template <typename M>
void lu<M>::check_apply_matrix_to_vector(matrix<T, X> *lp, T *w) {
if (lp != nullptr) {
lp -> set_number_of_rows(m_dim);
lp -> set_number_of_columns(m_dim);
@ -602,8 +606,8 @@ void lu<T, X>::check_apply_matrix_to_vector(matrix<T, X> *lp, T *w) {
}
}
template <typename T, typename X>
void lu<T, X>::check_apply_lp_lists_to_w(T * w) {
template <typename M>
void lu<M>::check_apply_lp_lists_to_w(T * w) {
for (unsigned i = 0; i < m_tail.size(); i++) {
check_apply_matrix_to_vector(m_tail[i], w);
}
@ -615,8 +619,8 @@ void lu<T, X>::check_apply_lp_lists_to_w(T * w) {
}
#endif
template <typename T, typename X>
void lu<T, X>::process_column(int j) {
template <typename M>
void lu<M>::process_column(int j) {
unsigned pi, pj;
bool success = m_U.get_pivot_for_column(pi, pj, m_settings.c_partial_pivoting, j);
if (!success) {
@ -637,8 +641,8 @@ void lu<T, X>::process_column(int j) {
m_failure = true;
}
}
template <typename T, typename X>
bool lu<T, X>::is_correct(const vector<unsigned>& basis) {
template <typename M>
bool lu<M>::is_correct(const vector<unsigned>& basis) {
#ifdef Z3DEBUG
if (get_status() != LU_status::OK) {
return false;
@ -651,10 +655,27 @@ bool lu<T, X>::is_correct(const vector<unsigned>& basis) {
#endif
}
template <typename M>
bool lu<M>::is_correct() {
#ifdef Z3DEBUG
if (get_status() != LU_status::OK) {
std::cout << " status" << std::endl;
return false;
}
dense_matrix<T, X> left_side = get_left_side();
std::cout << "ls = "; print_matrix(left_side, std::cout);
dense_matrix<T, X> right_side = get_right_side();
std::cout << "rs = "; print_matrix(right_side, std::cout);
return left_side == right_side;
#else
return true;
#endif
}
#ifdef Z3DEBUG
template <typename T, typename X>
dense_matrix<T, X> lu<T, X>::tail_product() {
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> lu<M>::tail_product() {
lp_assert(tail_size() > 0);
dense_matrix<T, X> left_side = permutation_matrix<T, X>(m_dim);
for (unsigned i = 0; i < tail_size(); i++) {
@ -665,8 +686,8 @@ dense_matrix<T, X> lu<T, X>::tail_product() {
}
return left_side;
}
template <typename T, typename X>
dense_matrix<T, X> lu<T, X>::get_left_side(const vector<unsigned>& basis) {
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> lu<M>::get_left_side(const vector<unsigned>& basis) {
dense_matrix<T, X> left_side = get_B(*this, basis);
for (unsigned i = 0; i < tail_size(); i++) {
matrix<T, X>* lp = get_lp_matrix(i);
@ -676,8 +697,19 @@ dense_matrix<T, X> lu<T, X>::get_left_side(const vector<unsigned>& basis) {
}
return left_side;
}
template <typename T, typename X>
dense_matrix<T, X> lu<T, X>::get_right_side() {
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> lu<M>::get_left_side() {
dense_matrix<T, X> left_side = get_B(*this);
for (unsigned i = 0; i < tail_size(); i++) {
matrix<T, X>* lp = get_lp_matrix(i);
lp->set_number_of_rows(m_dim);
lp->set_number_of_columns(m_dim);
left_side = ((*lp) * left_side);
}
return left_side;
}
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> lu<M>::get_right_side() {
auto ret = U() * R();
ret = Q() * ret;
return ret;
@ -685,8 +717,8 @@ dense_matrix<T, X> lu<T, X>::get_right_side() {
#endif
// needed for debugging purposes
template <typename T, typename X>
void lu<T, X>::copy_w(T *buffer, indexed_vector<T> & w) {
template <typename M>
void lu<M>::copy_w(T *buffer, indexed_vector<T> & w) {
unsigned i = m_dim;
while (i--) {
buffer[i] = w[i];
@ -694,15 +726,15 @@ void lu<T, X>::copy_w(T *buffer, indexed_vector<T> & w) {
}
// needed for debugging purposes
template <typename T, typename X>
void lu<T, X>::restore_w(T *buffer, indexed_vector<T> & w) {
template <typename M>
void lu<M>::restore_w(T *buffer, indexed_vector<T> & w) {
unsigned i = m_dim;
while (i--) {
w[i] = buffer[i];
}
}
template <typename T, typename X>
bool lu<T, X>::all_columns_and_rows_are_active() {
template <typename M>
bool lu<M>::all_columns_and_rows_are_active() {
unsigned i = m_dim;
while (i--) {
lp_assert(m_U.col_is_active(i));
@ -710,8 +742,8 @@ bool lu<T, X>::all_columns_and_rows_are_active() {
}
return true;
}
template <typename T, typename X>
bool lu<T, X>::too_dense(unsigned j) const {
template <typename M>
bool lu<M>::too_dense(unsigned j) const {
unsigned r = m_dim - j;
if (r < 5)
return false;
@ -720,8 +752,8 @@ bool lu<T, X>::too_dense(unsigned j) const {
// return r * r * m_settings.density_threshold <= m_U.get_number_of_nonzeroes_below_row(j);
return r * r * m_settings.density_threshold <= m_U.get_n_of_active_elems();
}
template <typename T, typename X>
void lu<T, X>::pivot_in_dense_mode(unsigned i) {
template <typename M>
void lu<M>::pivot_in_dense_mode(unsigned i) {
int j = m_dense_LU->find_pivot_column_in_row(i);
if (j == -1) {
m_failure = true;
@ -733,8 +765,8 @@ void lu<T, X>::pivot_in_dense_mode(unsigned i) {
}
m_dense_LU->pivot(i, m_settings);
}
template <typename T, typename X>
void lu<T, X>::create_initial_factorization(){
template <typename M>
void lu<M>::create_initial_factorization(){
m_U.prepare_for_factorization();
unsigned j;
for (j = 0; j < m_dim; j++) {
@ -771,8 +803,8 @@ void lu<T, X>::create_initial_factorization(){
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
}
template <typename T, typename X>
void lu<T, X>::calculate_r_wave_and_update_U(unsigned bump_start, unsigned bump_end, permutation_matrix<T, X> & r_wave) {
template <typename M>
void lu<M>::calculate_r_wave_and_update_U(unsigned bump_start, unsigned bump_end, permutation_matrix<T, X> & r_wave) {
if (bump_start > bump_end) {
set_status(LU_status::Degenerated);
return;
@ -790,8 +822,8 @@ void lu<T, X>::calculate_r_wave_and_update_U(unsigned bump_start, unsigned bump_
m_U.multiply_from_right(r_wave);
m_U.multiply_from_left_with_reverse(r_wave);
}
template <typename T, typename X>
void lu<T, X>::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) {
template <typename M>
void lu<M>::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) {
vector<indexed_value<T>> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump));
for (auto & iv : last_row_vec) {
if (is_zero(iv.m_value)) continue;
@ -805,8 +837,8 @@ void lu<T, X>::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) {
}
}
template <typename T, typename X>
void lu<T, X>::pivot_and_solve_the_system(unsigned replaced_column, unsigned lowest_row_of_the_bump) {
template <typename M>
void lu<M>::pivot_and_solve_the_system(unsigned replaced_column, unsigned lowest_row_of_the_bump) {
// we have the system right side at m_row_eta_work_vector now
// solve the system column wise
for (unsigned j = replaced_column; j < lowest_row_of_the_bump; j++) {
@ -846,8 +878,8 @@ void lu<T, X>::pivot_and_solve_the_system(unsigned replaced_column, unsigned low
}
// see Achim Koberstein's thesis page 58, but here we solve the system and pivot to the last
// row at the same time
template <typename T, typename X>
row_eta_matrix<T, X> *lu<T, X>::get_row_eta_matrix_and_set_row_vector(unsigned replaced_column, unsigned lowest_row_of_the_bump, const T & pivot_elem_for_checking) {
template <typename M>
row_eta_matrix<typename M::coefftype, typename M::argtype> *lu<M>::get_row_eta_matrix_and_set_row_vector(unsigned replaced_column, unsigned lowest_row_of_the_bump, const T & pivot_elem_for_checking) {
if (replaced_column == lowest_row_of_the_bump) return nullptr;
scan_last_row_to_work_vector(lowest_row_of_the_bump);
pivot_and_solve_the_system(replaced_column, lowest_row_of_the_bump);
@ -861,9 +893,9 @@ row_eta_matrix<T, X> *lu<T, X>::get_row_eta_matrix_and_set_row_vector(unsigned r
}
}
#ifdef Z3DEBUG
auto ret = new row_eta_matrix<T, X>(replaced_column, lowest_row_of_the_bump, m_dim);
auto ret = new row_eta_matrix<typename M::coefftype, typename M::argtype>(replaced_column, lowest_row_of_the_bump, m_dim);
#else
auto ret = new row_eta_matrix<T, X>(replaced_column, lowest_row_of_the_bump);
auto ret = new row_eta_matrix<typename M::coefftype, typename M::argtype>(replaced_column, lowest_row_of_the_bump);
#endif
for (auto j : m_row_eta_work_vector.m_index) {
@ -880,8 +912,8 @@ row_eta_matrix<T, X> *lu<T, X>::get_row_eta_matrix_and_set_row_vector(unsigned r
return ret;
}
template <typename T, typename X>
void lu<T, X>::replace_column(T pivot_elem_for_checking, indexed_vector<T> & w, unsigned leaving_column_of_U){
template <typename M>
void lu<M>::replace_column(T pivot_elem_for_checking, indexed_vector<T> & w, unsigned leaving_column_of_U){
m_refactor_counter++;
unsigned replaced_column = transform_U_to_V_by_replacing_column( w, leaving_column_of_U);
unsigned lowest_row_of_the_bump = m_U.lowest_row_in_column(replaced_column);
@ -903,8 +935,8 @@ void lu<T, X>::replace_column(T pivot_elem_for_checking, indexed_vector<T> & w,
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
// lp_assert(w.is_OK() && m_row_eta_work_vector.is_OK());
}
template <typename T, typename X>
void lu<T, X>::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned lowest_row_of_the_bump){
template <typename M>
void lu<M>::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned lowest_row_of_the_bump){
T diagonal_elem;
if (replaced_column < lowest_row_of_the_bump) {
diagonal_elem = m_row_eta_work_vector[lowest_row_of_the_bump];
@ -922,8 +954,8 @@ void lu<T, X>::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned
// lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings));
}
template <typename T, typename X>
void lu<T, X>::calculate_Lwave_Pwave_for_last_row(unsigned lowest_row_of_the_bump, T diagonal_element) {
template <typename M>
void lu<M>::calculate_Lwave_Pwave_for_last_row(unsigned lowest_row_of_the_bump, T diagonal_element) {
auto l = new one_elem_on_diag<T, X>(lowest_row_of_the_bump, diagonal_element);
#ifdef Z3DEBUG
l->set_number_of_columns(m_dim);
@ -933,26 +965,35 @@ void lu<T, X>::calculate_Lwave_Pwave_for_last_row(unsigned lowest_row_of_the_bum
l->conjugate_by_permutation(m_Q);
}
template <typename T, typename X>
void init_factorization(lu<T, X>* & factorization, static_matrix<T, X> & m_A, vector<unsigned> & m_basis, lp_settings &m_settings) {
template <typename M>
void init_factorization(lu<M>* & factorization, M & m_A, vector<unsigned> & m_basis, lp_settings &m_settings) {
if (factorization != nullptr)
delete factorization;
factorization = new lu<T, X>(m_A, m_basis, m_settings);
factorization = new lu<M>(m_A, m_basis, m_settings);
// if (factorization->get_status() != LU_status::OK)
// LP_OUT(m_settings, "failing in init_factorization" << std::endl);
}
#ifdef Z3DEBUG
template <typename T, typename X>
dense_matrix<T, X> get_B(lu<T, X>& f, const vector<unsigned>& basis) {
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> get_B(lu<M>& f, const vector<unsigned>& basis) {
lp_assert(basis.size() == f.dimension());
lp_assert(basis.size() == f.m_U.dimension());
dense_matrix<T, X> B(f.dimension(), f.dimension());
dense_matrix<typename M::coefftype, typename M::argtype> B(f.dimension(), f.dimension());
for (unsigned i = 0; i < f.dimension(); i++)
for (unsigned j = 0; j < f.dimension(); j++)
B.set_elem(i, j, f.B_(i, j, basis));
return B;
}
template <typename M>
dense_matrix<typename M::coefftype, typename M::argtype> get_B(lu<M>& f) {
dense_matrix<typename M::coefftype, typename M::argtype> B(f.dimension(), f.dimension());
for (unsigned i = 0; i < f.dimension(); i++)
for (unsigned j = 0; j < f.dimension(); j++)
B.set_elem(i, j, f.m_A[i][j]);
return B;
}
#endif
}

View file

@ -49,11 +49,25 @@ void apply_to_vector(matrix<T, X> & m, T * w);
unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A);
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out);
void print_string_matrix(vector<vector<std::string>> & A);
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out, unsigned blanks = 0);
void print_string_matrix(vector<vector<std::string>> & A, std::ostream &, unsigned blanks_in_front = 0);
template <typename T, typename X>
void print_matrix(matrix<T, X> const * m, std::ostream & out);
template <typename T>
void print_matrix(const vector<vector<T>> & A, std::ostream & out, unsigned blanks_in_front = 0) {
vector<vector<std::string>> s(A.size());
for (unsigned i = 0; i < A.size(); i++) {
for (const auto & v : A[i]) {
s[i].push_back(T_to_string(v));
}
}
print_string_matrix(s, out, blanks_in_front);
}
}
#endif

View file

@ -82,9 +82,11 @@ unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A) {
return r;
}
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out) {
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out, unsigned blanks_in_front) {
for (unsigned i = 0; i < A.size(); i++) {
for (unsigned j = 0; j < static_cast<unsigned>(A[i].size()); j++) {
if (i != 0 && j == 0)
print_blanks(blanks_in_front, out);
print_blanks(ws[j] - static_cast<unsigned>(A[i][j].size()), out);
out << A[i][j] << " ";
}
@ -92,7 +94,7 @@ void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned>
}
}
void print_string_matrix(vector<vector<std::string>> & A, std::ostream & out) {
void print_string_matrix(vector<vector<std::string>> & A, std::ostream & out, unsigned blanks_in_front) {
vector<unsigned> widths;
if (A.size() > 0)
@ -100,10 +102,23 @@ void print_string_matrix(vector<vector<std::string>> & A, std::ostream & out) {
widths.push_back(get_width_of_column(j, A));
}
print_matrix_with_widths(A, widths, out);
print_matrix_with_widths(A, widths, out, blanks_in_front);
out << std::endl;
}
template <typename T>
void print_matrix(vector<vector<T>> & A, std::ostream & out, unsigned blanks_in_front = 0) {
vector<vector<std::string>> s(A.size());
for (unsigned i = 0; i < A.size(); i++) {
for (const auto & v : A[i]) {
s[i].push_back(T_to_string(v));
}
}
print_string_matrix(s, out, blanks_in_front);
}
template <typename T, typename X>
void print_matrix(matrix<T, X> const * m, std::ostream & out) {
vector<vector<std::string>> A(m->row_count());

View file

@ -132,8 +132,6 @@ class permutation_matrix : public tail_matrix<T, X> {
unsigned size() const { return static_cast<unsigned>(m_rev.size()); }
unsigned * values() const { return m_permutation.c_ptr(); }
void resize(unsigned size) {
unsigned old_size = m_permutation.size();
m_permutation.resize(size);

View file

@ -1,116 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#include <memory>
#include "util/vector.h"
#include "util/lp/lp_settings.h"
#include "util/lp/lu.h"
#include "util/lp/sparse_matrix_def.h"
#include "util/lp/dense_matrix.h"
namespace lp {
template double sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const;
template void sparse_matrix<double, double>::add_new_element(unsigned int, unsigned int, const double&);
template void sparse_matrix<double, double>::divide_row_by_constant(unsigned int, const double&, lp_settings&);
template bool sparse_matrix<double, double>::fill_eta_matrix(unsigned int, eta_matrix<double, double>**);
template const double & sparse_matrix<double, double>::get(unsigned int, unsigned int) const;
template unsigned sparse_matrix<double, double>::get_number_of_nonzeroes() const;
template bool sparse_matrix<double, double>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned sparse_matrix<double, double>::lowest_row_in_column(unsigned int);
template bool sparse_matrix<double, double>::pivot_row_to_row(unsigned int, const double&, unsigned int, lp_settings&);
template bool sparse_matrix<double, double>::pivot_with_eta(unsigned int, eta_matrix<double, double>*, lp_settings&);
template void sparse_matrix<double, double>::prepare_for_factorization();
template void sparse_matrix<double, double>::remove_element(vector<indexed_value<double> >&, indexed_value<double>&);
template void sparse_matrix<double, double>::replace_column(unsigned int, indexed_vector<double>&, lp_settings&);
template void sparse_matrix<double, double>::set(unsigned int, unsigned int, double);
template void sparse_matrix<double, double>::set_max_in_row(vector<indexed_value<double> >&);
template bool sparse_matrix<double, double>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<double>&, lp_settings&);
template bool sparse_matrix<double, double>::shorten_active_matrix(unsigned int, eta_matrix<double, double>*);
template void sparse_matrix<double, double>::solve_y_U(vector<double>&) const;
template sparse_matrix<double, double>::sparse_matrix(static_matrix<double, double> const&, vector<unsigned int>&);
template sparse_matrix<double, double>::sparse_matrix(unsigned int);
template void sparse_matrix<mpq, mpq>::add_new_element(unsigned int, unsigned int, const mpq&);
template void sparse_matrix<mpq, mpq>::divide_row_by_constant(unsigned int, const mpq&, lp_settings&);
template bool sparse_matrix<mpq, mpq>::fill_eta_matrix(unsigned int, eta_matrix<mpq, mpq>**);
template mpq const & sparse_matrix<mpq, mpq>::get(unsigned int, unsigned int) const;
template unsigned sparse_matrix<mpq, mpq>::get_number_of_nonzeroes() const;
template bool sparse_matrix<mpq, mpq>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned sparse_matrix<mpq, mpq>::lowest_row_in_column(unsigned int);
template bool sparse_matrix<mpq, mpq>::pivot_with_eta(unsigned int, eta_matrix<mpq, mpq>*, lp_settings&);
template void sparse_matrix<mpq, mpq>::prepare_for_factorization();
template void sparse_matrix<mpq, mpq>::remove_element(vector<indexed_value<mpq>> &, indexed_value<mpq>&);
template void sparse_matrix<mpq, mpq>::replace_column(unsigned int, indexed_vector<mpq>&, lp_settings&);
template void sparse_matrix<mpq, mpq>::set_max_in_row(vector<indexed_value<mpq>>&);
template bool sparse_matrix<mpq, mpq>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<mpq>&, lp_settings&);
template bool sparse_matrix<mpq, mpq>::shorten_active_matrix(unsigned int, eta_matrix<mpq, mpq>*);
template void sparse_matrix<mpq, mpq>::solve_y_U(vector<mpq>&) const;
template sparse_matrix<mpq, mpq>::sparse_matrix(static_matrix<mpq, mpq> const&, vector<unsigned int>&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::add_new_element(unsigned int, unsigned int, const mpq&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::divide_row_by_constant(unsigned int, const mpq&, lp_settings&);
template bool sparse_matrix<mpq, numeric_pair<mpq>>::fill_eta_matrix(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >**);
template const mpq & sparse_matrix<mpq, numeric_pair<mpq>>::get(unsigned int, unsigned int) const;
template unsigned sparse_matrix<mpq, numeric_pair<mpq>>::get_number_of_nonzeroes() const;
template bool sparse_matrix<mpq, numeric_pair<mpq>>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned sparse_matrix<mpq, numeric_pair<mpq>>::lowest_row_in_column(unsigned int);
template bool sparse_matrix<mpq, numeric_pair<mpq>>::pivot_with_eta(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >*, lp_settings&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::prepare_for_factorization();
template void sparse_matrix<mpq, numeric_pair<mpq>>::remove_element(vector<indexed_value<mpq>>&, indexed_value<mpq>&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::replace_column(unsigned int, indexed_vector<mpq>&, lp_settings&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::set_max_in_row(vector<indexed_value<mpq>>&);
template bool sparse_matrix<mpq, numeric_pair<mpq>>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<mpq>&, lp_settings&);
template bool sparse_matrix<mpq, numeric_pair<mpq>>::shorten_active_matrix(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >*);
template void sparse_matrix<mpq, numeric_pair<mpq>>::solve_y_U(vector<mpq>&) const;
template sparse_matrix<mpq, numeric_pair<mpq>>::sparse_matrix(static_matrix<mpq, numeric_pair<mpq> > const&, vector<unsigned int>&);
template void sparse_matrix<double, double>::double_solve_U_y<double>(indexed_vector<double>&, const lp_settings &);
template void sparse_matrix<mpq, mpq>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
template void sparse_matrix<mpq, numeric_pair<mpq>>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
template void sparse_matrix<mpq, numeric_pair<mpq> >::double_solve_U_y<numeric_pair<mpq> >(indexed_vector<numeric_pair<mpq>>&, const lp_settings&);
template void lp::sparse_matrix<double, double>::solve_U_y_indexed_only<double>(lp::indexed_vector<double>&, const lp_settings&, vector<unsigned> &);
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_U_y_indexed_only<lp::mpq>(lp::indexed_vector<lp::mpq>&, const lp_settings &, vector<unsigned> &);
#ifdef Z3DEBUG
template bool sparse_matrix<double, double>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
template bool sparse_matrix<mpq, mpq>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
template bool sparse_matrix<mpq, numeric_pair<mpq> >::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
#endif
}
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y_indexed_only<lp::mpq>(lp::indexed_vector<lp::mpq>&, const lp_settings &, vector<unsigned> &);
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_U_y<lp::mpq>(vector<lp::mpq>&);
template void lp::sparse_matrix<lp::mpq, lp::mpq>::double_solve_U_y<lp::mpq>(vector<lp::mpq >&);
template void lp::sparse_matrix<double, double>::solve_U_y<double>(vector<double>&);
template void lp::sparse_matrix<double, double>::double_solve_U_y<double>(vector<double>&);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y<lp::numeric_pair<lp::mpq> >(vector<lp::numeric_pair<lp::mpq> >&);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::double_solve_U_y<lp::numeric_pair<lp::mpq> >(vector<lp::numeric_pair<lp::mpq> >&);
template void lp::sparse_matrix<double, double>::find_error_in_solution_U_y_indexed<double>(lp::indexed_vector<double>&, lp::indexed_vector<double>&, const vector<unsigned> &);
template double lp::sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, lp::indexed_vector<double> const&) const;
template void lp::sparse_matrix<lp::mpq, lp::mpq>::find_error_in_solution_U_y_indexed<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&, const vector<unsigned> &);
template lp::mpq lp::sparse_matrix<lp::mpq, lp::mpq>::dot_product_with_row<lp::mpq>(unsigned int, lp::indexed_vector<lp::mpq> const&) const;
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::find_error_in_solution_U_y_indexed<lp::mpq>(lp::indexed_vector<lp::mpq>&, lp::indexed_vector<lp::mpq>&, const vector<unsigned> &);
template lp::mpq lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dot_product_with_row<lp::mpq>(unsigned int, lp::indexed_vector<lp::mpq> const&) const;
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::find_error_in_solution_U_y_indexed<lp::numeric_pair<lp::mpq> >(lp::indexed_vector<lp::numeric_pair<lp::mpq> >&, lp::indexed_vector<lp::numeric_pair<lp::mpq> >&, const vector<unsigned> &);
template lp::numeric_pair<lp::mpq> lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dot_product_with_row<lp::numeric_pair<lp::mpq> >(unsigned int, lp::indexed_vector<lp::numeric_pair<lp::mpq> > const&) const;
template void lp::sparse_matrix<lp::mpq, lp::mpq>::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_U_y<lp::mpq>(vector<lp::mpq >&);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::double_solve_U_y<lp::mpq>(vector<lp::mpq >&);
template void lp::sparse_matrix< lp::mpq,lp::numeric_pair< lp::mpq> >::set(unsigned int,unsigned int, lp::mpq);
template void lp::sparse_matrix<double, double>::solve_y_U_indexed(lp::indexed_vector<double>&, const lp_settings & );
template void lp::sparse_matrix<lp::mpq, lp::mpq>::solve_y_U_indexed(lp::indexed_vector<lp::mpq>&, const lp_settings &);
template void lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::solve_y_U_indexed(lp::indexed_vector<lp::mpq>&, const lp_settings &);

View file

@ -20,14 +20,14 @@ Revision History:
#include <memory>
#include "util/vector.h"
#include "util/lp/square_dense_submatrix_def.h"
template void lp::square_dense_submatrix<double, double>::init(lp::sparse_matrix<double, double>*, unsigned int);
template lp::square_dense_submatrix<double, double>::square_dense_submatrix(lp::sparse_matrix<double, double>*, unsigned int);
template void lp::square_dense_submatrix<double, double>::init(lp::square_sparse_matrix<double, double>*, unsigned int);
template lp::square_dense_submatrix<double, double>::square_dense_submatrix(lp::square_sparse_matrix<double, double>*, unsigned int);
template void lp::square_dense_submatrix<double, double>::update_parent_matrix(lp::lp_settings&);
template bool lp::square_dense_submatrix<double, double>::is_L_matrix() const;
template void lp::square_dense_submatrix<double, double>::conjugate_by_permutation(lp::permutation_matrix<double, double>&);
template int lp::square_dense_submatrix<double, double>::find_pivot_column_in_row(unsigned int) const;
template void lp::square_dense_submatrix<double, double>::pivot(unsigned int, lp::lp_settings&);
template lp::square_dense_submatrix<lp::mpq, lp::numeric_pair<lp::mpq> >::square_dense_submatrix(lp::sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >*, unsigned int);
template lp::square_dense_submatrix<lp::mpq, lp::numeric_pair<lp::mpq> >::square_dense_submatrix(lp::square_sparse_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >*, unsigned int);
template void lp::square_dense_submatrix<lp::mpq, lp::numeric_pair<lp::mpq> >::update_parent_matrix(lp::lp_settings&);
template bool lp::square_dense_submatrix<lp::mpq, lp::numeric_pair<lp::mpq> >::is_L_matrix() const;
template void lp::square_dense_submatrix<lp::mpq, lp::numeric_pair<lp::mpq> >::conjugate_by_permutation(lp::permutation_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
@ -40,7 +40,7 @@ template void lp::square_dense_submatrix<double, double>::apply_from_right(vecto
template void lp::square_dense_submatrix<double, double>::apply_from_left_local<double>(lp::indexed_vector<double>&, lp::lp_settings&);
template void lp::square_dense_submatrix<double, double>::apply_from_left_to_vector<double>(vector<double>&);
template lp::square_dense_submatrix<lp::mpq, lp::mpq>::square_dense_submatrix(lp::sparse_matrix<lp::mpq, lp::mpq>*, unsigned int);
template lp::square_dense_submatrix<lp::mpq, lp::mpq>::square_dense_submatrix(lp::square_sparse_matrix<lp::mpq, lp::mpq>*, unsigned int);
template void lp::square_dense_submatrix<lp::mpq, lp::mpq>::update_parent_matrix(lp::lp_settings&);
template bool lp::square_dense_submatrix<lp::mpq, lp::mpq>::is_L_matrix() const;
template void lp::square_dense_submatrix<lp::mpq, lp::mpq>::conjugate_by_permutation(lp::permutation_matrix<lp::mpq, lp::mpq>&);

View file

@ -34,7 +34,7 @@ Revision History:
#include "util/lp/lp_settings.h"
#include "util/lp/eta_matrix.h"
#include "util/lp/binary_heap_upair_queue.h"
#include "util/lp/sparse_matrix.h"
#include "util/lp/square_sparse_matrix.h"
namespace lp {
template <typename T, typename X>
class square_dense_submatrix : public tail_matrix<T, X> {
@ -57,7 +57,7 @@ public:
unsigned m_index_start;
unsigned m_dim;
vector<T> m_v;
sparse_matrix<T, X> * m_parent;
square_sparse_matrix<T, X> * m_parent;
permutation_matrix<T, X> m_row_permutation;
indexed_vector<T> m_work_vector;
public:
@ -66,9 +66,9 @@ public:
square_dense_submatrix() {}
square_dense_submatrix (sparse_matrix<T, X> *parent_matrix, unsigned index_start);
square_dense_submatrix (square_sparse_matrix<T, X> *parent_matrix, unsigned index_start);
void init(sparse_matrix<T, X> *parent_matrix, unsigned index_start);
void init(square_sparse_matrix<T, X> *parent_matrix, unsigned index_start);
bool is_dense() const override { return true; }

View file

@ -21,7 +21,7 @@ Revision History:
#include "util/lp/square_dense_submatrix.h"
namespace lp {
template <typename T, typename X>
square_dense_submatrix<T, X>::square_dense_submatrix (sparse_matrix<T, X> *parent_matrix, unsigned index_start) :
square_dense_submatrix<T, X>::square_dense_submatrix (square_sparse_matrix<T, X> *parent_matrix, unsigned index_start) :
m_index_start(index_start),
m_dim(parent_matrix->dimension() - index_start),
m_v(m_dim * m_dim),
@ -40,7 +40,7 @@ square_dense_submatrix<T, X>::square_dense_submatrix (sparse_matrix<T, X> *paren
}
}
template <typename T, typename X> void square_dense_submatrix<T, X>::init(sparse_matrix<T, X> *parent_matrix, unsigned index_start) {
template <typename T, typename X> void square_dense_submatrix<T, X>::init(square_sparse_matrix<T, X> *parent_matrix, unsigned index_start) {
m_index_start = index_start;
m_dim = parent_matrix->dimension() - index_start;
m_v.resize(m_dim * m_dim);

View file

@ -0,0 +1,119 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#include <memory>
#include "util/vector.h"
#include "util/lp/lp_settings.h"
#include "util/lp/lu.h"
#include "util/lp/square_sparse_matrix_def.h"
#include "util/lp/dense_matrix.h"
namespace lp {
template double square_sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, vector<double> const&) const;
template void square_sparse_matrix<double, double>::add_new_element(unsigned int, unsigned int, const double&);
template void square_sparse_matrix<double, double>::divide_row_by_constant(unsigned int, const double&, lp_settings&);
template bool square_sparse_matrix<double, double>::fill_eta_matrix(unsigned int, eta_matrix<double, double>**);
template const double & square_sparse_matrix<double, double>::get(unsigned int, unsigned int) const;
template unsigned square_sparse_matrix<double, double>::get_number_of_nonzeroes() const;
template bool square_sparse_matrix<double, double>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned square_sparse_matrix<double, double>::lowest_row_in_column(unsigned int);
template bool square_sparse_matrix<double, double>::pivot_row_to_row(unsigned int, const double&, unsigned int, lp_settings&);
template bool square_sparse_matrix<double, double>::pivot_with_eta(unsigned int, eta_matrix<double, double>*, lp_settings&);
template void square_sparse_matrix<double, double>::prepare_for_factorization();
template void square_sparse_matrix<double, double>::remove_element(vector<indexed_value<double> >&, indexed_value<double>&);
template void square_sparse_matrix<double, double>::replace_column(unsigned int, indexed_vector<double>&, lp_settings&);
template void square_sparse_matrix<double, double>::set(unsigned int, unsigned int, double);
template void square_sparse_matrix<double, double>::set_max_in_row(vector<indexed_value<double> >&);
template bool square_sparse_matrix<double, double>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<double>&, lp_settings&);
template bool square_sparse_matrix<double, double>::shorten_active_matrix(unsigned int, eta_matrix<double, double>*);
template void square_sparse_matrix<double, double>::solve_y_U(vector<double>&) const;
template square_sparse_matrix<double, double>::square_sparse_matrix(unsigned int, unsigned);
template void square_sparse_matrix<mpq, mpq>::add_new_element(unsigned int, unsigned int, const mpq&);
template void square_sparse_matrix<mpq, mpq>::divide_row_by_constant(unsigned int, const mpq&, lp_settings&);
template bool square_sparse_matrix<mpq, mpq>::fill_eta_matrix(unsigned int, eta_matrix<mpq, mpq>**);
template mpq const & square_sparse_matrix<mpq, mpq>::get(unsigned int, unsigned int) const;
template unsigned square_sparse_matrix<mpq, mpq>::get_number_of_nonzeroes() const;
template bool square_sparse_matrix<mpq, mpq>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned square_sparse_matrix<mpq, mpq>::lowest_row_in_column(unsigned int);
template bool square_sparse_matrix<mpq, mpq>::pivot_with_eta(unsigned int, eta_matrix<mpq, mpq>*, lp_settings&);
template void square_sparse_matrix<mpq, mpq>::prepare_for_factorization();
template void square_sparse_matrix<mpq, mpq>::remove_element(vector<indexed_value<mpq>> &, indexed_value<mpq>&);
template void square_sparse_matrix<mpq, mpq>::replace_column(unsigned int, indexed_vector<mpq>&, lp_settings&);
template void square_sparse_matrix<mpq, mpq>::set_max_in_row(vector<indexed_value<mpq>>&);
template bool square_sparse_matrix<mpq, mpq>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<mpq>&, lp_settings&);
template bool square_sparse_matrix<mpq, mpq>::shorten_active_matrix(unsigned int, eta_matrix<mpq, mpq>*);
template void square_sparse_matrix<mpq, mpq>::solve_y_U(vector<mpq>&) const;
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::add_new_element(unsigned int, unsigned int, const mpq&);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::divide_row_by_constant(unsigned int, const mpq&, lp_settings&);
template bool square_sparse_matrix<mpq, numeric_pair<mpq>>::fill_eta_matrix(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >**);
template const mpq & square_sparse_matrix<mpq, numeric_pair<mpq>>::get(unsigned int, unsigned int) const;
template unsigned square_sparse_matrix<mpq, numeric_pair<mpq>>::get_number_of_nonzeroes() const;
template bool square_sparse_matrix<mpq, numeric_pair<mpq>>::get_pivot_for_column(unsigned int&, unsigned int&, int, unsigned int);
template unsigned square_sparse_matrix<mpq, numeric_pair<mpq>>::lowest_row_in_column(unsigned int);
template bool square_sparse_matrix<mpq, numeric_pair<mpq>>::pivot_with_eta(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >*, lp_settings&);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::prepare_for_factorization();
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::remove_element(vector<indexed_value<mpq>>&, indexed_value<mpq>&);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::replace_column(unsigned int, indexed_vector<mpq>&, lp_settings&);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::set_max_in_row(vector<indexed_value<mpq>>&);
template bool square_sparse_matrix<mpq, numeric_pair<mpq>>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector<mpq>&, lp_settings&);
template bool square_sparse_matrix<mpq, numeric_pair<mpq>>::shorten_active_matrix(unsigned int, eta_matrix<mpq, numeric_pair<mpq> >*);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::solve_y_U(vector<mpq>&) const;
template void square_sparse_matrix<double, double>::double_solve_U_y<double>(indexed_vector<double>&, const lp_settings &);
template void square_sparse_matrix<mpq, mpq>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
template void square_sparse_matrix<mpq, numeric_pair<mpq>>::double_solve_U_y<mpq>(indexed_vector<mpq>&, const lp_settings&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::double_solve_U_y<numeric_pair<mpq> >(indexed_vector<numeric_pair<mpq>>&, const lp_settings&);
template void square_sparse_matrix<double, double>::solve_U_y_indexed_only<double>(indexed_vector<double>&, const lp_settings&, vector<unsigned> &);
template void square_sparse_matrix<mpq, mpq>::solve_U_y_indexed_only<mpq>(indexed_vector<mpq>&, const lp_settings &, vector<unsigned> &);
#ifdef Z3DEBUG
template bool square_sparse_matrix<double, double>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
template bool square_sparse_matrix<mpq, mpq>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
template bool square_sparse_matrix<mpq, numeric_pair<mpq> >::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const;
#endif
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::solve_U_y_indexed_only<mpq>(indexed_vector<mpq>&, const lp_settings &, vector<unsigned> &);
template void square_sparse_matrix<mpq, mpq>::solve_U_y<mpq>(vector<mpq>&);
template void square_sparse_matrix<mpq, mpq>::double_solve_U_y<mpq>(vector<mpq >&);
template void square_sparse_matrix<double, double>::solve_U_y<double>(vector<double>&);
template void square_sparse_matrix<double, double>::double_solve_U_y<double>(vector<double>&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::solve_U_y<numeric_pair<mpq> >(vector<numeric_pair<mpq> >&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::double_solve_U_y<numeric_pair<mpq> >(vector<numeric_pair<mpq> >&);
template void square_sparse_matrix<double, double>::find_error_in_solution_U_y_indexed<double>(indexed_vector<double>&, indexed_vector<double>&, const vector<unsigned> &);
template double square_sparse_matrix<double, double>::dot_product_with_row<double>(unsigned int, indexed_vector<double> const&) const;
template void square_sparse_matrix<mpq, mpq>::find_error_in_solution_U_y_indexed<mpq>(indexed_vector<mpq>&, indexed_vector<mpq>&, const vector<unsigned> &);
template mpq square_sparse_matrix<mpq, mpq>::dot_product_with_row<mpq>(unsigned int, indexed_vector<mpq> const&) const;
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::find_error_in_solution_U_y_indexed<mpq>(indexed_vector<mpq>&, indexed_vector<mpq>&, const vector<unsigned> &);
template mpq square_sparse_matrix<mpq, numeric_pair<mpq> >::dot_product_with_row<mpq>(unsigned int, indexed_vector<mpq> const&) const;
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::find_error_in_solution_U_y_indexed<numeric_pair<mpq> >(indexed_vector<numeric_pair<mpq> >&, indexed_vector<numeric_pair<mpq> >&, const vector<unsigned> &);
template numeric_pair<mpq> square_sparse_matrix<mpq, numeric_pair<mpq> >::dot_product_with_row<numeric_pair<mpq> >(unsigned int, indexed_vector<numeric_pair<mpq> > const&) const;
template void square_sparse_matrix<mpq, mpq>::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::extend_and_sort_active_rows(vector<unsigned int> const&, vector<unsigned int>&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::solve_U_y<mpq>(vector<mpq >&);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::double_solve_U_y<mpq>(vector<mpq >&);
template void square_sparse_matrix< mpq,numeric_pair< mpq> >::set(unsigned int,unsigned int, mpq);
template void square_sparse_matrix<double, double>::solve_y_U_indexed(indexed_vector<double>&, const lp_settings & );
template void square_sparse_matrix<mpq, mpq>::solve_y_U_indexed(indexed_vector<mpq>&, const lp_settings &);
template void square_sparse_matrix<mpq, numeric_pair<mpq> >::solve_y_U_indexed(indexed_vector<mpq>&, const lp_settings &);
template square_sparse_matrix<double, double>::square_sparse_matrix(static_matrix<double, double> const&, vector<unsigned int, true, unsigned int>&);
template square_sparse_matrix<mpq, mpq>::square_sparse_matrix (static_matrix<mpq, mpq> const&, vector<unsigned int, true, unsigned int>&);
template square_sparse_matrix<mpq, numeric_pair<mpq> >::square_sparse_matrix(static_matrix<mpq, numeric_pair<mpq> > const&, vector<unsigned int, true, unsigned int>&);
}
template void lp::square_sparse_matrix<double, double>::copy_from_input_on_basis<lp::static_matrix<double, double> >(lp::static_matrix<double, double> const&, vector<unsigned int, true, unsigned int>&);
template void lp::square_sparse_matrix<rational, rational>::copy_from_input_on_basis<lp::static_matrix<rational, rational> >(lp::static_matrix<rational, rational> const&, vector<unsigned int, true, unsigned int>&);

View file

@ -39,7 +39,7 @@ Revision History:
namespace lp {
// it is a square matrix
template <typename T, typename X>
class sparse_matrix
class square_sparse_matrix
#ifdef Z3DEBUG
: public matrix<T, X>
#endif
@ -96,29 +96,46 @@ public:
return m_column_permutation[col];
}
void copy_column_from_static_matrix(unsigned col, static_matrix<T, X> const &A, unsigned col_index_in_the_new_matrix);
void copy_B(static_matrix<T, X> const &A, vector<unsigned> & basis);
template <typename M>
void copy_column_from_input(unsigned input_column, const M& A, unsigned j);
template <typename M>
void copy_column_from_input_with_possible_zeros(const M& A, unsigned j);
template <typename M>
void copy_from_input(const M& A);
template <typename M>
void copy_from_input_on_basis(const M& A, vector<unsigned> & basis);
public:
// constructor that copies columns of the basis from A
sparse_matrix(static_matrix<T, X> const &A, vector<unsigned> & basis);
// constructors
template <typename M>
square_sparse_matrix(const M &A, vector<unsigned>& basis);
template <typename M>
square_sparse_matrix(const M &A);
square_sparse_matrix(unsigned dim, unsigned); // the second parameter is needed to distinguish this
// constructor from the one above
class ref_matrix_element {
sparse_matrix & m_matrix;
square_sparse_matrix & m_matrix;
unsigned m_row;
unsigned m_col;
public:
ref_matrix_element(sparse_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
ref_matrix_element(square_sparse_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
ref_matrix_element & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
ref_matrix_element & operator=(ref_matrix_element const & v) { m_matrix.set(m_row, m_col, v.m_matrix.get(v.m_row, v.m_col)); return *this; }
operator T () const { return m_matrix.get(m_row, m_col); }
};
class ref_row {
sparse_matrix & m_matrix;
square_sparse_matrix & m_matrix;
unsigned m_row;
public:
ref_row(sparse_matrix & m, unsigned row) : m_matrix(m), m_row(row) {}
ref_row(square_sparse_matrix & m, unsigned row) : m_matrix(m), m_row(row) {}
ref_matrix_element operator[](unsigned col) const { return ref_matrix_element(m_matrix, m_row, col); }
};
@ -154,11 +171,6 @@ public:
return m_columns[col].m_values;
}
// constructor creating a zero matrix of dim*dim
sparse_matrix(unsigned dim);
unsigned dimension() const {return static_cast<unsigned>(m_row_permutation.size());}
#ifdef Z3DEBUG

View file

@ -19,38 +19,61 @@ Revision History:
--*/
#include "util/vector.h"
#include "util/lp/sparse_matrix.h"
#include "util/lp/square_sparse_matrix.h"
#include <set>
#include <queue>
namespace lp {
template <typename T, typename X>
void sparse_matrix<T, X>::copy_column_from_static_matrix(unsigned col, static_matrix<T, X> const &A, unsigned col_index_in_the_new_matrix) {
vector<column_cell> const & A_col_vector = A.m_columns[col];
unsigned size = static_cast<unsigned>(A_col_vector.size());
vector<indexed_value<T>> & new_column_vector = m_columns[col_index_in_the_new_matrix].m_values;
for (unsigned l = 0; l < size; l++) {
column_cell const & col_cell = A_col_vector[l];
template <typename M>
void square_sparse_matrix<T, X>::copy_column_from_input(unsigned input_column, const M& A, unsigned j) {
vector<indexed_value<T>> & new_column_vector = m_columns[j].m_values;
for (const auto & c : A.column(input_column)) {
unsigned col_offset = static_cast<unsigned>(new_column_vector.size());
vector<indexed_value<T>> & row_vector = m_rows[col_cell.m_i];
vector<indexed_value<T>> & row_vector = m_rows[c.var()];
unsigned row_offset = static_cast<unsigned>(row_vector.size());
const T & val = A.get_val(col_cell);
new_column_vector.push_back(indexed_value<T>(val, col_cell.m_i, row_offset));
row_vector.push_back(indexed_value<T>(val, col_index_in_the_new_matrix, col_offset));
new_column_vector.push_back(indexed_value<T>(c.coeff(), c.var(), row_offset));
row_vector.push_back(indexed_value<T>(c.coeff(), j, col_offset));
m_n_of_active_elems++;
}
}
template <typename T, typename X>
void sparse_matrix<T, X>::copy_B(static_matrix<T, X> const &A, vector<unsigned> & basis) {
unsigned m = A.row_count(); // this should be the size of basis
template <typename M>
void square_sparse_matrix<T, X>::copy_column_from_input_with_possible_zeros(const M& A, unsigned j) {
vector<indexed_value<T>> & new_column_vector = m_columns[j].m_values;
for (const auto & c : A.column(j)) {
if (is_zero(c.coeff()))
continue;
unsigned col_offset = static_cast<unsigned>(new_column_vector.size());
vector<indexed_value<T>> & row_vector = m_rows[c.var()];
unsigned row_offset = static_cast<unsigned>(row_vector.size());
new_column_vector.push_back(indexed_value<T>(c.coeff(), c.var(), row_offset));
row_vector.push_back(indexed_value<T>(c.coeff(), j, col_offset));
m_n_of_active_elems++;
}
}
template <typename T, typename X>
template <typename M>
void square_sparse_matrix<T, X>::copy_from_input_on_basis(const M & A, vector<unsigned> & basis) {
unsigned m = A.row_count();
for (unsigned j = m; j-- > 0;) {
copy_column_from_static_matrix(basis[j], A, j);
copy_column_from_input(basis[j], A, j);
}
}
template <typename T, typename X>
template <typename M>
void square_sparse_matrix<T, X>::copy_from_input(const M & A) {
unsigned m = A.row_count();
for (unsigned j = m; j-- > 0;) {
copy_column_from_input_with_possible_zeros(A, j);
}
}
// constructor that copies columns of the basis from A
template <typename T, typename X>
sparse_matrix<T, X>::sparse_matrix(static_matrix<T, X> const &A, vector<unsigned> & basis) :
template <typename M>
square_sparse_matrix<T, X>::square_sparse_matrix(const M &A, vector<unsigned> & basis) :
m_n_of_active_elems(0),
m_pivot_queue(A.row_count()),
m_row_permutation(A.row_count()),
@ -59,11 +82,26 @@ sparse_matrix<T, X>::sparse_matrix(static_matrix<T, X> const &A, vector<unsigned
m_processed(A.row_count()) {
init_row_headers();
init_column_headers();
copy_B(A, basis);
copy_from_input_on_basis(A, basis);
}
template <typename T, typename X>
void sparse_matrix<T, X>::set_with_no_adjusting_for_row(unsigned row, unsigned col, T val) { // should not be used in efficient code
template <typename M>
square_sparse_matrix<T, X>::square_sparse_matrix(const M &A) :
m_n_of_active_elems(0),
m_pivot_queue(A.row_count()),
m_row_permutation(A.row_count()),
m_column_permutation(A.row_count()),
m_work_pivot_vector(A.row_count(), -1),
m_processed(A.row_count()) {
init_row_headers();
init_column_headers();
copy_from_input(A);
}
template <typename T, typename X>
void square_sparse_matrix<T, X>::set_with_no_adjusting_for_row(unsigned row, unsigned col, T val) { // should not be used in efficient code
vector<indexed_value<T>> & row_vec = m_rows[row];
for (auto & iv : row_vec) {
if (iv.m_index == col) {
@ -76,7 +114,7 @@ void sparse_matrix<T, X>::set_with_no_adjusting_for_row(unsigned row, unsigned c
}
template <typename T, typename X>
void sparse_matrix<T, X>::set_with_no_adjusting_for_col(unsigned row, unsigned col, T val) { // should not be used in efficient code
void square_sparse_matrix<T, X>::set_with_no_adjusting_for_col(unsigned row, unsigned col, T val) { // should not be used in efficient code
vector<indexed_value<T>> & col_vec = m_columns[col].m_values;
for (auto & iv : col_vec) {
if (iv.m_index == row) {
@ -90,13 +128,13 @@ void sparse_matrix<T, X>::set_with_no_adjusting_for_col(unsigned row, unsigned c
template <typename T, typename X>
void sparse_matrix<T, X>::set_with_no_adjusting(unsigned row, unsigned col, T val) { // should not be used in efficient code
void square_sparse_matrix<T, X>::set_with_no_adjusting(unsigned row, unsigned col, T val) { // should not be used in efficient code
set_with_no_adjusting_for_row(row, col, val);
set_with_no_adjusting_for_col(row, col, val);
}
template <typename T, typename X>
void sparse_matrix<T, X>::set(unsigned row, unsigned col, T val) { // should not be used in efficient code
void square_sparse_matrix<T, X>::set(unsigned row, unsigned col, T val) { // should not be used in efficient code
lp_assert(row < dimension() && col < dimension());
// m_dense.set_elem(row, col, val);
row = adjust_row(row);
@ -106,7 +144,7 @@ void sparse_matrix<T, X>::set(unsigned row, unsigned col, T val) { // should not
}
template <typename T, typename X>
T const & sparse_matrix<T, X>::get_not_adjusted(unsigned row, unsigned col) const {
T const & square_sparse_matrix<T, X>::get_not_adjusted(unsigned row, unsigned col) const {
for (indexed_value<T> const & iv : m_rows[row]) {
if (iv.m_index == col) {
return iv.m_value;
@ -116,7 +154,7 @@ T const & sparse_matrix<T, X>::get_not_adjusted(unsigned row, unsigned col) cons
}
template <typename T, typename X>
T const & sparse_matrix<T, X>::get(unsigned row, unsigned col) const { // should not be used in efficient code
T const & square_sparse_matrix<T, X>::get(unsigned row, unsigned col) const { // should not be used in efficient code
row = adjust_row(row);
auto & row_chunk = m_rows[row];
col = adjust_column(col);
@ -130,7 +168,7 @@ T const & sparse_matrix<T, X>::get(unsigned row, unsigned col) const { // should
// constructor creating a zero matrix of dim*dim
template <typename T, typename X>
sparse_matrix<T, X>::sparse_matrix(unsigned dim) :
square_sparse_matrix<T, X>::square_sparse_matrix(unsigned dim, unsigned ) :
m_pivot_queue(dim), // dim will be the initial size of the queue
m_row_permutation(dim),
m_column_permutation(dim),
@ -141,21 +179,21 @@ sparse_matrix<T, X>::sparse_matrix(unsigned dim) :
}
template <typename T, typename X>
void sparse_matrix<T, X>::init_row_headers() {
void square_sparse_matrix<T, X>::init_row_headers() {
for (unsigned l = 0; l < m_row_permutation.size(); l++) {
m_rows.push_back(vector<indexed_value<T>>());
}
}
template <typename T, typename X>
void sparse_matrix<T, X>::init_column_headers() { // we alway have only square sparse_matrix
void square_sparse_matrix<T, X>::init_column_headers() { // we alway have only square square_sparse_matrix
for (unsigned l = 0; l < m_row_permutation.size(); l++) {
m_columns.push_back(col_header());
}
}
template <typename T, typename X>
unsigned sparse_matrix<T, X>::lowest_row_in_column(unsigned j) {
unsigned square_sparse_matrix<T, X>::lowest_row_in_column(unsigned j) {
auto & mc = get_column_values(adjust_column(j));
unsigned ret = 0;
for (auto & iv : mc) {
@ -168,7 +206,7 @@ unsigned sparse_matrix<T, X>::lowest_row_in_column(unsigned j) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::remove_element(vector<indexed_value<T>> & row_vals, unsigned row_offset, vector<indexed_value<T>> & column_vals, unsigned column_offset) {
void square_sparse_matrix<T, X>::remove_element(vector<indexed_value<T>> & row_vals, unsigned row_offset, vector<indexed_value<T>> & column_vals, unsigned column_offset) {
if (column_offset != column_vals.size() - 1) {
auto & column_iv = column_vals[column_offset] = column_vals.back(); // copy from the tail
column_iv_other(column_iv).m_other = column_offset;
@ -187,14 +225,14 @@ void sparse_matrix<T, X>::remove_element(vector<indexed_value<T>> & row_vals, un
}
template <typename T, typename X>
void sparse_matrix<T, X>::remove_element(vector<indexed_value<T>> & row_chunk, indexed_value<T> & row_el_iv) {
void square_sparse_matrix<T, X>::remove_element(vector<indexed_value<T>> & row_chunk, indexed_value<T> & row_el_iv) {
auto & column_chunk = get_column_values(row_el_iv.m_index);
indexed_value<T> & col_el_iv = column_chunk[row_el_iv.m_other];
remove_element(row_chunk, col_el_iv.m_other, column_chunk, row_el_iv.m_other);
}
template <typename T, typename X>
void sparse_matrix<T, X>::put_max_index_to_0(vector<indexed_value<T>> & row_vals, unsigned max_index) {
void square_sparse_matrix<T, X>::put_max_index_to_0(vector<indexed_value<T>> & row_vals, unsigned max_index) {
if (max_index == 0) return;
indexed_value<T> * max_iv = & row_vals[max_index];
indexed_value<T> * start_iv = & row_vals[0];
@ -209,7 +247,7 @@ void sparse_matrix<T, X>::put_max_index_to_0(vector<indexed_value<T>> & row_vals
}
template <typename T, typename X>
void sparse_matrix<T, X>::set_max_in_row(vector<indexed_value<T>> & row_vals) {
void square_sparse_matrix<T, X>::set_max_in_row(vector<indexed_value<T>> & row_vals) {
if (row_vals.size() == 0)
return;
T max_val = abs(row_vals[0].m_value);
@ -225,7 +263,7 @@ void sparse_matrix<T, X>::set_max_in_row(vector<indexed_value<T>> & row_vals) {
}
template <typename T, typename X>
bool sparse_matrix<T, X>::pivot_with_eta(unsigned i, eta_matrix<T, X> *eta_matrix, lp_settings & settings) {
bool square_sparse_matrix<T, X>::pivot_with_eta(unsigned i, eta_matrix<T, X> *eta_matrix, lp_settings & settings) {
const T& pivot = eta_matrix->get_diagonal_element();
for (auto & it : eta_matrix->m_column_vector.m_data) {
if (!pivot_row_to_row(i, it.second, it.first, settings)) {
@ -243,7 +281,7 @@ bool sparse_matrix<T, X>::pivot_with_eta(unsigned i, eta_matrix<T, X> *eta_matri
// returns the offset of the pivot column in the row
template <typename T, typename X>
void sparse_matrix<T, X>::scan_row_to_work_vector_and_remove_pivot_column(unsigned row, unsigned pivot_column) {
void square_sparse_matrix<T, X>::scan_row_to_work_vector_and_remove_pivot_column(unsigned row, unsigned pivot_column) {
auto & rvals = m_rows[row];
unsigned size = rvals.size();
for (unsigned j = 0; j < size; j++) {
@ -260,7 +298,7 @@ void sparse_matrix<T, X>::scan_row_to_work_vector_and_remove_pivot_column(unsign
#ifdef Z3DEBUG
template <typename T, typename X>
vector<T> sparse_matrix<T, X>::get_full_row(unsigned i) const {
vector<T> square_sparse_matrix<T, X>::get_full_row(unsigned i) const {
vector<T> r;
for (unsigned j = 0; j < column_count(); j++)
r.push_back(get(i, j));
@ -275,7 +313,7 @@ vector<T> sparse_matrix<T, X>::get_full_row(unsigned i) const {
// After pivoting the row i0 has a max abs value set correctly at the beginning of m_start,
// Returns false if the resulting row is all zeroes, and true otherwise
template <typename T, typename X>
bool sparse_matrix<T, X>::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0, lp_settings & settings ) {
bool square_sparse_matrix<T, X>::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0, lp_settings & settings ) {
lp_assert(i < dimension() && i0 < dimension());
lp_assert(i != i0);
unsigned pivot_col = adjust_column(i);
@ -334,7 +372,7 @@ bool sparse_matrix<T, X>::pivot_row_to_row(unsigned i, const T& alpha, unsigned
// set the max val as well
// returns false if the resulting row is all zeroes, and true otherwise
template <typename T, typename X>
bool sparse_matrix<T, X>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector<T> & work_vec,
bool square_sparse_matrix<T, X>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector<T> & work_vec,
lp_settings & settings) {
remove_zero_elements_and_set_data_on_existing_elements_not_adjusted(i0, work_vec, settings);
// all non-zero elements in m_work_pivot_vector are new
@ -358,7 +396,7 @@ bool sparse_matrix<T, X>::set_row_from_work_vector_and_clean_work_vector_not_adj
template <typename T, typename X>
void sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements(unsigned row) {
void square_sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements(unsigned row) {
auto & row_vals = m_rows[row];
for (unsigned k = static_cast<unsigned>(row_vals.size()); k-- > 0;) { // we cannot simply run the iterator since we are removing
// elements from row_vals
@ -377,7 +415,7 @@ void sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements
// work_vec here has not adjusted column indices
template <typename T, typename X>
void sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements_not_adjusted(unsigned row, indexed_vector<T> & work_vec, lp_settings & settings) {
void square_sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements_not_adjusted(unsigned row, indexed_vector<T> & work_vec, lp_settings & settings) {
auto & row_vals = m_rows[row];
for (unsigned k = static_cast<unsigned>(row_vals.size()); k-- > 0;) { // we cannot simply run the iterator since we are removing
// elements from row_vals
@ -398,7 +436,7 @@ void sparse_matrix<T, X>::remove_zero_elements_and_set_data_on_existing_elements
// adding delta columns at the end of the matrix
template <typename T, typename X>
void sparse_matrix<T, X>::add_columns_at_the_end(unsigned delta) {
void square_sparse_matrix<T, X>::add_columns_at_the_end(unsigned delta) {
for (unsigned i = 0; i < delta; i++) {
col_header col_head;
m_columns.push_back(col_head);
@ -407,7 +445,7 @@ void sparse_matrix<T, X>::add_columns_at_the_end(unsigned delta) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::delete_column(int i) {
void square_sparse_matrix<T, X>::delete_column(int i) {
lp_assert(i < dimension());
for (auto cell = m_columns[i].m_head; cell != nullptr;) {
auto next_cell = cell->m_down;
@ -417,7 +455,7 @@ void sparse_matrix<T, X>::delete_column(int i) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::divide_row_by_constant(unsigned i, const T & t, lp_settings & settings) {
void square_sparse_matrix<T, X>::divide_row_by_constant(unsigned i, const T & t, lp_settings & settings) {
lp_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t));
i = adjust_row(i);
for (auto & iv : m_rows[i]) {
@ -434,7 +472,7 @@ void sparse_matrix<T, X>::divide_row_by_constant(unsigned i, const T & t, lp_set
// solving x * this = y, and putting the answer into y
// the matrix here has to be upper triangular
template <typename T, typename X>
void sparse_matrix<T, X>::solve_y_U(vector<T> & y) const { // works by rows
void square_sparse_matrix<T, X>::solve_y_U(vector<T> & y) const { // works by rows
#ifdef Z3DEBUG
// T * rs = clone_vector<T>(y, dimension());
#endif
@ -464,7 +502,7 @@ void sparse_matrix<T, X>::solve_y_U(vector<T> & y) const { // works by rows
// solving x * this = y, and putting the answer into y
// the matrix here has to be upper triangular
template <typename T, typename X>
void sparse_matrix<T, X>::solve_y_U_indexed(indexed_vector<T> & y, const lp_settings & settings) {
void square_sparse_matrix<T, X>::solve_y_U_indexed(indexed_vector<T> & y, const lp_settings & settings) {
#if 0 && Z3DEBUG
vector<T> ycopy(y.m_data);
if (numeric_traits<T>::precise() == false)
@ -525,7 +563,7 @@ void sparse_matrix<T, X>::solve_y_U_indexed(indexed_vector<T> & y, const lp_sett
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::find_error_in_solution_U_y(vector<L>& y_orig, vector<L> & y) {
void square_sparse_matrix<T, X>::find_error_in_solution_U_y(vector<L>& y_orig, vector<L> & y) {
unsigned i = dimension();
while (i--) {
y_orig[i] -= dot_product_with_row(i, y);
@ -534,7 +572,7 @@ void sparse_matrix<T, X>::find_error_in_solution_U_y(vector<L>& y_orig, vector<L
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::find_error_in_solution_U_y_indexed(indexed_vector<L>& y_orig, indexed_vector<L> & y, const vector<unsigned>& sorted_active_rows) {
void square_sparse_matrix<T, X>::find_error_in_solution_U_y_indexed(indexed_vector<L>& y_orig, indexed_vector<L> & y, const vector<unsigned>& sorted_active_rows) {
for (unsigned i: sorted_active_rows)
y_orig.add_value_at_index(i, -dot_product_with_row(i, y)); // cannot round up here!!!
// y_orig can contain very small values
@ -543,7 +581,7 @@ void sparse_matrix<T, X>::find_error_in_solution_U_y_indexed(indexed_vector<L>&
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::add_delta_to_solution(const vector<L>& del, vector<L> & y) {
void square_sparse_matrix<T, X>::add_delta_to_solution(const vector<L>& del, vector<L> & y) {
unsigned i = dimension();
while (i--) {
y[i] += del[i];
@ -551,7 +589,7 @@ void sparse_matrix<T, X>::add_delta_to_solution(const vector<L>& del, vector<L>
}
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::add_delta_to_solution(const indexed_vector<L>& del, indexed_vector<L> & y) {
void square_sparse_matrix<T, X>::add_delta_to_solution(const indexed_vector<L>& del, indexed_vector<L> & y) {
// lp_assert(del.is_OK());
// lp_assert(y.is_OK());
for (auto i : del.m_index) {
@ -560,7 +598,7 @@ void sparse_matrix<T, X>::add_delta_to_solution(const indexed_vector<L>& del, in
}
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::double_solve_U_y(indexed_vector<L>& y, const lp_settings & settings){
void square_sparse_matrix<T, X>::double_solve_U_y(indexed_vector<L>& y, const lp_settings & settings){
lp_assert(y.is_OK());
indexed_vector<L> y_orig(y); // copy y aside
vector<unsigned> active_rows;
@ -582,7 +620,7 @@ void sparse_matrix<T, X>::double_solve_U_y(indexed_vector<L>& y, const lp_settin
}
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::double_solve_U_y(vector<L>& y){
void square_sparse_matrix<T, X>::double_solve_U_y(vector<L>& y){
vector<L> y_orig(y); // copy y aside
solve_U_y(y);
find_error_in_solution_U_y(y_orig, y);
@ -595,7 +633,7 @@ void sparse_matrix<T, X>::double_solve_U_y(vector<L>& y){
// the matrix here has to be upper triangular
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::solve_U_y(vector<L> & y) { // it is a column wise version
void square_sparse_matrix<T, X>::solve_U_y(vector<L> & y) { // it is a column wise version
#ifdef Z3DEBUG
// T * rs = clone_vector<T>(y, dimension());
#endif
@ -618,7 +656,7 @@ void sparse_matrix<T, X>::solve_U_y(vector<L> & y) { // it is a column wise vers
#endif
}
template <typename T, typename X>
void sparse_matrix<T, X>::process_index_recursively_for_y_U(unsigned j, vector<unsigned> & sorted_active_rows) {
void square_sparse_matrix<T, X>::process_index_recursively_for_y_U(unsigned j, vector<unsigned> & sorted_active_rows) {
lp_assert(m_processed[j] == false);
m_processed[j]=true;
auto & row = m_rows[adjust_row(j)];
@ -633,7 +671,7 @@ void sparse_matrix<T, X>::process_index_recursively_for_y_U(unsigned j, vector<u
}
template <typename T, typename X>
void sparse_matrix<T, X>::process_column_recursively(unsigned j, vector<unsigned> & sorted_active_rows) {
void square_sparse_matrix<T, X>::process_column_recursively(unsigned j, vector<unsigned> & sorted_active_rows) {
lp_assert(m_processed[j] == false);
auto & mc = m_columns[adjust_column(j)].m_values;
for (auto & iv : mc) {
@ -649,7 +687,7 @@ void sparse_matrix<T, X>::process_column_recursively(unsigned j, vector<unsigned
template <typename T, typename X>
void sparse_matrix<T, X>::create_graph_G(const vector<unsigned> & index_or_right_side, vector<unsigned> & sorted_active_rows) {
void square_sparse_matrix<T, X>::create_graph_G(const vector<unsigned> & index_or_right_side, vector<unsigned> & sorted_active_rows) {
for (auto i : index_or_right_side) {
if (m_processed[i]) continue;
process_column_recursively(i, sorted_active_rows);
@ -662,7 +700,7 @@ void sparse_matrix<T, X>::create_graph_G(const vector<unsigned> & index_or_right
template <typename T, typename X>
void sparse_matrix<T, X>::extend_and_sort_active_rows(const vector<unsigned> & index_or_right_side, vector<unsigned> & sorted_active_rows) {
void square_sparse_matrix<T, X>::extend_and_sort_active_rows(const vector<unsigned> & index_or_right_side, vector<unsigned> & sorted_active_rows) {
for (auto i : index_or_right_side) {
if (m_processed[i]) continue;
process_index_recursively_for_y_U(i, sorted_active_rows);
@ -676,7 +714,7 @@ void sparse_matrix<T, X>::extend_and_sort_active_rows(const vector<unsigned> & i
template <typename T, typename X>
template <typename L>
void sparse_matrix<T, X>::solve_U_y_indexed_only(indexed_vector<L> & y, const lp_settings & settings, vector<unsigned> & sorted_active_rows) { // it is a column wise version
void square_sparse_matrix<T, X>::solve_U_y_indexed_only(indexed_vector<L> & y, const lp_settings & settings, vector<unsigned> & sorted_active_rows) { // it is a column wise version
create_graph_G(y.m_index, sorted_active_rows);
for (auto k = sorted_active_rows.size(); k-- > 0;) {
@ -710,7 +748,7 @@ void sparse_matrix<T, X>::solve_U_y_indexed_only(indexed_vector<L> & y, const lp
template <typename T, typename X>
template <typename L>
L sparse_matrix<T, X>::dot_product_with_row (unsigned row, const vector<L> & y) const {
L square_sparse_matrix<T, X>::dot_product_with_row (unsigned row, const vector<L> & y) const {
L ret = zero_of_type<L>();
auto & mc = get_row_values(adjust_row(row));
for (auto & c : mc) {
@ -722,7 +760,7 @@ L sparse_matrix<T, X>::dot_product_with_row (unsigned row, const vector<L> & y)
template <typename T, typename X>
template <typename L>
L sparse_matrix<T, X>::dot_product_with_row (unsigned row, const indexed_vector<L> & y) const {
L square_sparse_matrix<T, X>::dot_product_with_row (unsigned row, const indexed_vector<L> & y) const {
L ret = zero_of_type<L>();
auto & mc = get_row_values(adjust_row(row));
for (auto & c : mc) {
@ -734,7 +772,7 @@ L sparse_matrix<T, X>::dot_product_with_row (unsigned row, const indexed_vector<
template <typename T, typename X>
unsigned sparse_matrix<T, X>::get_number_of_nonzeroes() const {
unsigned square_sparse_matrix<T, X>::get_number_of_nonzeroes() const {
unsigned ret = 0;
for (unsigned i = dimension(); i--; ) {
ret += number_of_non_zeroes_in_row(i);
@ -743,7 +781,7 @@ unsigned sparse_matrix<T, X>::get_number_of_nonzeroes() const {
}
template <typename T, typename X>
bool sparse_matrix<T, X>::get_non_zero_column_in_row(unsigned i, unsigned *j) const {
bool square_sparse_matrix<T, X>::get_non_zero_column_in_row(unsigned i, unsigned *j) const {
// go over the i-th row
auto & mc = get_row_values(adjust_row(i));
if (mc.size() > 0) {
@ -754,7 +792,7 @@ bool sparse_matrix<T, X>::get_non_zero_column_in_row(unsigned i, unsigned *j) co
}
template <typename T, typename X>
void sparse_matrix<T, X>::remove_element_that_is_not_in_w(vector<indexed_value<T>> & column_vals, indexed_value<T> & col_el_iv) {
void square_sparse_matrix<T, X>::remove_element_that_is_not_in_w(vector<indexed_value<T>> & column_vals, indexed_value<T> & col_el_iv) {
auto & row_chunk = m_rows[col_el_iv.m_index];
indexed_value<T> & row_el_iv = row_chunk[col_el_iv.m_other];
unsigned index_in_row = col_el_iv.m_other;
@ -767,7 +805,7 @@ void sparse_matrix<T, X>::remove_element_that_is_not_in_w(vector<indexed_value<T
// w contains the new column
// the old column inside of the matrix has not been changed yet
template <typename T, typename X>
void sparse_matrix<T, X>::remove_elements_that_are_not_in_w_and_update_common_elements(unsigned column_to_replace, indexed_vector<T> & w) {
void square_sparse_matrix<T, X>::remove_elements_that_are_not_in_w_and_update_common_elements(unsigned column_to_replace, indexed_vector<T> & w) {
// --------------------------------
// column_vals represents the old column
auto & column_vals = m_columns[column_to_replace].m_values;
@ -796,7 +834,7 @@ void sparse_matrix<T, X>::remove_elements_that_are_not_in_w_and_update_common_el
}
template <typename T, typename X>
void sparse_matrix<T, X>::add_new_element(unsigned row, unsigned col, const T& val) {
void square_sparse_matrix<T, X>::add_new_element(unsigned row, unsigned col, const T& val) {
auto & row_vals = m_rows[row];
auto & col_vals = m_columns[col].m_values;
unsigned row_el_offs = static_cast<unsigned>(row_vals.size());
@ -809,7 +847,7 @@ void sparse_matrix<T, X>::add_new_element(unsigned row, unsigned col, const T& v
// w contains the "rest" of the new column; all common elements of w and the old column has been zeroed
// the old column inside of the matrix has not been changed yet
template <typename T, typename X>
void sparse_matrix<T, X>::add_new_elements_of_w_and_clear_w(unsigned column_to_replace, indexed_vector<T> & w, lp_settings & settings) {
void square_sparse_matrix<T, X>::add_new_elements_of_w_and_clear_w(unsigned column_to_replace, indexed_vector<T> & w, lp_settings & settings) {
for (unsigned i : w.m_index) {
T w_at_i = w[i];
if (numeric_traits<T>::is_zero(w_at_i)) continue; // was dealt with already
@ -827,14 +865,14 @@ void sparse_matrix<T, X>::add_new_elements_of_w_and_clear_w(unsigned column_to_r
}
template <typename T, typename X>
void sparse_matrix<T, X>::replace_column(unsigned column_to_replace, indexed_vector<T> & w, lp_settings &settings) {
void square_sparse_matrix<T, X>::replace_column(unsigned column_to_replace, indexed_vector<T> & w, lp_settings &settings) {
column_to_replace = adjust_column(column_to_replace);
remove_elements_that_are_not_in_w_and_update_common_elements(column_to_replace, w);
add_new_elements_of_w_and_clear_w(column_to_replace, w, settings);
}
template <typename T, typename X>
unsigned sparse_matrix<T, X>::pivot_score(unsigned i, unsigned j) {
unsigned square_sparse_matrix<T, X>::pivot_score(unsigned i, unsigned j) {
// It goes like this (rnz-1)(cnz-1) is the Markovitz number, that is the max number of
// new non zeroes we can obtain after the pivoting.
// In addition we will get another cnz - 1 elements in the eta matrix created for this pivot,
@ -847,7 +885,7 @@ unsigned sparse_matrix<T, X>::pivot_score(unsigned i, unsigned j) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::enqueue_domain_into_pivot_queue() {
void square_sparse_matrix<T, X>::enqueue_domain_into_pivot_queue() {
lp_assert(m_pivot_queue.size() == 0);
for (unsigned i = 0; i < dimension(); i++) {
auto & rh = m_rows[i];
@ -860,7 +898,7 @@ void sparse_matrix<T, X>::enqueue_domain_into_pivot_queue() {
}
template <typename T, typename X>
void sparse_matrix<T, X>::set_max_in_rows() {
void square_sparse_matrix<T, X>::set_max_in_rows() {
unsigned i = dimension();
while (i--)
set_max_in_row(i);
@ -868,27 +906,27 @@ void sparse_matrix<T, X>::set_max_in_rows() {
template <typename T, typename X>
void sparse_matrix<T, X>::zero_shortened_markovitz_numbers() {
void square_sparse_matrix<T, X>::zero_shortened_markovitz_numbers() {
for (auto & ch : m_columns)
ch.zero_shortened_markovitz();
}
template <typename T, typename X>
void sparse_matrix<T, X>::prepare_for_factorization() {
void square_sparse_matrix<T, X>::prepare_for_factorization() {
zero_shortened_markovitz_numbers();
set_max_in_rows();
enqueue_domain_into_pivot_queue();
}
template <typename T, typename X>
void sparse_matrix<T, X>::recover_pivot_queue(vector<upair> & rejected_pivots) {
void square_sparse_matrix<T, X>::recover_pivot_queue(vector<upair> & rejected_pivots) {
for (auto p : rejected_pivots) {
m_pivot_queue.enqueue(p.first, p.second, pivot_score(p.first, p.second));
}
}
template <typename T, typename X>
int sparse_matrix<T, X>::elem_is_too_small(unsigned i, unsigned j, int c_partial_pivoting) {
int square_sparse_matrix<T, X>::elem_is_too_small(unsigned i, unsigned j, int c_partial_pivoting) {
auto & row_chunk = m_rows[i];
if (j == row_chunk[0].m_index) {
@ -904,7 +942,7 @@ int sparse_matrix<T, X>::elem_is_too_small(unsigned i, unsigned j, int c_partial
}
template <typename T, typename X>
bool sparse_matrix<T, X>::remove_row_from_active_pivots_and_shorten_columns(unsigned row) {
bool square_sparse_matrix<T, X>::remove_row_from_active_pivots_and_shorten_columns(unsigned row) {
unsigned arow = adjust_row(row);
for (auto & iv : m_rows[arow]) {
m_pivot_queue.remove(arow, iv.m_index);
@ -921,7 +959,7 @@ bool sparse_matrix<T, X>::remove_row_from_active_pivots_and_shorten_columns(unsi
}
template <typename T, typename X>
void sparse_matrix<T, X>::remove_pivot_column(unsigned row) {
void square_sparse_matrix<T, X>::remove_pivot_column(unsigned row) {
unsigned acol = adjust_column(row);
for (const auto & iv : m_columns[acol].m_values)
if (adjust_row_inverse(iv.m_index) >= row)
@ -929,7 +967,7 @@ void sparse_matrix<T, X>::remove_pivot_column(unsigned row) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::update_active_pivots(unsigned row) {
void square_sparse_matrix<T, X>::update_active_pivots(unsigned row) {
unsigned arow = adjust_row(row);
for (const auto & iv : m_rows[arow]) {
col_header & ch = m_columns[iv.m_index];
@ -944,7 +982,7 @@ void sparse_matrix<T, X>::update_active_pivots(unsigned row) {
}
template <typename T, typename X>
bool sparse_matrix<T, X>::shorten_active_matrix(unsigned row, eta_matrix<T, X> *eta_matrix) {
bool square_sparse_matrix<T, X>::shorten_active_matrix(unsigned row, eta_matrix<T, X> *eta_matrix) {
if (!remove_row_from_active_pivots_and_shorten_columns(row))
return false;
remove_pivot_column(row);
@ -969,7 +1007,7 @@ bool sparse_matrix<T, X>::shorten_active_matrix(unsigned row, eta_matrix<T, X> *
}
template <typename T, typename X>
unsigned sparse_matrix<T, X>::pivot_score_without_shortened_counters(unsigned i, unsigned j, unsigned k) {
unsigned square_sparse_matrix<T, X>::pivot_score_without_shortened_counters(unsigned i, unsigned j, unsigned k) {
auto &cols = m_columns[j].m_values;
unsigned cnz = cols.size();
for (auto & iv : cols) {
@ -981,7 +1019,7 @@ unsigned sparse_matrix<T, X>::pivot_score_without_shortened_counters(unsigned i,
}
#ifdef Z3DEBUG
template <typename T, typename X>
bool sparse_matrix<T, X>::can_improve_score_for_row(unsigned row, unsigned score, T const & c_partial_pivoting, unsigned k) {
bool square_sparse_matrix<T, X>::can_improve_score_for_row(unsigned row, unsigned score, T const & c_partial_pivoting, unsigned k) {
unsigned arow = adjust_row(row);
auto & row_vals = m_rows[arow].m_values;
auto & begin_iv = row_vals[0];
@ -1005,7 +1043,7 @@ bool sparse_matrix<T, X>::can_improve_score_for_row(unsigned row, unsigned score
}
template <typename T, typename X>
bool sparse_matrix<T, X>::really_best_pivot(unsigned i, unsigned j, T const & c_partial_pivoting, unsigned k) {
bool square_sparse_matrix<T, X>::really_best_pivot(unsigned i, unsigned j, T const & c_partial_pivoting, unsigned k) {
unsigned queue_pivot_score = pivot_score_without_shortened_counters(i, j, k);
for (unsigned ii = k; ii < dimension(); ii++) {
lp_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k));
@ -1013,7 +1051,7 @@ bool sparse_matrix<T, X>::really_best_pivot(unsigned i, unsigned j, T const & c_
return true;
}
template <typename T, typename X>
void sparse_matrix<T, X>::print_active_matrix(unsigned k, std::ostream & out) {
void square_sparse_matrix<T, X>::print_active_matrix(unsigned k, std::ostream & out) {
out << "active matrix for k = " << k << std::endl;
if (k >= dimension()) {
out << "empty" << std::endl;
@ -1038,7 +1076,7 @@ void sparse_matrix<T, X>::print_active_matrix(unsigned k, std::ostream & out) {
}
template <typename T, typename X>
bool sparse_matrix<T, X>::pivot_queue_is_correct_for_row(unsigned i, unsigned k) {
bool square_sparse_matrix<T, X>::pivot_queue_is_correct_for_row(unsigned i, unsigned k) {
unsigned arow = adjust_row(i);
for (auto & iv : m_rows[arow].m_values) {
lp_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) ==
@ -1048,7 +1086,7 @@ bool sparse_matrix<T, X>::pivot_queue_is_correct_for_row(unsigned i, unsigned k)
}
template <typename T, typename X>
bool sparse_matrix<T, X>::pivot_queue_is_correct_after_pivoting(int k) {
bool square_sparse_matrix<T, X>::pivot_queue_is_correct_after_pivoting(int k) {
for (unsigned i = k + 1; i < dimension(); i++ )
lp_assert(pivot_queue_is_correct_for_row(i, k));
lp_assert(m_pivot_queue.is_correct());
@ -1057,7 +1095,7 @@ bool sparse_matrix<T, X>::pivot_queue_is_correct_after_pivoting(int k) {
#endif
template <typename T, typename X>
bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_partial_pivoting, unsigned k) {
bool square_sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_partial_pivoting, unsigned k) {
vector<upair> pivots_candidates_that_are_too_small;
while (!m_pivot_queue.is_empty()) {
m_pivot_queue.dequeue(i, j);
@ -1087,7 +1125,7 @@ bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_p
}
template <typename T, typename X>
bool sparse_matrix<T, X>::elem_is_too_small(vector<indexed_value<T>> & row_chunk, indexed_value<T> & iv, int c_partial_pivoting) {
bool square_sparse_matrix<T, X>::elem_is_too_small(vector<indexed_value<T>> & row_chunk, indexed_value<T> & iv, int c_partial_pivoting) {
if (&iv == &row_chunk[0]) {
return false; // the max element is at the head
}
@ -1097,7 +1135,7 @@ bool sparse_matrix<T, X>::elem_is_too_small(vector<indexed_value<T>> & row_chunk
}
template <typename T, typename X>
bool sparse_matrix<T, X>::shorten_columns_by_pivot_row(unsigned i, unsigned pivot_column) {
bool square_sparse_matrix<T, X>::shorten_columns_by_pivot_row(unsigned i, unsigned pivot_column) {
vector<indexed_value<T>> & row_chunk = get_row_values(i);
for (indexed_value<T> & iv : row_chunk) {
@ -1116,7 +1154,7 @@ bool sparse_matrix<T, X>::shorten_columns_by_pivot_row(unsigned i, unsigned pivo
}
template <typename T, typename X>
bool sparse_matrix<T, X>::fill_eta_matrix(unsigned j, eta_matrix<T, X> ** eta) {
bool square_sparse_matrix<T, X>::fill_eta_matrix(unsigned j, eta_matrix<T, X> ** eta) {
const vector<indexed_value<T>> & col_chunk = get_column_values(adjust_column(j));
bool is_unit = true;
for (const auto & iv : col_chunk) {
@ -1163,7 +1201,7 @@ bool sparse_matrix<T, X>::fill_eta_matrix(unsigned j, eta_matrix<T, X> ** eta) {
}
#ifdef Z3DEBUG
template <typename T, typename X>
bool sparse_matrix<T, X>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const {
bool square_sparse_matrix<T, X>::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const {
for (unsigned i = 0; i < dimension(); i++) {
vector<indexed_value<T>> const & row_chunk = get_row_values(i);
lp_assert(row_chunk.size());
@ -1188,7 +1226,7 @@ bool sparse_matrix<T, X>::is_upper_triangular_and_maximums_are_set_correctly_in_
}
template <typename T, typename X>
bool sparse_matrix<T, X>::is_upper_triangular_until(unsigned k) const {
bool square_sparse_matrix<T, X>::is_upper_triangular_until(unsigned k) const {
for (unsigned j = 0; j < dimension() && j < k; j++) {
unsigned aj = adjust_column(j);
auto & col = get_column_values(aj);
@ -1202,7 +1240,7 @@ bool sparse_matrix<T, X>::is_upper_triangular_until(unsigned k) const {
}
template <typename T, typename X>
void sparse_matrix<T, X>::check_column_vs_rows(unsigned col) {
void square_sparse_matrix<T, X>::check_column_vs_rows(unsigned col) {
auto & mc = get_column_values(col);
for (indexed_value<T> & column_iv : mc) {
indexed_value<T> & row_iv = column_iv_other(column_iv);
@ -1225,7 +1263,7 @@ void sparse_matrix<T, X>::check_column_vs_rows(unsigned col) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::check_row_vs_columns(unsigned row) {
void square_sparse_matrix<T, X>::check_row_vs_columns(unsigned row) {
auto & mc = get_row_values(row);
for (indexed_value<T> & row_iv : mc) {
indexed_value<T> & column_iv = row_iv_other(row_iv);
@ -1249,20 +1287,20 @@ void sparse_matrix<T, X>::check_row_vs_columns(unsigned row) {
}
template <typename T, typename X>
void sparse_matrix<T, X>::check_rows_vs_columns() {
void square_sparse_matrix<T, X>::check_rows_vs_columns() {
for (unsigned i = 0; i < dimension(); i++) {
check_row_vs_columns(i);
}
}
template <typename T, typename X>
void sparse_matrix<T, X>::check_columns_vs_rows() {
void square_sparse_matrix<T, X>::check_columns_vs_rows() {
for (unsigned i = 0; i < dimension(); i++) {
check_column_vs_rows(i);
}
}
template <typename T, typename X>
void sparse_matrix<T, X>::check_matrix() {
void square_sparse_matrix<T, X>::check_matrix() {
check_rows_vs_columns();
check_columns_vs_rows();
}

View file

@ -82,17 +82,17 @@ public:
ref(static_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
ref & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
ref & operator=(ref const & v) { m_matrix.set(m_row, m_col, v.m_matrix.get(v.m_row, v.m_col)); return *this; }
ref operator=(ref & v) { m_matrix.set(m_row, m_col, v.m_matrix.get(v.m_row, v.m_col)); return *this; }
operator T () const { return m_matrix.get_elem(m_row, m_col); }
};
class ref_row {
static_matrix & m_matrix;
const static_matrix & m_matrix;
unsigned m_row;
public:
ref_row(static_matrix & m, unsigned row):m_matrix(m), m_row(row) {}
ref operator[](unsigned col) const { return ref(m_matrix, m_row, col); }
ref_row(const static_matrix & m, unsigned row): m_matrix(m), m_row(row) {}
const T operator[](unsigned col) const { return m_matrix.get_elem(m_row, col); }
};
public:
@ -450,6 +450,10 @@ public:
column_container column(unsigned j) const {
return column_container(j, *this);
}
ref_row operator[](unsigned i) const { return ref_row(*this, i);}
typedef T coefftype;
typedef X argtype;
};
}

View file

@ -39,5 +39,12 @@ public:
virtual void apply_from_right(indexed_vector<T> & w) = 0;
virtual ~tail_matrix() {}
virtual bool is_dense() const = 0;
struct ref_row {
const tail_matrix & m_A;
unsigned m_row;
ref_row(const tail_matrix& m, unsigned row): m_A(m), m_row(row) {}
T operator[](unsigned j) const { return m_A.get_elem(m_row, j);}
};
ref_row operator[](unsigned i) const { return ref_row(*this, i);}
};
}

View file

@ -501,7 +501,7 @@ public:
void machine_div(mpz const & a, mpz const & b, mpz & c) { mpz_manager<SYNCH>::machine_div(a, b, c); }
void machine_div_rem(mpz const & a, mpz const & b, mpz & c, mpz& d) { mpz_manager<SYNCH>::machine_div_rem(a, b, c, d); }
void machine_div_rem(mpz const & a, mpz const & b, mpz & c, mpz & d) { mpz_manager<SYNCH>::machine_div_rem(a, b, c, d); }
void div(mpz const & a, mpz const & b, mpz & c) { mpz_manager<SYNCH>::div(a, b, c); }

View file

@ -188,6 +188,12 @@ public:
return r;
}
friend inline rational machine_div_rem(rational const & r1, rational const & r2, rational & rem) {
rational r;
rational::m().machine_idiv_rem(r1.m_val, r2.m_val, r.m_val, rem.m_val);
return r;
}
friend inline rational mod(rational const & r1, rational const & r2) {
rational r;
rational::m().mod(r1.m_val, r2.m_val, r.m_val);
@ -409,8 +415,6 @@ public:
}
return num_bits;
}
};
inline bool operator!=(rational const & r1, rational const & r2) {