SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Matrix.h
Go to the documentation of this file.
1 #pragma once
2 #include <vector>
3 #include <carl-arith/numbers/numbers.h>
4 
5 namespace smtrat::fmplex {
6 
7 using Rational = mpq_class;
8 
9 class Matrix {
10 
11 // Type definitions ////////////////////////////////////////////////////////////////////////////////
12 public:
13  using RowIndex = std::size_t;
14  using ColIndex = std::size_t;
15  using DataIndex = std::size_t;
16 
17  struct RowEntry {
20  RowEntry(ColIndex col, const Rational& v) : col_index(col), value(v) {}
21  RowEntry() : col_index(0), value(0) {}
22  };
23 
24  struct ColEntry {
27  };
28 
29  using Column = std::vector<ColEntry>;
30 
31 // Members /////////////////////////////////////////////////////////////////////////////////////////
32 private:
33  std::vector<RowEntry> m_data;
34  std::vector<DataIndex> m_row_starts;
35  std::vector<Column> m_cols;
36 
37 // Private methods /////////////////////////////////////////////////////////////////////////////////
38 private:
39  DataIndex row_start_idx(const RowIndex ri) const {
40  assert(ri < m_row_starts.size());
41  return m_row_starts[ri];
42  }
43 
44  DataIndex row_end_idx(const RowIndex ri) const {
45  return (ri >= (m_row_starts.size() - 1)) ? m_data.size() : m_row_starts[ri+1];
46  }
47 
48  std::size_t row_size(const RowIndex ri) const {
49  return row_end_idx(ri) - row_start_idx(ri);
50  }
51 
52 // Public interfaces ///////////////////////////////////////////////////////////////////////////////
53 public:
54  Matrix() {}
55 
56  Matrix(const Matrix& other) = default;
57  Matrix(Matrix&& other) = default;
58 
59  Matrix(std::size_t expected_rows, std::size_t expected_cols) : m_cols(expected_cols) {
60  m_row_starts.reserve(expected_rows);
61  }
62 
63  ~Matrix() = default;
64 
65  Matrix& operator=(const Matrix& other)=default;
66 
67  void reserve(std::size_t n) { m_data.reserve(n); }
68 
69  std::size_t n_rows() const { return m_row_starts.size(); }
70  std::size_t n_cols() const { return m_cols.size(); }
71 
72  std::size_t non_zeros_in_col(const ColIndex ci) const { return m_cols[ci].size(); }
73  std::size_t non_zeros_in_row(const RowIndex ri) const { return row_end_idx(ri) - row_start_idx(ri); }
74  std::size_t non_zeros_total () const { return m_data.size(); }
75 
76  Rational coeff(const RowIndex i, const ColIndex j) const {
77  DataIndex max = row_end_idx(i);
78  for (DataIndex cur = row_start_idx(i); cur < max; ++cur) {
79  if (m_data[cur].col_index == j) return m_data[cur].value;
80  }
81  return Rational(0);
82  }
83 
84 
85  /**
86  * Appends the row contained in the range between begin and end to the matrix.
87  * This assumes the inputs to be of the same iterator-like type pointing to RowEntry's.
88  * @return the row index of the appended row within the matrix.
89  */
90  template<typename It>
91  RowIndex append_row(const It& begin, const It& end) {
92  RowIndex r_idx(m_row_starts.size());
93  m_row_starts.push_back(m_data.size());
94  for (It it = begin; it != end; ++it) {
95  m_cols[it->col_index].push_back(ColEntry {r_idx, static_cast<unsigned>(m_data.size())});
96  m_data.push_back(*it);
97  }
98  return r_idx;
99  }
100 
101 
102  /**
103  * Computes scale_1*A_(i,-) + scale_2*A_(j,-) where i=row_idx_1, j=row_idx_2.
104  * @return a vector containing the elements of the computed row.
105  */
106  std::vector<RowEntry> combine(const RowIndex row_idx_1, const Rational& scale_1,
107  const RowIndex row_idx_2, const Rational& scale_2) const {
108  std::vector<RowEntry> result;
109  result.reserve(3*(row_size(row_idx_1) + row_size(row_idx_2))/4); // just an estimation
110  DataIndex idx_1 = row_start_idx(row_idx_1);
111  DataIndex idx_2 = row_start_idx(row_idx_2);
112  DataIndex end_1 = row_end_idx(row_idx_1);
113  DataIndex end_2 = row_end_idx(row_idx_2);
114 
115  while (idx_1 != end_1 && idx_2 != end_2) {
116  if (m_data[idx_1].col_index < m_data[idx_2].col_index) {
117  result.emplace_back(m_data[idx_1].col_index, scale_1*m_data[idx_1].value);
118  ++idx_1;
119  } else if (m_data[idx_2].col_index < m_data[idx_1].col_index) {
120  result.emplace_back(m_data[idx_2].col_index, scale_2*m_data[idx_2].value);
121  ++idx_2;
122  } else {
123  Rational new_value = scale_1*m_data[idx_1].value + scale_2*m_data[idx_2].value;
124  if (!carl::is_zero(new_value)) {
125  result.emplace_back(m_data[idx_1].col_index, new_value);
126  }
127  ++idx_1;
128  ++idx_2;
129  }
130  }
131  // At most one of the following loops triggers
132  for (; idx_1 != end_1; ++idx_1)
133  result.emplace_back(m_data[idx_1].col_index, scale_1*m_data[idx_1].value);
134  for (; idx_2 != end_2; ++idx_2)
135  result.emplace_back(m_data[idx_2].col_index, scale_2*m_data[idx_2].value);
136 
137  return result;
138  }
139 
140 
141 // Iterators & Views ///////////////////////////////////////////////////////////////////////////////
142 public:
143  struct row_iterator {
144  private:
145  const std::vector<RowEntry>& mr_data;
147  public:
148  row_iterator(const std::vector<RowEntry>& data, DataIndex idx)
149  : mr_data(data), m_curr(idx) {}
150 
151  const RowEntry& operator* () const { return mr_data[m_curr]; }
152  const RowEntry* operator->() const { return &(operator*()); }
153 
154  row_iterator& operator++() { ++m_curr; return *this; }
155 
156  bool operator==(const row_iterator& it) const { return m_curr == it.m_curr; }
157  bool operator!=(const row_iterator& it) const { return m_curr != it.m_curr; }
158  };
159 
162 
163  struct row_view {
164  private:
165  const Matrix& mr_data;
167  public:
170  row_view(const Matrix& m, const RowIndex ri) : mr_data(m), m_row_id(ri) {}
171  };
172 
173  row_view row_entries(const RowIndex ri) const { return row_view(*this, ri); }
174 
175 
176  struct col_iterator {
177  private:
178  Column::const_iterator m_it;
179  const std::vector<RowEntry>& mr_data;
180  public:
181  col_iterator(Column::const_iterator it, const std::vector<RowEntry>& data)
182  : m_it(it), mr_data(data) {}
183 
184  const RowEntry& operator* () const { return mr_data[m_it->position]; }
185  const RowEntry* operator->() const { return &(operator*()); }
186  RowIndex row() const { return m_it->row_index; }
187 
188  col_iterator& operator++() { ++m_it; return *this; }
189 
190  bool operator==(const col_iterator& other) const { return m_it == other.m_it; }
191  bool operator!=(const col_iterator& other) const { return m_it != other.m_it; }
192  };
193 
194  col_iterator col_begin(ColIndex c) const {return col_iterator(m_cols[c].begin(), m_data);}
195  col_iterator col_end (ColIndex c) const {return col_iterator(m_cols[c].end(), m_data);}
196 
197 
198  struct col_view {
199  private:
200  const Matrix& mr_data;
202  public:
205  col_view(const Matrix& m, const ColIndex ci) : mr_data(m), m_col_id(ci) {}
206  };
207 
208  col_view col_entries(const ColIndex ci) const { return col_view(*this, ci); }
209 };
210 
211 
212 inline void gcd_normalize(std::vector<typename Matrix::RowEntry>& row) {
213  Rational gcd = row.front().value.get_num();
214  Rational lcm = row.front().value.get_den();
215  for (const auto& e : row) {
216  gcd = carl::gcd(gcd, e.value.get_num());
217  lcm = carl::lcm(lcm, e.value.get_den());
218  }
219  Rational scale = lcm/gcd;
220  if (!carl::is_one(scale)) {
221  for (auto& e : row) e.value *= scale;
222  }
223 }
224 
225 
226 }
std::vector< DataIndex > m_row_starts
Definition: Matrix.h:34
Rational coeff(const RowIndex i, const ColIndex j) const
Definition: Matrix.h:76
std::vector< ColEntry > Column
Definition: Matrix.h:29
std::size_t non_zeros_in_row(const RowIndex ri) const
Definition: Matrix.h:73
std::vector< RowEntry > m_data
Definition: Matrix.h:33
col_iterator col_begin(ColIndex c) const
Definition: Matrix.h:194
Matrix(const Matrix &other)=default
col_view col_entries(const ColIndex ci) const
Definition: Matrix.h:208
Matrix(std::size_t expected_rows, std::size_t expected_cols)
Definition: Matrix.h:59
col_iterator col_end(ColIndex c) const
Definition: Matrix.h:195
std::size_t non_zeros_total() const
Definition: Matrix.h:74
std::size_t RowIndex
Definition: Matrix.h:13
std::vector< RowEntry > combine(const RowIndex row_idx_1, const Rational &scale_1, const RowIndex row_idx_2, const Rational &scale_2) const
Computes scale_1*A_(i,-) + scale_2*A_(j,-) where i=row_idx_1, j=row_idx_2.
Definition: Matrix.h:106
std::size_t n_cols() const
Definition: Matrix.h:70
DataIndex row_end_idx(const RowIndex ri) const
Definition: Matrix.h:44
Matrix & operator=(const Matrix &other)=default
std::size_t row_size(const RowIndex ri) const
Definition: Matrix.h:48
row_view row_entries(const RowIndex ri) const
Definition: Matrix.h:173
row_iterator row_end(RowIndex r) const
Definition: Matrix.h:161
void reserve(std::size_t n)
Definition: Matrix.h:67
row_iterator row_begin(RowIndex r) const
Definition: Matrix.h:160
RowIndex append_row(const It &begin, const It &end)
Appends the row contained in the range between begin and end to the matrix.
Definition: Matrix.h:91
std::size_t n_rows() const
Definition: Matrix.h:69
Matrix(Matrix &&other)=default
std::size_t DataIndex
Definition: Matrix.h:15
std::size_t ColIndex
Definition: Matrix.h:14
std::size_t non_zeros_in_col(const ColIndex ci) const
Definition: Matrix.h:72
std::vector< Column > m_cols
Definition: Matrix.h:35
DataIndex row_start_idx(const RowIndex ri) const
Definition: Matrix.h:39
mpq_class Rational
Definition: Matrix.h:7
void gcd_normalize(std::vector< typename Matrix::RowEntry > &row)
Definition: Matrix.h:212
Numeric lcm(const Numeric &_valueA, const Numeric &_valueB)
Calculates the least common multiple of the two arguments.
Definition: Numeric.cpp:302
Numeric gcd(const Numeric &_valueA, const Numeric &_valueB)
Calculates the greatest common divisor of the two arguments.
Definition: Numeric.cpp:317
RowEntry(ColIndex col, const Rational &v)
Definition: Matrix.h:20
const std::vector< RowEntry > & mr_data
Definition: Matrix.h:179
bool operator!=(const col_iterator &other) const
Definition: Matrix.h:191
const RowEntry * operator->() const
Definition: Matrix.h:185
Column::const_iterator m_it
Definition: Matrix.h:178
const RowEntry & operator*() const
Definition: Matrix.h:184
col_iterator(Column::const_iterator it, const std::vector< RowEntry > &data)
Definition: Matrix.h:181
bool operator==(const col_iterator &other) const
Definition: Matrix.h:190
col_view(const Matrix &m, const ColIndex ci)
Definition: Matrix.h:205
bool operator==(const row_iterator &it) const
Definition: Matrix.h:156
row_iterator(const std::vector< RowEntry > &data, DataIndex idx)
Definition: Matrix.h:148
const std::vector< RowEntry > & mr_data
Definition: Matrix.h:145
bool operator!=(const row_iterator &it) const
Definition: Matrix.h:157
const RowEntry & operator*() const
Definition: Matrix.h:151
const RowEntry * operator->() const
Definition: Matrix.h:152
row_view(const Matrix &m, const RowIndex ri)
Definition: Matrix.h:170