mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 19:05:51 +00:00
Merge branch 'master' into polysat
This commit is contained in:
commit
1df749ad33
368 changed files with 12363 additions and 6152 deletions
|
@ -25,7 +25,7 @@ Revision History:
|
|||
template<class T>
|
||||
class positive_boolean_algebra {
|
||||
public:
|
||||
virtual ~positive_boolean_algebra() {}
|
||||
virtual ~positive_boolean_algebra() = default;
|
||||
virtual T mk_false() = 0;
|
||||
virtual T mk_true() = 0;
|
||||
virtual T mk_and(T x, T y) = 0;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
Extended Linear Simplification (as exploited in Bosphorus AAAI 2019):
|
||||
- multiply each polynomial by one variable from their orbits.
|
||||
- The orbit of a varible are the variables that occur in the same monomial as it in some polynomial.
|
||||
- The orbit of a variable are the variables that occur in the same monomial as it in some polynomial.
|
||||
- The extended set of polynomials is fed to a linear Gauss Jordan Eliminator that extracts
|
||||
additional linear equalities.
|
||||
- Bosphorus uses M4RI to perform efficient GJE to scale on large bit-matrices.
|
||||
|
@ -32,7 +32,7 @@
|
|||
The method seems rather specific to hardware multipliers so not clear it is useful to
|
||||
generalize.
|
||||
- find monomials that contain pairs of vanishing polynomials, transitively
|
||||
withtout actually inlining.
|
||||
without actually inlining.
|
||||
Then color polynomial variables w by p, resp, q if they occur in polynomial equalities
|
||||
w - r = 0, such that all paths in r contain a node colored by p, resp q.
|
||||
polynomial variables that get colored by both p and q can be set to 0.
|
||||
|
|
|
@ -61,8 +61,7 @@ namespace dd {
|
|||
|
||||
solver::solver(reslimit& lim, pdd_manager& m) :
|
||||
m(m),
|
||||
m_limit(lim),
|
||||
m_conflict(nullptr)
|
||||
m_limit(lim)
|
||||
{}
|
||||
|
||||
solver::~solver() {
|
||||
|
@ -179,9 +178,8 @@ namespace dd {
|
|||
set[i]->set_index(j++);
|
||||
}
|
||||
~scoped_update() {
|
||||
for (; i < sz; ++i) {
|
||||
for (; i < sz; ++i)
|
||||
nextj();
|
||||
}
|
||||
set.shrink(j);
|
||||
}
|
||||
};
|
||||
|
@ -191,23 +189,24 @@ namespace dd {
|
|||
equation& target = *set[sr.i];
|
||||
bool changed_leading_term = false;
|
||||
bool simplified = true;
|
||||
simplified = !done() && simplifier(target, changed_leading_term);
|
||||
simplified = !done() && simplifier(target, changed_leading_term);
|
||||
|
||||
|
||||
if (simplified && is_trivial(target)) {
|
||||
if (simplified && is_trivial(target))
|
||||
retire(&target);
|
||||
}
|
||||
else if (simplified && check_conflict(target)) {
|
||||
// pushed to solved
|
||||
}
|
||||
else if (simplified && changed_leading_term) {
|
||||
push_equation(to_simplify, target);
|
||||
if (!m_var2level.empty()) {
|
||||
if (&m_to_simplify == &set)
|
||||
sr.nextj();
|
||||
else
|
||||
push_equation(to_simplify, target);
|
||||
if (!m_var2level.empty())
|
||||
m_levelp1 = std::max(m_var2level[target.poly().var()]+1, m_levelp1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
sr.nextj();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ private:
|
|||
vector<std::tuple<unsigned, pdd, u_dependency*>> m_subst;
|
||||
mutable u_dependency_manager m_dep_manager;
|
||||
equation_vector m_all_eqs;
|
||||
equation* m_conflict;
|
||||
equation* m_conflict = nullptr;
|
||||
bool m_too_complex;
|
||||
public:
|
||||
solver(reslimit& lim, pdd_manager& m);
|
||||
|
|
|
@ -66,7 +66,7 @@ class heap_trie {
|
|||
unsigned m_ref;
|
||||
public:
|
||||
node(node_t t): m_type(t), m_ref(0) {}
|
||||
virtual ~node() {}
|
||||
virtual ~node() = default;
|
||||
node_t type() const { return m_type; }
|
||||
void inc_ref() { ++m_ref; }
|
||||
void dec_ref() { SASSERT(m_ref > 0); --m_ref; }
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
Abstract:
|
||||
|
||||
intervals with depedency tracking.
|
||||
intervals with dependency tracking.
|
||||
|
||||
Author:
|
||||
Nikolaj Bjorner (nbjorner)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
Abstract:
|
||||
|
||||
intervals with depedency tracking.
|
||||
intervals with dependency tracking.
|
||||
|
||||
Author:
|
||||
Nikolaj Bjorner (nbjorner)
|
||||
|
|
|
@ -518,7 +518,7 @@ std::ostream& emonics::display(std::ostream& out, cell* c) const {
|
|||
|
||||
bool emonics::invariant() const {
|
||||
TRACE("nla_solver_mons", display(tout););
|
||||
// the varible index contains exactly the active monomials
|
||||
// the variable index contains exactly the active monomials
|
||||
unsigned mons = 0;
|
||||
for (lpvar v = 0; v < m_var2index.size(); v++) {
|
||||
if (is_monic_var(v)) {
|
||||
|
@ -546,6 +546,7 @@ bool emonics::invariant() const {
|
|||
}
|
||||
CTRACE("nla_solver_mons", !found, tout << "not found v" << v << ": " << m << "\n";);
|
||||
SASSERT(found);
|
||||
(void)found;
|
||||
c = c->m_next;
|
||||
}
|
||||
while (c != ht.m_head);
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
virtual vector<std::pair<mpq, var_index>> coeffs() const = 0;
|
||||
lar_base_constraint(unsigned j, lconstraint_kind kind, const mpq& right_side) :m_kind(kind), m_right_side(right_side), m_active(false), m_j(j) {}
|
||||
virtual ~lar_base_constraint() {}
|
||||
virtual ~lar_base_constraint() = default;
|
||||
|
||||
lconstraint_kind kind() const { return m_kind; }
|
||||
mpq const& rhs() const { return m_right_side; }
|
||||
|
|
|
@ -93,7 +93,7 @@ class lar_solver : public column_namer {
|
|||
unsigned_vector m_row_bounds_to_replay;
|
||||
|
||||
u_set m_basic_columns_with_changed_cost;
|
||||
// these are basic columns with the value changed, so the the corresponding row in the tableau
|
||||
// these are basic columns with the value changed, so the corresponding row in the tableau
|
||||
// does not sum to zero anymore
|
||||
u_set m_incorrect_columns;
|
||||
// copy of m_r_solver.inf_set()
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace lp_api {
|
|||
m_constraints[1] = ct;
|
||||
}
|
||||
|
||||
virtual ~bound() {}
|
||||
virtual ~bound() = default;
|
||||
|
||||
theory_var get_var() const { return m_var; }
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ const char* lp_status_to_string(lp_status status) {
|
|||
case lp_status::TIME_EXHAUSTED: return "TIME_EXHAUSTED";
|
||||
case lp_status::EMPTY: return "EMPTY";
|
||||
case lp_status::UNSTABLE: return "UNSTABLE";
|
||||
case lp_status::CANCELLED: return "CANCELLED";
|
||||
default:
|
||||
lp_unreachable();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
virtual void set_number_of_rows(unsigned m) = 0;
|
||||
virtual void set_number_of_columns(unsigned n) = 0;
|
||||
|
||||
virtual ~matrix() {}
|
||||
virtual ~matrix() = default;
|
||||
|
||||
bool is_equal(const matrix<T, X>& other);
|
||||
bool operator == (matrix<T, X> const & other) {
|
||||
|
|
|
@ -20,7 +20,7 @@ Revision History:
|
|||
|
||||
#pragma once
|
||||
|
||||
// reads an MPS file reperesenting a Mixed Integer Program
|
||||
// reads an MPS file representing a Mixed Integer Program
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
bool is_scalar() const { return type() == expr_type::SCALAR; }
|
||||
virtual bool is_pure_monomial() const { return false; }
|
||||
std::string str() const { std::stringstream ss; print(ss); return ss.str(); }
|
||||
virtual ~nex() {}
|
||||
virtual ~nex() = default;
|
||||
virtual bool contains(lpvar j) const { return false; }
|
||||
virtual unsigned get_degree() const = 0;
|
||||
// simplifies the expression and also assigns the address of "this" to *e
|
||||
|
|
|
@ -45,14 +45,19 @@ namespace nla {
|
|||
if (is_conflicting())
|
||||
return;
|
||||
|
||||
if (propagate_bounds())
|
||||
return;
|
||||
try {
|
||||
if (propagate_bounds())
|
||||
return;
|
||||
|
||||
if (propagate_eqs())
|
||||
return;
|
||||
if (propagate_eqs())
|
||||
return;
|
||||
|
||||
if (propagate_factorization())
|
||||
return;
|
||||
if (propagate_factorization())
|
||||
return;
|
||||
}
|
||||
catch (...) {
|
||||
|
||||
}
|
||||
|
||||
if (quota > 1)
|
||||
quota--;
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
virtual void apply_from_left(vector<X> & w, lp_settings & settings) = 0;
|
||||
virtual void apply_from_right(vector<T> & w) = 0;
|
||||
virtual void apply_from_right(indexed_vector<T> & w) = 0;
|
||||
virtual ~tail_matrix() {}
|
||||
virtual ~tail_matrix() = default;
|
||||
virtual bool is_dense() const = 0;
|
||||
struct ref_row {
|
||||
const tail_matrix & m_A;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,9 @@ namespace opt {
|
|||
t_eq,
|
||||
t_lt,
|
||||
t_le,
|
||||
t_mod
|
||||
t_divides,
|
||||
t_mod,
|
||||
t_div
|
||||
};
|
||||
|
||||
|
||||
|
@ -48,15 +50,23 @@ namespace opt {
|
|||
return x.m_id < y.m_id;
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(var const& other) const {
|
||||
return m_id == other.m_id && m_coeff == other.m_coeff;
|
||||
}
|
||||
|
||||
bool operator!=(var const& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
struct row {
|
||||
row(): m_type(t_le), m_value(0), m_alive(false) {}
|
||||
vector<var> m_vars; // variables with coefficients
|
||||
rational m_coeff; // constant in inequality
|
||||
rational m_mod; // value the term divide
|
||||
ineq_type m_type; // inequality type
|
||||
rational m_value; // value of m_vars + m_coeff under interpretation of m_var2value.
|
||||
bool m_alive; // rows can be marked dead if they have been processed.
|
||||
vector<var> m_vars; // variables with coefficients
|
||||
rational m_coeff = rational::zero(); // constant in inequality
|
||||
rational m_mod = rational::zero(); // value the term divide
|
||||
ineq_type m_type = t_le; // inequality type
|
||||
rational m_value = rational::zero(); // value of m_vars + m_coeff under interpretation of m_var2value.
|
||||
bool m_alive = false; // rows can be marked dead if they have been processed.
|
||||
unsigned m_id = UINT_MAX; // variable defined by row (used for mod_t and div_t)
|
||||
void reset() { m_vars.reset(); m_coeff.reset(); m_value.reset(); }
|
||||
|
||||
row& normalize();
|
||||
|
@ -85,9 +95,9 @@ namespace opt {
|
|||
static const unsigned m_objective_id = 0;
|
||||
vector<unsigned_vector> m_var2row_ids;
|
||||
vector<rational> m_var2value;
|
||||
bool_vector m_var2is_int;
|
||||
bool_vector m_var2is_int;
|
||||
vector<var> m_new_vars;
|
||||
unsigned_vector m_lub, m_glb, m_mod;
|
||||
unsigned_vector m_lub, m_glb, m_divides, m_mod, m_div;
|
||||
unsigned_vector m_above, m_below;
|
||||
unsigned_vector m_retired_rows;
|
||||
|
||||
|
@ -114,7 +124,7 @@ namespace opt {
|
|||
|
||||
void mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2);
|
||||
|
||||
void mul_add(unsigned x, rational const& a1, unsigned row_src, rational const& a2, unsigned row_dst);
|
||||
void mul_add(unsigned x, rational a1, unsigned row_src, rational a2, unsigned row_dst);
|
||||
|
||||
void mul(unsigned dst, rational const& c);
|
||||
|
||||
|
@ -122,14 +132,18 @@ namespace opt {
|
|||
|
||||
void sub(unsigned dst, rational const& c);
|
||||
|
||||
void del_var(unsigned dst, unsigned x);
|
||||
void set_row(unsigned row_id, vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel);
|
||||
|
||||
void set_row(unsigned row_id, vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel);
|
||||
void add_lower_bound(unsigned x, rational const& lo);
|
||||
|
||||
void add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type r);
|
||||
void add_upper_bound(unsigned x, rational const& hi);
|
||||
|
||||
unsigned add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type r, unsigned id);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& A, unsigned y, rational const& B);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& A, unsigned y, rational const& B, unsigned z);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& C);
|
||||
|
||||
void normalize(unsigned row_id);
|
||||
|
@ -138,7 +152,7 @@ namespace opt {
|
|||
|
||||
unsigned new_row();
|
||||
|
||||
unsigned copy_row(unsigned row_id);
|
||||
unsigned copy_row(unsigned row_id, unsigned excl = UINT_MAX);
|
||||
|
||||
rational n_sign(rational const& b) const;
|
||||
|
||||
|
@ -150,8 +164,10 @@ namespace opt {
|
|||
|
||||
def solve_for(unsigned row_id, unsigned x, bool compute_def);
|
||||
|
||||
def solve_mod(unsigned x, unsigned_vector const& mod_rows, bool compute_def);
|
||||
|
||||
def solve_divides(unsigned x, unsigned_vector const& divide_rows, bool compute_def);
|
||||
|
||||
def solve_mod_div(unsigned x, unsigned_vector const& mod_rows, unsigned_vector const& divide_rows, bool compute_def);
|
||||
|
||||
bool is_int(unsigned x) const { return m_var2is_int[x]; }
|
||||
|
||||
void retire_row(unsigned row_id);
|
||||
|
@ -173,6 +189,17 @@ namespace opt {
|
|||
// add a divisibility constraint. The row should divide m.
|
||||
void add_divides(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
|
||||
// add sub-expression for modulus
|
||||
// v = add_mod(coeffs, m) means
|
||||
// v = coeffs mod m
|
||||
unsigned add_mod(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
// add sub-expression for div
|
||||
// v = add_div(coeffs, m) means
|
||||
// v = coeffs div m
|
||||
unsigned add_div(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
// Set the objective function (linear).
|
||||
void set_objective(vector<var> const& coeffs, rational const& c);
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace smt {
|
|||
m_states(states),
|
||||
m_enter_id(enter_id) {
|
||||
}
|
||||
virtual ~pivot_rule_impl() {}
|
||||
virtual ~pivot_rule_impl() = default;
|
||||
virtual bool choose_entering_edge() = 0;
|
||||
virtual pivot_rule rule() const = 0;
|
||||
};
|
||||
|
|
|
@ -41,6 +41,10 @@ namespace simplex {
|
|||
sparse_matrix_ops::kernel(M, K);
|
||||
}
|
||||
|
||||
void kernel_ffe(sparse_matrix<mpq_ext> &M, vector<vector<rational>> &K) {
|
||||
sparse_matrix_ops::kernel_ffe(M, K);
|
||||
}
|
||||
|
||||
void ensure_rational_solution(simplex<mpq_ext>& S) {
|
||||
rational delta(1);
|
||||
for (unsigned i = 0; i < S.get_num_vars(); ++i) {
|
||||
|
|
|
@ -203,5 +203,6 @@ namespace simplex {
|
|||
void ensure_rational_solution(simplex<mpq_ext>& s);
|
||||
|
||||
void kernel(sparse_matrix<mpq_ext>& s, vector<vector<rational>>& K);
|
||||
void kernel_ffe(sparse_matrix<mpq_ext> &s, vector<vector<rational>> &K);
|
||||
};
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ namespace simplex {
|
|||
void add_var(row r, numeral const& n, var_t var);
|
||||
void add(row r, numeral const& n, row src);
|
||||
void mul(row r, numeral const& n);
|
||||
void div(row r, numeral const& n);
|
||||
void neg(row r);
|
||||
void del(row r);
|
||||
|
||||
|
|
|
@ -432,6 +432,25 @@ namespace simplex {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set row <- n/row
|
||||
*/
|
||||
template <typename Ext>
|
||||
void sparse_matrix<Ext>::div(row r, numeral const &n) {
|
||||
SASSERT(!m.is_zero(n));
|
||||
if (m.is_one(n)) {
|
||||
// no op
|
||||
} else if (m.is_minus_one(n)) {
|
||||
neg(r);
|
||||
} else {
|
||||
row_iterator it = row_begin(r);
|
||||
row_iterator end = row_end(r);
|
||||
for (; it != end; ++it) {
|
||||
m.div(it->m_coeff, n, it->m_coeff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Delete row.
|
||||
*/
|
||||
|
|
|
@ -43,7 +43,7 @@ class sparse_matrix_ops {
|
|||
for (auto [row, row_entry] : M.get_rows(k)) {
|
||||
if (c[row.id()] != 0) continue;
|
||||
auto &m_jk = row_entry->m_coeff;
|
||||
if (mpq_manager<false>::is_zero(m_jk)) continue;
|
||||
if (m.is_zero(m_jk)) continue;
|
||||
|
||||
// D = rational(-1) / m_jk;
|
||||
m.set(D, m_jk);
|
||||
|
@ -68,9 +68,10 @@ class sparse_matrix_ops {
|
|||
K.push_back(vector<rational>());
|
||||
for (unsigned i = 0; i < n_vars; ++i) {
|
||||
if (d[i] > 0) {
|
||||
auto r = sparse_matrix<mpq_ext>::row(d[i] - 1);
|
||||
auto r = typename sparse_matrix<Ext>::row(d[i] - 1);
|
||||
K.back().push_back(rational(M.get_coeff(r, k)));
|
||||
} else if (i == k)
|
||||
}
|
||||
else if (i == k)
|
||||
K.back().push_back(rational(1));
|
||||
else
|
||||
K.back().push_back(rational(0));
|
||||
|
@ -81,5 +82,157 @@ class sparse_matrix_ops {
|
|||
static void kernel(sparse_matrix<mpq_ext> &M, vector<vector<rational>> &K) {
|
||||
kernel<mpq_ext>(M, K);
|
||||
}
|
||||
|
||||
/// \brief Kernel computation using fraction-free-elimination
|
||||
///
|
||||
template <typename Ext>
|
||||
static void kernel_ffe(sparse_matrix<Ext> &M, vector<vector<rational>> &K) {
|
||||
using scoped_numeral = typename Ext::scoped_numeral;
|
||||
|
||||
/// Based on George Nakos, Peter R. Turner, Robert M. Williams:
|
||||
/// Fraction-free algorithms for linear and polynomial equations. SIGSAM
|
||||
/// Bull. 31(3): 11-19 (1997)
|
||||
vector<unsigned> d, c;
|
||||
unsigned n_vars = M.num_vars(), n_rows = M.num_rows();
|
||||
c.resize(n_rows, 0u);
|
||||
d.resize(n_vars, 0u);
|
||||
|
||||
auto &m = M.get_manager();
|
||||
scoped_numeral m_ik(m);
|
||||
scoped_numeral m_jk(m);
|
||||
scoped_numeral last_pv(m);
|
||||
|
||||
m.set(last_pv, 1);
|
||||
|
||||
for (unsigned k = 0; k < n_vars; ++k) {
|
||||
d[k] = 0;
|
||||
for (auto [row, row_entry] : M.get_rows(k)) {
|
||||
if (c[row.id()] != 0) continue;
|
||||
auto &m_jk_ref = row_entry->m_coeff;
|
||||
if (m.is_zero(m_jk_ref))
|
||||
// XXX: should not happen, the matrix is sparse
|
||||
continue;
|
||||
|
||||
// this a pivot column
|
||||
m.set(m_jk, m_jk_ref);
|
||||
|
||||
// ensure that pivot is negative
|
||||
if (m.is_pos(m_jk_ref)) { M.neg(row); }
|
||||
else { m.neg(m_jk); }
|
||||
// m_jk is abs(M[j]][k])
|
||||
|
||||
for (auto row_i : M.get_rows()) {
|
||||
if (row_i.id() == row.id()) continue;
|
||||
|
||||
m.set(m_ik, M.get_coeff(row_i, k));
|
||||
// row_i *= m_jk
|
||||
M.mul(row_i, m_jk);
|
||||
if (!m.is_zero(m_ik)) {
|
||||
// row_i += m_ik * row
|
||||
M.add(row_i, m_ik, row);
|
||||
}
|
||||
M.div(row_i, last_pv);
|
||||
}
|
||||
c[row.id()] = k + 1;
|
||||
d[k] = row.id() + 1;
|
||||
m.set(last_pv, m_jk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned k = 0; k < n_vars; ++k) {
|
||||
if (d[k] != 0) continue;
|
||||
K.push_back(vector<rational>());
|
||||
for (unsigned i = 0; i < n_vars; ++i) {
|
||||
if (d[i] > 0) {
|
||||
auto r = typename sparse_matrix<Ext>::row(d[i] - 1);
|
||||
K.back().push_back(rational(M.get_coeff(r, k)));
|
||||
}
|
||||
else if (i == k)
|
||||
K.back().push_back(rational(last_pv));
|
||||
else
|
||||
K.back().push_back(rational(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kernel_ffe(sparse_matrix<mpq_ext> &M,
|
||||
vector<vector<rational>> &K) {
|
||||
kernel_ffe<mpq_ext>(M, K);
|
||||
}
|
||||
|
||||
|
||||
template <typename Ext>
|
||||
static void kernel_ffe(sparse_matrix<Ext> &M, sparse_matrix<Ext> &K,
|
||||
vector<unsigned> &basics) {
|
||||
using scoped_numeral = typename Ext::scoped_numeral;
|
||||
|
||||
/// Based on George Nakos, Peter R. Turner, Robert M. Williams:
|
||||
/// Fraction-free algorithms for linear and polynomial equations. SIGSAM
|
||||
/// Bull. 31(3): 11-19 (1997)
|
||||
vector<unsigned> d, c;
|
||||
unsigned n_vars = M.num_vars(), n_rows = M.num_rows();
|
||||
c.resize(n_rows, 0u);
|
||||
d.resize(n_vars, 0u);
|
||||
|
||||
auto &m = M.get_manager();
|
||||
scoped_numeral m_ik(m);
|
||||
scoped_numeral m_jk(m);
|
||||
scoped_numeral last_pv(m);
|
||||
|
||||
m.set(last_pv, 1);
|
||||
|
||||
for (unsigned k = 0; k < n_vars; ++k) {
|
||||
d[k] = 0;
|
||||
for (auto [row, row_entry] : M.get_rows(k)) {
|
||||
if (c[row.id()] != 0) continue;
|
||||
auto &m_jk_ref = row_entry->m_coeff;
|
||||
if (m.is_zero(m_jk_ref))
|
||||
// XXX: should not happen, the matrix is sparse
|
||||
continue;
|
||||
|
||||
// this a pivot column
|
||||
m.set(m_jk, m_jk_ref);
|
||||
|
||||
// ensure that pivot is negative
|
||||
if (m.is_pos(m_jk_ref)) { M.neg(row); }
|
||||
else { m.neg(m_jk); }
|
||||
// m_jk is abs(M[j]][k])
|
||||
|
||||
for (auto row_i : M.get_rows()) {
|
||||
if (row_i.id() == row.id()) continue;
|
||||
|
||||
m.set(m_ik, M.get_coeff(row_i, k));
|
||||
// row_i *= m_jk
|
||||
M.mul(row_i, m_jk);
|
||||
if (!m.is_zero(m_ik)) {
|
||||
// row_i += m_ik * row
|
||||
M.add(row_i, m_ik, row);
|
||||
}
|
||||
M.div(row_i, last_pv);
|
||||
}
|
||||
c[row.id()] = k + 1;
|
||||
d[k] = row.id() + 1;
|
||||
m.set(last_pv, m_jk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
K.ensure_var(n_vars - 1);
|
||||
for (unsigned k = 0; k < n_vars; ++k) {
|
||||
if (d[k] != 0) continue;
|
||||
auto row = K.mk_row();
|
||||
basics.push_back(k);
|
||||
for (unsigned i = 0; i < n_vars; ++i) {
|
||||
if (d[i] > 0) {
|
||||
auto r = typename sparse_matrix<Ext>::row(d[i] - 1);
|
||||
K.add_var(row, M.get_coeff(r, k), i);
|
||||
}
|
||||
else if (i == k)
|
||||
K.add_var(row, last_pv, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace simplex
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace subpaving {
|
|||
|
||||
class context {
|
||||
public:
|
||||
virtual ~context() {}
|
||||
virtual ~context() = default;
|
||||
|
||||
virtual unsynch_mpq_manager & qm() const = 0;
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ public:
|
|||
context_t * m_ctx;
|
||||
public:
|
||||
node_selector(context_t * ctx):m_ctx(ctx) {}
|
||||
virtual ~node_selector() {}
|
||||
virtual ~node_selector() = default;
|
||||
|
||||
context_t * ctx() const { return m_ctx; }
|
||||
|
||||
|
@ -403,7 +403,7 @@ public:
|
|||
context_t * m_ctx;
|
||||
public:
|
||||
var_selector(context_t * ctx):m_ctx(ctx) {}
|
||||
virtual ~var_selector() {}
|
||||
virtual ~var_selector() = default;
|
||||
|
||||
context_t * ctx() const { return m_ctx; }
|
||||
|
||||
|
@ -436,7 +436,7 @@ public:
|
|||
context_t * m_ctx;
|
||||
public:
|
||||
node_splitter(context_t * ctx):m_ctx(ctx) {}
|
||||
virtual ~node_splitter() {}
|
||||
virtual ~node_splitter() = default;
|
||||
|
||||
context_t * ctx() const { return m_ctx; }
|
||||
node * mk_node(node * p) { return ctx()->mk_node(p); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue