3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 11:55:51 +00:00

add cancellations

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

syntax errors

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

use std::vector instead of vector in cut_solver temporarily

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

fix in is_upper_bound, is_lower_bound

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

add bound() for polynomial, needs more testing

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

work on resolve

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

implement resolve()

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

implement improves()

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

replace low_bound by lower_bound

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

work on cut_solver

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

work on cut_solver

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

better printing in cut_solver.h

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

add value vector to cut_solver

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

work on bound propagaion for cut_solver

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

bound propagation for integer inequalites

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

bound propagation for integer inequalites

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

bound propagattions on integers

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

adding m_explanation field to cut_solver

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

simplify bound propagation in cut_solver

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

calculate conflict explanation

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

change m_explanation type to a set

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

making cut_solver a member of int_solver, missing push/pop support

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

Nikolaj's comments

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

Nikolaj's comments

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

return explanations from cut_solver and hook up push/pop

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

hook up push/pop

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

using resize of std::vector

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

it is a big squashed commit

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

rename hpp to cpp

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

fixes in push/pop of cut_solver

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

return simple inequalities a part of a conflict

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

work on propagation and the main loop

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

add file

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

work on cut_solver

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

init m_v[j], the var values only when j is fixed

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

cut_solver

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

handle decide in cut_solver

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

start on resolve_conflict

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

start on resolve_conflict

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

remove cut_solver_def.h

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

in the middle

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

change signature of resolve

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

fix the domain of the decided var

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

work on tightening of ineqs

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

work on tight ineqs

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

work on tightening

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

work on tightening

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

resolve conflict

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

fix in usage of resolve()

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

work on conflict resolution

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

cut_solver is not a template

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

represent var_info as a class, not a struct

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

make literal a class

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

better resolve_conflict scheme, and switch to *constraints in literals

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

debug conflict resolution in cut_solver

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

switch to vector

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

remove nondetermenistic behavior from cut_solver

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

debug resolve conflict

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

fix backjump

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

fix backjump

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

fix backjump

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

fix backjump

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

dumb explanation

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

get rid of a parameter

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

add lemmas origins

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

use lemma_origins to provide correct explanations

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

use lemma_origins to provide correct explanations

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

store lemmas in a separate vector

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

use std::unordered_set for m_dependent_constraints

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

use std::unordered_set for m_dependent_constraints

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

fix bugs with lemmas

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

finding conflicting cores

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

switch from changed variables to active_set

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

less active constraints

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

work on cut_solver.h

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

propagate simple constraing immediately

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

propagate simple constraints immediately

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

fixing bugs with active set

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

remove const_cast

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

towards unbounded variables

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

toward unbounded variables

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

toward unbounded variables

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

make lemmas_origins a set

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

use correct hash and equal in m_lemma_origins

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

add testing code

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

add testing code

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

debug

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

debug unlimited vars

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

take in Nikolaj's comments and improvements

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

address the comments

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

handle unlimited vars in check_inconsistent

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

debug

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

detect trivial polynomials in resolve

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

Nikolaj's changes

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

simplify handling of m_global_bound_var

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

decide on m_global_bound_var if it is not fixed

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

simplify m_global_bound_var

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

remove m_global_bound_var, simplify the indexing of var_infos of cut_solver

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

do not run cut_solver with vars without any bound

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

small changes

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

add cancellation in cut_solver

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

do not pop lemmas during a cut_solver run

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

treating cut_solver as an heurisitic

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

prepare for cut_solver returning undef

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

simplify work with active_set in cut_solver, add stats

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

simplify var_info literals

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

fix a bug in fill_conflict_explanation

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

fix a bug in the conflict explanation

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

add timeout to validate_* in theory_lra.cpp

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

simplify cut_solver, no special treatment for simple constraints

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

cleanup the cancel story

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

cleanup cancelling

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

fix a bug in push/pop of cut_solver

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

extract a method in int_solver

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

some progress with the new scheme

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

add testing code

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

fixes in test and in literal creation

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

fix a bug in bound propagation in cut_solver.h

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

simplify cut_solver

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

provide valid conflict explanation

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

use a lazy push in stacked_map

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

use a lazy push in stacked_map

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

optimize stack operations on var_info's domains

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

fix a bug in tightening

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

use the standard tactics from qflia_tactic

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

spread the var domain stack over literals

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

