mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 06:03:23 +00:00
add stub for cheap equality propagation
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
6a45c5d17c
commit
d372af4782
13 changed files with 131 additions and 105 deletions
|
@ -55,6 +55,17 @@ public :
|
||||||
m_rs(rs)
|
m_rs(rs)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
static void analyze_row(const C & row,
|
||||||
|
unsigned bj, // basis column for the row
|
||||||
|
const numeric_pair<mpq>& rs,
|
||||||
|
unsigned row_or_term_index,
|
||||||
|
lp_bound_propagator & bp) {
|
||||||
|
bound_analyzer_on_row a(row, bj, rs, row_or_term_index, bp);
|
||||||
|
a.analyze();
|
||||||
|
// TBD: a.analyze_eq();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
void analyze() {
|
void analyze() {
|
||||||
for (const auto & c : m_row) {
|
for (const auto & c : m_row) {
|
||||||
|
@ -73,6 +84,37 @@ public :
|
||||||
limit_all_monoids_from_above();
|
limit_all_monoids_from_above();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void analyze_eq() {
|
||||||
|
lpvar x = null_lpvar, y = null_lpvar;
|
||||||
|
for (const auto & c : m_row) {
|
||||||
|
if (m_bp.get_column_type(c.var()) == column_type::fixed)
|
||||||
|
continue;
|
||||||
|
if (x == null_lpvar && c.coeff().is_one())
|
||||||
|
x = c.var();
|
||||||
|
else if (y == null_lpvar && c.coeff().is_minus_one())
|
||||||
|
y = c.var();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (x == null_lpvar || y == null_lpvar)
|
||||||
|
return;
|
||||||
|
impq value;
|
||||||
|
for (const auto & c : m_row) {
|
||||||
|
if (m_bp.get_column_type(c.var()) == column_type::fixed)
|
||||||
|
value += c.coeff() * lb(c.var());
|
||||||
|
}
|
||||||
|
if (!value.is_zero()) {
|
||||||
|
// insert / check offset table to infer equalities
|
||||||
|
// of the form y = z from offset table collision:
|
||||||
|
// value = (x - y)
|
||||||
|
// value = (x - z)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// m_bp.try_add_fixed(x, y, m_row_or_term_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool bound_is_available(unsigned j, bool lower_bound) {
|
bool bound_is_available(unsigned j, bool lower_bound) {
|
||||||
return (lower_bound && lower_bound_is_available(j)) ||
|
return (lower_bound && lower_bound_is_available(j)) ||
|
||||||
(!lower_bound && upper_bound_is_available(j));
|
(!lower_bound && upper_bound_is_available(j));
|
||||||
|
@ -319,14 +361,6 @@ public :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void analyze_row(const C & row,
|
|
||||||
unsigned bj, // basis column for the row
|
|
||||||
const numeric_pair<mpq>& rs,
|
|
||||||
unsigned row_or_term_index,
|
|
||||||
lp_bound_propagator & bp) {
|
|
||||||
bound_analyzer_on_row a(row, bj, rs, row_or_term_index, bp);
|
|
||||||
a.analyze();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,7 +631,7 @@ public:
|
||||||
for (unsigned i = 0; i < m_r_A.row_count(); i++) {
|
for (unsigned i = 0; i < m_r_A.row_count(); i++) {
|
||||||
auto & row = m_r_A.m_rows[i];
|
auto & row = m_r_A.m_rows[i];
|
||||||
for (row_cell<mpq> & c : row) {
|
for (row_cell<mpq> & c : row) {
|
||||||
A.add_new_element(i, c.var(), c.get_val().get_double());
|
A.add_new_element(i, c.var(), c.coeff().get_double());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ void lar_core_solver::fill_not_improvable_zero_sum_from_inf_row() {
|
||||||
m_infeasible_sum_sign = m_r_solver.inf_sign_of_column(bj);
|
m_infeasible_sum_sign = m_r_solver.inf_sign_of_column(bj);
|
||||||
m_infeasible_linear_combination.clear();
|
m_infeasible_linear_combination.clear();
|
||||||
for (auto & rc : m_r_solver.m_A.m_rows[m_r_solver.m_inf_row_index_for_tableau]) {
|
for (auto & rc : m_r_solver.m_A.m_rows[m_r_solver.m_inf_row_index_for_tableau]) {
|
||||||
m_infeasible_linear_combination.push_back(std::make_pair( rc.get_val(), rc.var()));
|
m_infeasible_linear_combination.push_back(std::make_pair(rc.coeff(), rc.var()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,14 +141,16 @@ void lar_solver::analyze_new_bounds_on_row(
|
||||||
lp_bound_propagator & bp) {
|
lp_bound_propagator & bp) {
|
||||||
lp_assert(!use_tableau());
|
lp_assert(!use_tableau());
|
||||||
unsigned j = m_mpq_lar_core_solver.m_r_basis[row_index]; // basis column for the row
|
unsigned j = m_mpq_lar_core_solver.m_r_basis[row_index]; // basis column for the row
|
||||||
bound_analyzer_on_row<indexed_vector<mpq>>
|
|
||||||
ra_pos(m_mpq_lar_core_solver.get_pivot_row(),
|
|
||||||
j,
|
bound_analyzer_on_row<indexed_vector<mpq>>::analyze_row(
|
||||||
zero_of_type<numeric_pair<mpq>>(),
|
m_mpq_lar_core_solver.get_pivot_row(),
|
||||||
row_index,
|
j,
|
||||||
bp
|
zero_of_type<numeric_pair<mpq>>(),
|
||||||
);
|
row_index,
|
||||||
ra_pos.analyze();
|
bp
|
||||||
|
);
|
||||||
|
// ra_pos.analyze();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lar_solver::row_has_a_big_num(unsigned i) const {
|
bool lar_solver::row_has_a_big_num(unsigned i) const {
|
||||||
|
@ -167,6 +169,7 @@ void lar_solver::analyze_new_bounds_on_row_tableau(
|
||||||
|| row_has_a_big_num(row_index))
|
|| row_has_a_big_num(row_index))
|
||||||
return;
|
return;
|
||||||
lp_assert(use_tableau());
|
lp_assert(use_tableau());
|
||||||
|
|
||||||
bound_analyzer_on_row<row_strip<mpq>>::analyze_row(A_r().m_rows[row_index],
|
bound_analyzer_on_row<row_strip<mpq>>::analyze_row(A_r().m_rows[row_index],
|
||||||
null_ci,
|
null_ci,
|
||||||
zero_of_type<numeric_pair<mpq>>(),
|
zero_of_type<numeric_pair<mpq>>(),
|
||||||
|
@ -227,7 +230,7 @@ void lar_solver::explain_implied_bound(implied_bound & ib, lp_bound_propagator &
|
||||||
for (auto const& r : A_r().m_rows[i]) {
|
for (auto const& r : A_r().m_rows[i]) {
|
||||||
unsigned j = r.var();
|
unsigned j = r.var();
|
||||||
if (j == bound_j) continue;
|
if (j == bound_j) continue;
|
||||||
mpq const& a = r.get_val();
|
mpq const& a = r.coeff();
|
||||||
int a_sign = is_pos(a)? 1: -1;
|
int a_sign = is_pos(a)? 1: -1;
|
||||||
int sign = j_sign * a_sign;
|
int sign = j_sign * a_sign;
|
||||||
const ul_pair & ul = m_columns_to_ul_pairs[j];
|
const ul_pair & ul = m_columns_to_ul_pairs[j];
|
||||||
|
@ -948,7 +951,7 @@ void lar_solver::copy_from_mpq_matrix(static_matrix<U, V> & matr) {
|
||||||
matr.m_columns.resize(A_r().column_count());
|
matr.m_columns.resize(A_r().column_count());
|
||||||
for (unsigned i = 0; i < matr.row_count(); i++) {
|
for (unsigned i = 0; i < matr.row_count(); i++) {
|
||||||
for (auto & it : A_r().m_rows[i]) {
|
for (auto & it : A_r().m_rows[i]) {
|
||||||
matr.set(i, it.var(), convert_struct<U, mpq>::convert(it.get_val()));
|
matr.set(i, it.var(), convert_struct<U, mpq>::convert(it.coeff()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1399,7 +1402,7 @@ void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) {
|
||||||
for (unsigned k = last_row.size(); k-- > 0;) {
|
for (unsigned k = last_row.size(); k-- > 0;) {
|
||||||
auto &rc = last_row[k];
|
auto &rc = last_row[k];
|
||||||
if (cost_is_nz) {
|
if (cost_is_nz) {
|
||||||
m_mpq_lar_core_solver.m_r_solver.m_d[rc.var()] += cost_j*rc.get_val();
|
m_mpq_lar_core_solver.m_r_solver.m_d[rc.var()] += cost_j * rc.coeff();
|
||||||
}
|
}
|
||||||
A_r().remove_element(last_row, rc);
|
A_r().remove_element(last_row, rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ public:
|
||||||
const impq & get_lower_bound(unsigned) const;
|
const impq & get_lower_bound(unsigned) const;
|
||||||
const impq & get_upper_bound(unsigned) const;
|
const impq & get_upper_bound(unsigned) const;
|
||||||
void try_add_bound(mpq const & v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict);
|
void try_add_bound(mpq const & v, unsigned j, bool is_low, bool coeff_before_j_is_pos, unsigned row_or_term_index, bool strict);
|
||||||
|
void try_add_eq(lpvar x, lpvar y, unsigned row_or_term_index) {} // TBD
|
||||||
virtual bool bound_is_interesting(unsigned vi,
|
virtual bool bound_is_interesting(unsigned vi,
|
||||||
lp::lconstraint_kind kind,
|
lp::lconstraint_kind kind,
|
||||||
const rational & bval) {return true;}
|
const rational & bval) {return true;}
|
||||||
|
|
|
@ -95,7 +95,7 @@ pivot_to_reduced_costs_tableau(unsigned i, unsigned j) {
|
||||||
return;
|
return;
|
||||||
for (const row_cell<T> & r: m_A.m_rows[i]){
|
for (const row_cell<T> & r: m_A.m_rows[i]){
|
||||||
if (r.var() != j)
|
if (r.var() != j)
|
||||||
m_d[r.var()] -= a * r.get_val();
|
m_d[r.var()] -= a * r.coeff();
|
||||||
}
|
}
|
||||||
a = zero_of_type<T>(); // zero the pivot column's m_d finally
|
a = zero_of_type<T>(); // zero the pivot column's m_d finally
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned pivot_row) {
|
||||||
for (auto & c : m_A.m_rows[i]) {
|
for (auto & c : m_A.m_rows[i]) {
|
||||||
unsigned j = c.var();
|
unsigned j = c.var();
|
||||||
if (m_basis_heading[j] < 0) {
|
if (m_basis_heading[j] < 0) {
|
||||||
m_pivot_row.add_value_at_index_with_drop_tolerance(j, c.get_val() * pi_1);
|
m_pivot_row.add_value_at_index_with_drop_tolerance(j, c.coeff() * pi_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,7 +444,7 @@ rs_minus_Anx(vector<X> & rs) {
|
||||||
for (auto & it : m_A.m_rows[row]) {
|
for (auto & it : m_A.m_rows[row]) {
|
||||||
unsigned j = it.var();
|
unsigned j = it.var();
|
||||||
if (m_basis_heading[j] < 0) {
|
if (m_basis_heading[j] < 0) {
|
||||||
rsv -= m_x[j] * it.get_val();
|
rsv -= m_x[j] * it.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -630,8 +630,8 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) {
|
||||||
column[0] = column[pivot_col_cell_index];
|
column[0] = column[pivot_col_cell_index];
|
||||||
column[pivot_col_cell_index] = c;
|
column[pivot_col_cell_index] = c;
|
||||||
|
|
||||||
m_A.m_rows[piv_row_index][column[0].m_offset].m_offset = 0;
|
m_A.m_rows[piv_row_index][column[0].offset()].offset() = 0;
|
||||||
m_A.m_rows[c.var()][c.m_offset].m_offset = pivot_col_cell_index;
|
m_A.m_rows[c.var()][c.offset()].offset() = pivot_col_cell_index;
|
||||||
}
|
}
|
||||||
while (column.size() > 1) {
|
while (column.size() > 1) {
|
||||||
auto & c = column.back();
|
auto & c = column.back();
|
||||||
|
@ -761,7 +761,7 @@ fill_reduced_costs_from_m_y_by_rows() {
|
||||||
for (row_cell<T> & c : m_A.m_rows[i]) {
|
for (row_cell<T> & c : m_A.m_rows[i]) {
|
||||||
j = c.var();
|
j = c.var();
|
||||||
if (m_basis_heading[j] < 0) {
|
if (m_basis_heading[j] < 0) {
|
||||||
m_d[j] -= y * c.get_val();
|
m_d[j] -= y * c.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,7 +804,7 @@ find_error_in_BxB(vector<X>& rs){
|
||||||
for (auto & it : m_A.m_rows[row]) {
|
for (auto & it : m_A.m_rows[row]) {
|
||||||
unsigned j = it.var();
|
unsigned j = it.var();
|
||||||
if (m_basis_heading[j] >= 0) {
|
if (m_basis_heading[j] >= 0) {
|
||||||
rsv -= m_x[j] * it.get_val();
|
rsv -= m_x[j] * it.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1046,7 @@ void lp_core_solver_base<T, X>::calculate_pivot_row(unsigned i) {
|
||||||
unsigned basic_j = m_basis[i];
|
unsigned basic_j = m_basis[i];
|
||||||
for (auto & c : m_A.m_rows[i]) {
|
for (auto & c : m_A.m_rows[i]) {
|
||||||
if (c.var() != basic_j)
|
if (c.var() != basic_j)
|
||||||
m_pivot_row.set_value(c.get_val(), c.var());
|
m_pivot_row.set_value(c.coeff(), c.var());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,19 +180,19 @@ public:
|
||||||
case column_type::fixed:
|
case column_type::fixed:
|
||||||
return false;
|
return false;
|
||||||
case column_type::lower_bound:
|
case column_type::lower_bound:
|
||||||
if (is_pos(rc.get_val())) {
|
if (is_pos(rc.coeff())) {
|
||||||
return this->x_above_lower_bound(j);
|
return this->x_above_lower_bound(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case column_type::upper_bound:
|
case column_type::upper_bound:
|
||||||
if (is_pos(rc.get_val())) {
|
if (is_pos(rc.coeff())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->x_below_upper_bound(j);
|
return this->x_below_upper_bound(j);
|
||||||
case column_type::boxed:
|
case column_type::boxed:
|
||||||
if (is_pos(rc.get_val())) {
|
if (is_pos(rc.coeff())) {
|
||||||
return this->x_above_lower_bound(j);
|
return this->x_above_lower_bound(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,19 +213,19 @@ public:
|
||||||
case column_type::fixed:
|
case column_type::fixed:
|
||||||
return false;
|
return false;
|
||||||
case column_type::lower_bound:
|
case column_type::lower_bound:
|
||||||
if (is_neg(rc.get_val())) {
|
if (is_neg(rc.coeff())) {
|
||||||
return this->x_above_lower_bound(j);
|
return this->x_above_lower_bound(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case column_type::upper_bound:
|
case column_type::upper_bound:
|
||||||
if (is_neg(rc.get_val())) {
|
if (is_neg(rc.coeff())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->x_below_upper_bound(j);
|
return this->x_below_upper_bound(j);
|
||||||
case column_type::boxed:
|
case column_type::boxed:
|
||||||
if (is_neg(rc.get_val())) {
|
if (is_neg(rc.coeff())) {
|
||||||
return this->x_above_lower_bound(j);
|
return this->x_above_lower_bound(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,7 +923,7 @@ public:
|
||||||
unsigned k = rc.var();
|
unsigned k = rc.var();
|
||||||
if (k == j)
|
if (k == j)
|
||||||
continue;
|
continue;
|
||||||
this->m_d[k] += delta * rc.get_val();
|
this->m_d[k] += delta * rc.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,7 @@ void lu< M>::find_error_of_yB_indexed(const indexed_vector<T>& y, const vector<i
|
||||||
if (hj < 0) continue;
|
if (hj < 0) continue;
|
||||||
if (m_ii.m_data[hj] == 0)
|
if (m_ii.m_data[hj] == 0)
|
||||||
m_ii.set_value(1, hj);
|
m_ii.set_value(1, hj);
|
||||||
m_y_copy.m_data[hj] -= c.get_val() * y_k;
|
m_y_copy.m_data[hj] -= c.coeff() * y_k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add the index of m_y_copy to m_ii
|
// add the index of m_y_copy to m_ii
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2017 Microsoft Corporation
|
Copyright (c) 2017 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
|
||||||
|
|
||||||
<name>
|
|
||||||
|
|
||||||
Abstract:
|
|
||||||
|
|
||||||
<abstract>
|
|
||||||
|
|
||||||
Author:
|
Author:
|
||||||
|
|
||||||
Lev Nachmanson (levnach)
|
Lev Nachmanson (levnach)
|
||||||
|
|
||||||
Revision History:
|
|
||||||
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -30,27 +19,26 @@ Revision History:
|
||||||
namespace lp {
|
namespace lp {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct row_cell {
|
class row_cell {
|
||||||
unsigned m_j; // points to the column
|
unsigned m_j; // points to the column
|
||||||
unsigned m_offset; // offset in column
|
unsigned m_offset; // offset in column
|
||||||
T m_value;
|
T m_coeff; // coefficient
|
||||||
row_cell(unsigned j, unsigned offset, T const & val) : m_j(j), m_offset(offset), m_value(val) {
|
public:
|
||||||
|
row_cell(unsigned j, unsigned offset, T const & val) : m_j(j), m_offset(offset), m_coeff(val) {
|
||||||
}
|
}
|
||||||
row_cell(unsigned j, unsigned offset) : m_j(j), m_offset(offset) {
|
row_cell(unsigned j, unsigned offset) : m_j(j), m_offset(offset) {
|
||||||
}
|
}
|
||||||
const T & get_val() const { return m_value;}
|
inline const T & coeff() const { return m_coeff; }
|
||||||
T & get_val() { return m_value;}
|
inline T & coeff() { return m_coeff; }
|
||||||
const T & coeff() const { return m_value;}
|
inline unsigned var() const { return m_j; }
|
||||||
T & coeff() { return m_value;}
|
inline unsigned & var() { return m_j; }
|
||||||
unsigned var() const { return m_j;}
|
inline unsigned offset() const { return m_offset; }
|
||||||
unsigned & var() { return m_j;}
|
inline unsigned & offset() { return m_offset; }
|
||||||
unsigned offset() const { return m_offset;}
|
|
||||||
unsigned & offset() { return m_offset;}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::ostream& operator<<(std::ostream& out, const row_cell<T>& rc) {
|
std::ostream& operator<<(std::ostream& out, const row_cell<T>& rc) {
|
||||||
return out << "(m_j=" << rc.m_j << ", m_offset= " << rc.m_offset << ", m_value=" << rc.m_value << ")";
|
return out << "(j=" << rc.var() << ", offset= " << rc.offset() << ", coeff=" << rc.coeff() << ")";
|
||||||
}
|
}
|
||||||
struct empty_struct {};
|
struct empty_struct {};
|
||||||
typedef row_cell<empty_struct> column_cell;
|
typedef row_cell<empty_struct> column_cell;
|
||||||
|
@ -102,11 +90,11 @@ public:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
const T & get_val(const column_cell & c) const {
|
const T & get_val(const column_cell & c) const {
|
||||||
return m_rows[c.var()][c.m_offset].get_val();
|
return m_rows[c.var()][c.offset()].coeff();
|
||||||
}
|
}
|
||||||
|
|
||||||
column_cell & get_column_cell(const row_cell<T> &rc) {
|
column_cell & get_column_cell(const row_cell<T> &rc) {
|
||||||
return m_columns[rc.m_j][rc.m_offset];
|
return m_columns[rc.var()][rc.offset()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_row_columns(unsigned m, unsigned n);
|
void init_row_columns(unsigned m, unsigned n);
|
||||||
|
@ -243,7 +231,7 @@ public:
|
||||||
|
|
||||||
void pop_row_columns(const vector<row_cell<T>> & row) {
|
void pop_row_columns(const vector<row_cell<T>> & row) {
|
||||||
for (auto & c : row) {
|
for (auto & c : row) {
|
||||||
unsigned j = c.m_j;
|
unsigned j = c.var();
|
||||||
auto & col = m_columns[j];
|
auto & col = m_columns[j];
|
||||||
lp_assert(col[col.size() - 1].var() == m_rows.size() -1 ); // todo : start here!!!!
|
lp_assert(col[col.size() - 1].var() == m_rows.size() -1 ); // todo : start here!!!!
|
||||||
col.pop_back();
|
col.pop_back();
|
||||||
|
@ -277,13 +265,13 @@ public:
|
||||||
|
|
||||||
void multiply_row(unsigned row, T const & alpha) {
|
void multiply_row(unsigned row, T const & alpha) {
|
||||||
for (auto & t : m_rows[row]) {
|
for (auto & t : m_rows[row]) {
|
||||||
t.m_value *= alpha;
|
t.coeff() *= alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void divide_row(unsigned row, T const & alpha) {
|
void divide_row(unsigned row, T const & alpha) {
|
||||||
for (auto & t : m_rows[row]) {
|
for (auto & t : m_rows[row]) {
|
||||||
t.m_value /= alpha;
|
t.coeff() /= alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,12 +294,12 @@ public:
|
||||||
m_rows[ii] = t;
|
m_rows[ii] = t;
|
||||||
// now fix the columns
|
// now fix the columns
|
||||||
for (auto & rc : m_rows[i]) {
|
for (auto & rc : m_rows[i]) {
|
||||||
column_cell & cc = m_columns[rc.m_j][rc.m_offset];
|
column_cell & cc = m_columns[rc.var()][rc.offset()];
|
||||||
lp_assert(cc.var() == ii);
|
lp_assert(cc.var() == ii);
|
||||||
cc.var() = i;
|
cc.var() = i;
|
||||||
}
|
}
|
||||||
for (auto & rc : m_rows[ii]) {
|
for (auto & rc : m_rows[ii]) {
|
||||||
column_cell & cc = m_columns[rc.m_j][rc.m_offset];
|
column_cell & cc = m_columns[rc.var()][rc.offset()];
|
||||||
lp_assert(cc.var() == i);
|
lp_assert(cc.var() == i);
|
||||||
cc.var() = ii;
|
cc.var() = ii;
|
||||||
}
|
}
|
||||||
|
@ -326,17 +314,17 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const auto & c : m_rows[row_index]) {
|
for (const auto & c : m_rows[row_index]) {
|
||||||
if (c.m_j == j) {
|
if (c.var() == j) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
T & wv = m_work_vector.m_data[c.m_j];
|
T & wv = m_work_vector.m_data[c.var()];
|
||||||
bool was_zero = is_zero(wv);
|
bool was_zero = is_zero(wv);
|
||||||
wv -= alpha * c.m_value;
|
wv -= alpha * c.coeff();
|
||||||
if (was_zero)
|
if (was_zero)
|
||||||
m_work_vector.m_index.push_back(c.m_j);
|
m_work_vector.m_index.push_back(c.var());
|
||||||
else {
|
else {
|
||||||
if (is_zero(wv)) {
|
if (is_zero(wv)) {
|
||||||
m_work_vector.erase_from_index(c.m_j);
|
m_work_vector.erase_from_index(c.var());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,7 +378,7 @@ public:
|
||||||
L ret = zero_of_type<L>();
|
L ret = zero_of_type<L>();
|
||||||
lp_assert(row < m_rows.size());
|
lp_assert(row < m_rows.size());
|
||||||
for (auto & it : m_rows[row]) {
|
for (auto & it : m_rows[row]) {
|
||||||
ret += w[it.m_j] * it.get_val();
|
ret += w[it.var()] * it.coeff();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -402,7 +390,7 @@ public:
|
||||||
column_cell_plus(const column_cell & c, const static_matrix& A) :
|
column_cell_plus(const column_cell & c, const static_matrix& A) :
|
||||||
m_c(c), m_A(A) {}
|
m_c(c), m_A(A) {}
|
||||||
unsigned var() const { return m_c.var(); }
|
unsigned var() const { return m_c.var(); }
|
||||||
const T & coeff() const { return m_A.m_rows[var()][m_c.m_offset].get_val(); }
|
const T & coeff() const { return m_A.m_rows[var()][m_c.offset()].coeff(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,21 +47,21 @@ template <typename T, typename X> bool static_matrix<T, X>::pivot_row_to_row_giv
|
||||||
T alpha = -get_val(c);
|
T alpha = -get_val(c);
|
||||||
lp_assert(!is_zero(alpha));
|
lp_assert(!is_zero(alpha));
|
||||||
auto & rowii = m_rows[ii];
|
auto & rowii = m_rows[ii];
|
||||||
remove_element(rowii, rowii[c.m_offset]);
|
remove_element(rowii, rowii[c.offset()]);
|
||||||
scan_row_ii_to_offset_vector(rowii);
|
scan_row_ii_to_offset_vector(rowii);
|
||||||
unsigned prev_size_ii = rowii.size();
|
unsigned prev_size_ii = rowii.size();
|
||||||
// run over the pivot row and update row ii
|
// run over the pivot row and update row ii
|
||||||
for (const auto & iv : m_rows[i]) {
|
for (const auto & iv : m_rows[i]) {
|
||||||
unsigned j = iv.var();
|
unsigned j = iv.var();
|
||||||
if (j == pivot_col) continue;
|
if (j == pivot_col) continue;
|
||||||
T alv = alpha * iv.m_value;
|
T alv = alpha * iv.coeff();
|
||||||
lp_assert(!is_zero(iv.m_value));
|
lp_assert(!is_zero(iv.coeff()));
|
||||||
int j_offs = m_vector_of_row_offsets[j];
|
int j_offs = m_vector_of_row_offsets[j];
|
||||||
if (j_offs == -1) { // it is a new element
|
if (j_offs == -1) { // it is a new element
|
||||||
add_new_element(ii, j, alv);
|
add_new_element(ii, j, alv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rowii[j_offs].m_value += alv;
|
rowii[j_offs].coeff() += alv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// clean the work vector
|
// clean the work vector
|
||||||
|
@ -71,7 +71,7 @@ template <typename T, typename X> bool static_matrix<T, X>::pivot_row_to_row_giv
|
||||||
|
|
||||||
// remove zeroes
|
// remove zeroes
|
||||||
for (unsigned k = rowii.size(); k-- > 0; ) {
|
for (unsigned k = rowii.size(); k-- > 0; ) {
|
||||||
if (is_zero(rowii[k].m_value))
|
if (is_zero(rowii[k].coeff()))
|
||||||
remove_element(rowii, rowii[k]);
|
remove_element(rowii, rowii[k]);
|
||||||
}
|
}
|
||||||
return !rowii.empty();
|
return !rowii.empty();
|
||||||
|
@ -188,7 +188,7 @@ template <typename T, typename X> void static_matrix<T, X>::copy_column_to_in
|
||||||
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_row(unsigned row) const {
|
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_row(unsigned row) const {
|
||||||
T ret = numeric_traits<T>::zero();
|
T ret = numeric_traits<T>::zero();
|
||||||
for (auto & t : m_rows[row]) {
|
for (auto & t : m_rows[row]) {
|
||||||
T a = abs(t.get_val());
|
T a = abs(t.coeff());
|
||||||
if (a > ret) {
|
if (a > ret) {
|
||||||
ret = a;
|
ret = a;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ template <typename T, typename X> T static_matrix<T, X>::get_min_abs_in_row(u
|
||||||
bool first_time = true;
|
bool first_time = true;
|
||||||
T ret = numeric_traits<T>::zero();
|
T ret = numeric_traits<T>::zero();
|
||||||
for (auto & t : m_rows[row]) {
|
for (auto & t : m_rows[row]) {
|
||||||
T a = abs(t.get_val());
|
T a = abs(t.coeff());
|
||||||
if (first_time) {
|
if (first_time) {
|
||||||
ret = a;
|
ret = a;
|
||||||
first_time = false;
|
first_time = false;
|
||||||
|
@ -245,7 +245,7 @@ template <typename T, typename X> void static_matrix<T, X>::check_consistency
|
||||||
for (auto & t : m_rows[i]) {
|
for (auto & t : m_rows[i]) {
|
||||||
std::pair<unsigned, unsigned> p(i, t.var());
|
std::pair<unsigned, unsigned> p(i, t.var());
|
||||||
lp_assert(by_rows.find(p) == by_rows.end());
|
lp_assert(by_rows.find(p) == by_rows.end());
|
||||||
by_rows[p] = t.get_val();
|
by_rows[p] = t.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::unordered_map<std::pair<unsigned, unsigned>, T> by_cols;
|
std::unordered_map<std::pair<unsigned, unsigned>, T> by_cols;
|
||||||
|
@ -311,7 +311,7 @@ template <typename T, typename X> void static_matrix<T, X>::cross_out_row_fro
|
||||||
template <typename T, typename X> T static_matrix<T, X>::get_elem(unsigned i, unsigned j) const { // should not be used in efficient code !!!!
|
template <typename T, typename X> T static_matrix<T, X>::get_elem(unsigned i, unsigned j) const { // should not be used in efficient code !!!!
|
||||||
for (auto & t : m_rows[i]) {
|
for (auto & t : m_rows[i]) {
|
||||||
if (t.var() == j) {
|
if (t.var() == j) {
|
||||||
return t.get_val();
|
return t.coeff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return numeric_traits<T>::zero();
|
return numeric_traits<T>::zero();
|
||||||
|
@ -329,8 +329,8 @@ template <typename T, typename X> T static_matrix<T, X>::get_balance() const
|
||||||
template <typename T, typename X> T static_matrix<T, X>::get_row_balance(unsigned row) const {
|
template <typename T, typename X> T static_matrix<T, X>::get_row_balance(unsigned row) const {
|
||||||
T ret = zero_of_type<T>();
|
T ret = zero_of_type<T>();
|
||||||
for (auto & t : m_rows[row]) {
|
for (auto & t : m_rows[row]) {
|
||||||
if (numeric_traits<T>::is_zero(t.get_val())) continue;
|
if (numeric_traits<T>::is_zero(t.coeff())) continue;
|
||||||
T a = abs(t.get_val());
|
T a = abs(t.coeff());
|
||||||
numeric_traits<T>::log(a);
|
numeric_traits<T>::log(a);
|
||||||
ret += a * a;
|
ret += a * a;
|
||||||
}
|
}
|
||||||
|
@ -348,11 +348,11 @@ template <typename T, typename X> bool static_matrix<T, X>::is_correct() const {
|
||||||
s.insert(rc.var());
|
s.insert(rc.var());
|
||||||
if (rc.var() >= m_columns.size())
|
if (rc.var() >= m_columns.size())
|
||||||
return false;
|
return false;
|
||||||
if (rc.m_offset >= m_columns[rc.var()].size())
|
if (rc.offset() >= m_columns[rc.var()].size())
|
||||||
return false;
|
return false;
|
||||||
if (rc.get_val() != get_val(m_columns[rc.var()][rc.m_offset]))
|
if (rc.coeff() != get_val(m_columns[rc.var()][rc.offset()]))
|
||||||
return false;
|
return false;
|
||||||
if (is_zero(rc.get_val())) {
|
if (is_zero(rc.coeff())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,24 +369,21 @@ template <typename T, typename X> bool static_matrix<T, X>::is_correct() const {
|
||||||
s.insert(cc.var());
|
s.insert(cc.var());
|
||||||
if (cc.var() >= m_rows.size())
|
if (cc.var() >= m_rows.size())
|
||||||
return false;
|
return false;
|
||||||
if (cc.m_offset >= m_rows[cc.var()].size())
|
if (cc.offset() >= m_rows[cc.var()].size())
|
||||||
return false;
|
return false;
|
||||||
if (get_val(cc) != m_rows[cc.var()][cc.m_offset].get_val())
|
if (get_val(cc) != m_rows[cc.var()][cc.offset()].coeff())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X>
|
template <typename T, typename X>
|
||||||
void static_matrix<T, X>::remove_element(vector<row_cell<T>> & row_vals, row_cell<T> & row_el_iv) {
|
void static_matrix<T, X>::remove_element(vector<row_cell<T>> & row_vals, row_cell<T> & row_el_iv) {
|
||||||
unsigned column_offset = row_el_iv.m_offset;
|
unsigned column_offset = row_el_iv.offset();
|
||||||
auto & column_vals = m_columns[row_el_iv.var()];
|
auto & column_vals = m_columns[row_el_iv.var()];
|
||||||
column_cell& cs = m_columns[row_el_iv.var()][column_offset];
|
column_cell& cs = m_columns[row_el_iv.var()][column_offset];
|
||||||
unsigned row_offset = cs.m_offset;
|
unsigned row_offset = cs.offset();
|
||||||
if (column_offset != column_vals.size() - 1) {
|
if (column_offset != column_vals.size() - 1) {
|
||||||
auto & cc = column_vals[column_offset] = column_vals.back(); // copy from the tail
|
auto & cc = column_vals[column_offset] = column_vals.back(); // copy from the tail
|
||||||
m_rows[cc.var()][cc.offset()].offset() = column_offset;
|
m_rows[cc.var()][cc.offset()].offset() = column_offset;
|
||||||
|
|
|
@ -64,22 +64,21 @@ namespace smt {
|
||||||
expr* s = nullptr, *r = nullptr;
|
expr* s = nullptr, *r = nullptr;
|
||||||
expr* e = ctx.bool_var2expr(lit.var());
|
expr* e = ctx.bool_var2expr(lit.var());
|
||||||
expr_ref id(a().mk_int(e->get_id()), m);
|
expr_ref id(a().mk_int(e->get_id()), m);
|
||||||
unsigned idx = 0;
|
|
||||||
VERIFY(str().is_in_re(e, s, r));
|
VERIFY(str().is_in_re(e, s, r));
|
||||||
sort* seq_sort = m.get_sort(s);
|
sort* seq_sort = m.get_sort(s);
|
||||||
vector<expr_ref_vector> patterns;
|
vector<expr_ref_vector> patterns;
|
||||||
auto mk_cont = [&](unsigned idx) {
|
auto mk_cont = [&](unsigned idx) {
|
||||||
return sk().mk("seq.cont", id, a().mk_int(idx), seq_sort);
|
return sk().mk("seq.cont", id, a().mk_int(idx), seq_sort);
|
||||||
};
|
};
|
||||||
|
unsigned idx = 0;
|
||||||
if (seq_rw().is_re_contains_pattern(r, patterns)) {
|
if (seq_rw().is_re_contains_pattern(r, patterns)) {
|
||||||
expr_ref t(m);
|
|
||||||
expr_ref_vector ts(m);
|
expr_ref_vector ts(m);
|
||||||
ts.push_back(mk_cont(idx));
|
ts.push_back(mk_cont(idx));
|
||||||
for (auto const& p : patterns) {
|
for (auto const& p : patterns) {
|
||||||
ts.append(p);
|
ts.append(p);
|
||||||
ts.push_back(mk_cont(++idx));
|
ts.push_back(mk_cont(++idx));
|
||||||
}
|
}
|
||||||
t = th.mk_concat(ts, seq_sort);
|
expr_ref t = th.mk_concat(ts, seq_sort);
|
||||||
th.propagate_eq(lit, s, t, true);
|
th.propagate_eq(lit, s, t, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1012,6 +1012,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool internalize_atom(app * atom, bool gate_ctx) {
|
bool internalize_atom(app * atom, bool gate_ctx) {
|
||||||
|
TRACE("arith", tout << mk_pp(atom, m) << "\n";);
|
||||||
SASSERT(!ctx().b_internalized(atom));
|
SASSERT(!ctx().b_internalized(atom));
|
||||||
expr* n1, *n2;
|
expr* n1, *n2;
|
||||||
rational r;
|
rational r;
|
||||||
|
@ -1722,7 +1723,9 @@ public:
|
||||||
final_check_status st = FC_DONE;
|
final_check_status st = FC_DONE;
|
||||||
switch (is_sat) {
|
switch (is_sat) {
|
||||||
case l_true:
|
case l_true:
|
||||||
TRACE("arith", display(tout););
|
TRACE("arith", /*display(tout);*/
|
||||||
|
ctx().display(tout);
|
||||||
|
);
|
||||||
switch (check_lia()) {
|
switch (check_lia()) {
|
||||||
case l_true:
|
case l_true:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1173,6 +1173,8 @@ bool theory_seq::reduce_length(unsigned i, unsigned j, bool front, expr_ref_vect
|
||||||
expr_ref lenl = mk_len(l);
|
expr_ref lenl = mk_len(l);
|
||||||
expr_ref lenr = mk_len(r);
|
expr_ref lenr = mk_len(r);
|
||||||
literal lit = mk_eq(lenl, lenr, false);
|
literal lit = mk_eq(lenl, lenr, false);
|
||||||
|
ctx.mark_as_relevant(lit);
|
||||||
|
|
||||||
if (ctx.get_assignment(lit) == l_true) {
|
if (ctx.get_assignment(lit) == l_true) {
|
||||||
expr_ref_vector lhs(m), rhs(m);
|
expr_ref_vector lhs(m), rhs(m);
|
||||||
lhs.append(l2, ls2);
|
lhs.append(l2, ls2);
|
||||||
|
@ -2753,7 +2755,6 @@ bool theory_seq::lower_bound(expr* e, rational& lo) const {
|
||||||
VERIFY(m_autil.is_int(e));
|
VERIFY(m_autil.is_int(e));
|
||||||
bool is_strict = true;
|
bool is_strict = true;
|
||||||
return m_arith_value.get_lo(e, lo, is_strict) && !is_strict && lo.is_int();
|
return m_arith_value.get_lo(e, lo, is_strict) && !is_strict && lo.is_int();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool theory_seq::upper_bound(expr* e, rational& hi) const {
|
bool theory_seq::upper_bound(expr* e, rational& hi) const {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue