z3-z3-4.13.0.src.muz.spacer.spacer_arith_kernel.cpp Maven / Gradle / Ivy
The newest version!
/**++
Copyright (c) 2020 Arie Gurfinkel
Module Name:
spacer_arith_kernel.cpp
Abstract:
Compute kernel of a matrix
Author:
Hari Govind
Arie Gurfinkel
Notes:
--*/
#include "muz/spacer/spacer_arith_kernel.h"
#include "math/simplex/sparse_matrix_def.h"
#include "math/simplex/sparse_matrix_ops.h"
using namespace spacer;
bool spacer_arith_kernel::compute_kernel() {
SASSERT(m_matrix.num_rows() > 1);
if (false && m_matrix.compute_linear_deps(m_kernel)) {
// the matrix cannot be reduced further
if (m_matrix.num_cols() - m_kernel.num_rows() <= 1) return true;
m_kernel.reset(m_kernel.num_cols());
SASSERT(m_matrix.num_cols() > 2);
}
if (m_matrix.num_cols() > 2) m_st.m_failed++;
if (m_plugin /* && m_matrix.num_cols() > 2 */) {
return m_plugin->compute_kernel(m_matrix, m_kernel, m_basic_vars);
}
return false;
}
namespace {
class simplex_arith_kernel_plugin : public spacer_arith_kernel::plugin {
public:
simplex_arith_kernel_plugin() {}
bool compute_kernel(const spacer_matrix &in, spacer_matrix &out,
vector &basics) override {
using qmatrix = simplex::sparse_matrix;
unsynch_mpq_manager m;
qmatrix qmat(m);
// extra column for column of 1
qmat.ensure_var(in.num_cols());
for (unsigned i = 0, n_rows = in.num_rows(); i < n_rows; ++i) {
auto row_id = qmat.mk_row();
unsigned j, n_cols;
for (j = 0, n_cols = in.num_cols(); j < n_cols; ++j) {
qmat.add_var(row_id, in.get(i, j).to_mpq(), j);
}
qmat.add_var(row_id, rational::one().to_mpq(), n_cols);
}
TRACE("gg", qmat.display(tout););
qmatrix kern(m);
simplex::sparse_matrix_ops::kernel_ffe(qmat, kern,
basics);
out.reset(kern.num_vars());
vector vec;
for (auto row : kern.get_rows()) {
vec.reset();
vec.reserve(kern.num_vars(), rational(0));
for (auto &[coeff, v] : kern.get_row(row)) {
vec[v] = rational(coeff);
}
out.add_row(vec);
}
TRACE("gg", {
tout << "Computed kernel\n";
qmat.display(tout);
tout << "\n";
kern.display(tout);
tout << "\n";
tout << "basics: " << basics << "\n";
out.display(tout);
});
return out.num_rows() > 0;
}
void collect_statistics(statistics &st) const override {}
void reset_statistics() override {}
void reset() override {}
};
} // namespace
namespace spacer {
spacer_arith_kernel::plugin *mk_simplex_kernel_plugin() {
return alloc(simplex_arith_kernel_plugin);
}
} // namespace spacer