spread the var domain stack over literals

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

avoid cycling in cut_solver.h and fixes in push/pop

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

fixes after rebase

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2017-10-03 11:50:21 -07:00
parent 58ca4518e5
commit 6202b2f2e4
103 changed files with 7035 additions and 5106 deletions

View file

@ -0,0 +1,420 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#include "util/vector.h"
#include <utility>
#include <set>
#include "util/lp/static_matrix.h"
namespace lp {
// each assignment for this matrix should be issued only once!!!
template <typename T, typename X>
void static_matrix<T, X>::init_row_columns(unsigned m, unsigned n) {
lp_assert(m_rows.size() == 0 && m_columns.size() == 0);
for (unsigned i = 0; i < m; i++){
m_rows.push_back(row_strip());
}
for (unsigned j = 0; j < n; j++){
m_columns.push_back(column_strip());
}
}
template <typename T, typename X> void static_matrix<T, X>::scan_row_ii_to_offset_vector(const row_strip & rvals) {
for (unsigned j = 0; j < rvals.size(); j++)
m_vector_of_row_offsets[rvals[j].m_j] = j;
}
template <typename T, typename X> bool static_matrix<T, X>::pivot_row_to_row_given_cell(unsigned i, column_cell & c, unsigned pivot_col) {
unsigned ii = c.m_i;
lp_assert(i < row_count() && ii < column_count() && i != ii);
T alpha = -get_val(c);
lp_assert(!is_zero(alpha));
auto & rowii = m_rows[ii];
remove_element(rowii, rowii[c.m_offset]);
scan_row_ii_to_offset_vector(rowii);
unsigned prev_size_ii = rowii.size();
// run over the pivot row and update row ii
for (const auto & iv : m_rows[i]) {
unsigned j = iv.m_j;
if (j == pivot_col) continue;
T alv = alpha * iv.m_value;
lp_assert(!is_zero(iv.m_value));
int j_offs = m_vector_of_row_offsets[j];
if (j_offs == -1) { // it is a new element
add_new_element(ii, j, alv);
}
else {
rowii[j_offs].m_value += alv;
}
}
// clean the work vector
for (unsigned k = 0; k < prev_size_ii; k++) {
m_vector_of_row_offsets[rowii[k].m_j] = -1;
}
// remove zeroes
for (unsigned k = rowii.size(); k-- > 0; ) {
if (is_zero(rowii[k].m_value))
remove_element(rowii, rowii[k]);
}
return !rowii.empty();
}
// constructor that copies columns of the basis from A
template <typename T, typename X>
static_matrix<T, X>::static_matrix(static_matrix const &A, unsigned * /* basis */) :
m_vector_of_row_offsets(A.column_count(), numeric_traits<T>::zero()) {
unsigned m = A.row_count();
init_row_columns(m, m);
while (m--) {
for (auto & col : A.m_columns[m]){
set(col.m_i, m, A.get_value_of_column_cell(col));
}
}
}
template <typename T, typename X> void static_matrix<T, X>::clear() {
m_vector_of_row_offsets.clear();
m_rows.clear();
m_columns.clear();
}
template <typename T, typename X> void static_matrix<T, X>::init_vector_of_row_offsets() {
m_vector_of_row_offsets.clear();
m_vector_of_row_offsets.resize(column_count(), -1);
}
template <typename T, typename X> void static_matrix<T, X>::init_empty_matrix(unsigned m, unsigned n) {
init_vector_of_row_offsets();
init_row_columns(m, n);
}
template <typename T, typename X> unsigned static_matrix<T, X>::lowest_row_in_column(unsigned col) {
lp_assert(col < column_count());
column_strip & colstrip = m_columns[col];
lp_assert(colstrip.size() > 0);
unsigned ret = 0;
for (auto & t : colstrip) {
if (t.m_i > ret) {
ret = t.m_i;
}
}
return ret;
}
template <typename T, typename X> void static_matrix<T, X>::add_columns_at_the_end(unsigned delta) {
for (unsigned i = 0; i < delta; i++)
add_column();
}
template <typename T, typename X> void static_matrix<T, X>::forget_last_columns(unsigned how_many_to_forget) {
lp_assert(m_columns.size() >= how_many_to_forget);
unsigned j = column_count() - 1;
for (; how_many_to_forget > 0; how_many_to_forget--) {
remove_last_column(j --);
}
}
template <typename T, typename X> void static_matrix<T, X>::remove_last_column(unsigned j) {
column_strip & col = m_columns.back();
for (auto & it : col) {
auto & row = m_rows[it.m_i];
unsigned offset = row.size() - 1;
for (auto row_it = row.rbegin(); row_it != row.rend(); row_it ++) {
if (row_it->m_j == j) {
row.erase(row.begin() + offset);
break;
}
offset--;
}
}
m_columns.pop_back();
m_vector_of_row_offsets.pop_back();
}
template <typename T, typename X> void static_matrix<T, X>::set(unsigned row, unsigned col, T const & val) {
if (numeric_traits<T>::is_zero(val)) return;
lp_assert(row < row_count() && col < column_count());
auto & r = m_rows[row];
unsigned offs_in_cols = static_cast<unsigned>(m_columns[col].size());
m_columns[col].push_back(make_column_cell(row, static_cast<unsigned>(r.size())));
r.push_back(make_row_cell(col, offs_in_cols, val));
}
template <typename T, typename X>
std::set<std::pair<unsigned, unsigned>> static_matrix<T, X>::get_domain() {
std::set<std::pair<unsigned, unsigned>> ret;
for (unsigned i = 0; i < m_rows.size(); i++) {
for (auto it : m_rows[i]) {
ret.insert(std::make_pair(i, it.m_j));
}
}
return ret;
}
template <typename T, typename X> void static_matrix<T, X>::copy_column_to_indexed_vector (unsigned j, indexed_vector<T> & v) const {
lp_assert(j < m_columns.size());
for (auto & it : m_columns[j]) {
const T& val = get_val(it);
if (!is_zero(val))
v.set_value(val, it.m_i);
}
}
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_row(unsigned row) const {
T ret = numeric_traits<T>::zero();
for (auto & t : m_rows[row]) {
T a = abs(t.get_val());
if (a > ret) {
ret = a;
}
}
return ret;
}
template <typename T, typename X> T static_matrix<T, X>::get_min_abs_in_row(unsigned row) const {
bool first_time = true;
T ret = numeric_traits<T>::zero();
for (auto & t : m_rows[row]) {
T a = abs(t.get_val());
if (first_time) {
ret = a;
first_time = false;
} else if (a < ret) {
ret = a;
}
}
return ret;
}
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_column(unsigned column) const {
T ret = numeric_traits<T>::zero();
for (const auto & t : m_columns[column]) {
T a = abs(get_val(t));
if (a > ret) {
ret = a;
}
}
return ret;
}
template <typename T, typename X> T static_matrix<T, X>::get_min_abs_in_column(unsigned column) const {
bool first_time = true;
T ret = numeric_traits<T>::zero();
for (auto & t : m_columns[column]) {
T a = abs(get_val(t));
if (first_time) {
first_time = false;
ret = a;
} else if (a < ret) {
ret = a;
}
}
return ret;
}
#ifdef Z3DEBUG
template <typename T, typename X> void static_matrix<T, X>::check_consistency() {
std::unordered_map<std::pair<unsigned, unsigned>, T> by_rows;
for (int i = 0; i < m_rows.size(); i++){
for (auto & t : m_rows[i]) {
std::pair<unsigned, unsigned> p(i, t.m_j);
lp_assert(by_rows.find(p) == by_rows.end());
by_rows[p] = t.get_val();
}
}
std::unordered_map<std::pair<unsigned, unsigned>, T> by_cols;
for (int i = 0; i < m_columns.size(); i++){
for (auto & t : m_columns[i]) {
std::pair<unsigned, unsigned> p(t.m_i, i);
lp_assert(by_cols.find(p) == by_cols.end());
by_cols[p] = get_val(t);
}
}
lp_assert(by_rows.size() == by_cols.size());
for (auto & t : by_rows) {
auto ic = by_cols.find(t.first);
if (ic == by_cols.end()){
//std::cout << "rows have pair (" << t.first.first <<"," << t.first.second
// << "), but columns don't " << std::endl;
}
lp_assert(ic != by_cols.end());
lp_assert(t.second == ic->second);
}
}
#endif
template <typename T, typename X> void static_matrix<T, X>::cross_out_row(unsigned k) {
#ifdef Z3DEBUG
check_consistency();
#endif
cross_out_row_from_columns(k, m_rows[k]);
fix_row_indices_in_each_column_for_crossed_row(k);
m_rows.erase(m_rows.begin() + k);
#ifdef Z3DEBUG
regen_domain();
check_consistency();
#endif
}
template <typename T, typename X> void static_matrix<T, X>::fix_row_indices_in_each_column_for_crossed_row(unsigned k) {
for (unsigned j = 0; j < m_columns.size(); j++) {
auto & col = m_columns[j];
for (int i = 0; i < col.size(); i++) {
if (col[i].m_i > k) {
col[i].m_i--;
}
}
}
}
template <typename T, typename X> void static_matrix<T, X>::cross_out_row_from_columns(unsigned k, row_strip & row) {
for (auto & t : row) {
cross_out_row_from_column(t.m_j, k);
}
}
template <typename T, typename X> void static_matrix<T, X>::cross_out_row_from_column(unsigned col, unsigned k) {
auto & s = m_columns[col];
for (unsigned i = 0; i < s.size(); i++) {
if (s[i].m_i == k) {
s.erase(s.begin() + i);
break;
}
}
}
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]) {
if (t.m_j == j) {
return t.get_val();
}
}
return numeric_traits<T>::zero();
}
template <typename T, typename X> T static_matrix<T, X>::get_balance() const {
T ret = zero_of_type<T>();
for (unsigned i = 0; i < row_count(); i++) {
ret += get_row_balance(i);
}
return ret;
}
template <typename T, typename X> T static_matrix<T, X>::get_row_balance(unsigned row) const {
T ret = zero_of_type<T>();
for (auto & t : m_rows[row]) {
if (numeric_traits<T>::is_zero(t.get_val())) continue;
T a = abs(t.get_val());
numeric_traits<T>::log(a);
ret += a * a;
}
return ret;
}
template <typename T, typename X> bool static_matrix<T, X>::is_correct() const {
for (unsigned i = 0; i < m_rows.size(); i++) {
auto &r = m_rows[i];
std::unordered_set<unsigned> s;
for (auto & rc : r) {
if (s.find(rc.m_j) != s.end()) {
std::cout << "found column " << rc.m_j << " twice in a row " << i << std::endl;
return false;
}
s.insert(rc.m_j);
if (rc.m_j >= m_columns.size())
return false;
if (rc.m_offset >= m_columns[rc.m_j].size())
return false;
if (rc.get_val() != get_val(m_columns[rc.m_j][rc.m_offset]))
return false;
if (is_zero(rc.get_val())) {
std::cout << "found zero column " << rc.m_j << " in row " << i << std::endl;
return false;
}
}
}
for (unsigned j = 0; j < m_columns.size(); j++) {
auto & c = m_columns[j];
std::unordered_set<unsigned> s;
for (auto & cc : c) {
if (s.find(cc.m_i) != s.end()) {
std::cout << "found row " << cc.m_i << " twice in a column " << j << std::endl;
return false;
}
s.insert(cc.m_i);
if (cc.m_i >= m_rows.size())
return false;
if (cc.m_offset >= m_rows[cc.m_i].size())
return false;
if (get_val(cc) != m_rows[cc.m_i][cc.m_offset].get_val())
return false;
}
}
return true;
}
template <typename T, typename X>
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;
auto & column_vals = m_columns[row_el_iv.m_j];
column_cell& cs = m_columns[row_el_iv.m_j][column_offset];
unsigned row_offset = cs.m_offset;
if (column_offset != column_vals.size() - 1) {
auto & cc = column_vals[column_offset] = column_vals.back(); // copy from the tail
m_rows[cc.m_i][cc.m_offset].m_offset = column_offset;
}
if (row_offset != row_vals.size() - 1) {
auto & rc = row_vals[row_offset] = row_vals.back(); // copy from the tail
m_columns[rc.m_j][rc.m_offset].m_offset = row_offset;
}
column_vals.pop_back();
row_vals.pop_back();
}
template <typename T, typename X>
void static_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];
unsigned row_el_offs = static_cast<unsigned>(row_vals.size());
unsigned col_el_offs = static_cast<unsigned>(col_vals.size());
row_vals.push_back(row_cell<T>(col, col_el_offs, val));
col_vals.push_back(column_cell(row, row_el_offs));
}
}