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