Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
FlexibleSparseMatrix.cpp
Go to the documentation of this file.
2
9
10namespace storm {
11namespace storage {
12template<typename ValueType>
13FlexibleSparseMatrix<ValueType>::FlexibleSparseMatrix(index_type rows) : data(rows), columnCount(0), nonzeroEntryCount(0) {
14 // Intentionally left empty.
15}
16
17template<typename ValueType>
18FlexibleSparseMatrix<ValueType>::FlexibleSparseMatrix(storm::storage::SparseMatrix<ValueType> const& matrix, bool setAllValuesToOne, bool revertEquationSystem)
19 : data(matrix.getRowCount()),
20 columnCount(matrix.getColumnCount()),
21 nonzeroEntryCount(matrix.getNonzeroEntryCount()),
22 trivialRowGrouping(matrix.hasTrivialRowGrouping()) {
23 STORM_LOG_THROW(!revertEquationSystem || trivialRowGrouping, storm::exceptions::InvalidArgumentException, "Illegal option for creating flexible matrix.");
24
25 if (!trivialRowGrouping) {
26 rowGroupIndices = matrix.getRowGroupIndices();
27 }
28 for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) {
29 typename storm::storage::SparseMatrix<ValueType>::const_rows row = matrix.getRow(rowIndex);
30 reserveInRow(rowIndex, row.getNumberOfEntries());
31 for (auto const& element : row) {
32 // If the probability is zero, we skip this entry.
33 if (storm::utility::isZero(element.getValue())) {
34 if (revertEquationSystem && rowIndex == element.getColumn()) {
35 getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one<ValueType>());
36 } else {
37 continue;
38 }
39 }
40 if (setAllValuesToOne) {
41 if (revertEquationSystem && element.getColumn() == rowIndex && storm::utility::isOne(element.getValue())) {
42 continue;
43 } else {
44 getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one<ValueType>());
45 }
46 } else {
47 if (revertEquationSystem) {
48 if (element.getColumn() == rowIndex) {
49 if (storm::utility::isOne(element.getValue())) {
50 continue;
51 }
52 getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one<ValueType>() - element.getValue());
53 } else {
54 getRow(rowIndex).emplace_back(element.getColumn(), -element.getValue());
55 }
56 } else {
57 getRow(rowIndex).emplace_back(element);
58 }
59 }
60 }
61 }
62}
63
64template<typename ValueType>
66 this->data[row].reserve(numberOfElements);
67}
68
69template<typename ValueType>
73
74template<typename ValueType>
76 return this->data[index];
77}
78
79template<typename ValueType>
81 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(), "Invalid rowGroup.");
82 STORM_LOG_ASSERT(offset < this->getRowGroupSize(rowGroup), "Invalid offset.");
83 return getRow(rowGroupIndices[rowGroup] + offset);
84}
85
86template<typename ValueType>
88 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(), "Invalid rowGroup.");
89 STORM_LOG_ASSERT(offset < this->getRowGroupSize(rowGroup), "Invalid offset.");
90 return getRow(rowGroupIndices[rowGroup] + offset);
91}
92
93template<typename ValueType>
94std::vector<typename FlexibleSparseMatrix<ValueType>::index_type> const& FlexibleSparseMatrix<ValueType>::getRowGroupIndices() const {
95 return rowGroupIndices;
96}
97
98template<typename ValueType>
102
103template<typename ValueType>
107
108template<typename ValueType>
112
113template<typename ValueType>
115 return rowGroupIndices.size() - 1;
116}
117
118template<typename ValueType>
120 return rowGroupIndices[group + 1] - rowGroupIndices[group];
121}
122
123template<typename ValueType>
125 ValueType sum = storm::utility::zero<ValueType>();
126 for (auto const& element : getRow(row)) {
127 sum += element.getValue();
128 }
129 return sum;
130}
131
132template<typename ValueType>
134 this->nonzeroEntryCount = 0;
135 this->columnCount = 0;
136 for (auto const& row : this->data) {
137 for (auto const& element : row) {
138 STORM_LOG_ASSERT(!storm::utility::isZero(element.getValue()), "Entry is 0.");
139 ++this->nonzeroEntryCount;
140 this->columnCount = std::max(element.getColumn() + 1, this->columnCount);
141 }
142 }
143}
144
145template<typename ValueType>
147 for (auto const& row : this->data) {
148 if (!row.empty()) {
149 return false;
150 }
151 }
152 return true;
153}
154
155template<typename ValueType>
157 return trivialRowGrouping;
158}
159
160template<typename ValueType>
162 for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) {
163 auto& row = this->data[rowIndex];
164 if (!rowConstraint.get(rowIndex)) {
165 row.clear();
166 row.shrink_to_fit();
167 continue;
168 }
169 row_type newRow;
170 for (auto const& element : row) {
171 if (columnConstraint.get(element.getColumn())) {
172 newRow.push_back(element);
173 }
174 }
175 row = std::move(newRow);
176 }
177}
178
179template<typename ValueType>
182 STORM_LOG_ERROR_COND(this->columnCount == this->getRowCount(), "insertNewRowsAtEnd only works when the FlexibleMatrix is square but column count is "
183 << columnCount << " and row count is " << this->getRowCount());
184 // ... because otherwise assumptions break when creating the SparseMatrix and we get weird entries for some reason
185 index_type newRowsIndex = data.size();
186 for (index_type i = 0; i < numRows; i++) {
187 row_type newRow;
188 this->data.push_back(newRow);
189 }
190 this->columnCount = getRowCount();
191 return newRowsIndex;
192}
193
194template<typename ValueType>
196 uint_fast64_t numEntries = 0;
197 for (auto const& row : this->data) {
198 numEntries += row.size();
199 }
200
203 uint_fast64_t currRowIndex = 0;
204 auto rowGroupIndexIt = getRowGroupIndices().begin();
205 for (auto const& row : this->data) {
206 if (!hasTrivialRowGrouping()) {
207 while (currRowIndex >= *rowGroupIndexIt) {
208 matrixBuilder.newRowGroup(currRowIndex);
209 ++rowGroupIndexIt;
210 }
211 }
212 for (auto const& entry : row) {
213 matrixBuilder.addNextValue(currRowIndex, entry.getColumn(), entry.getValue());
214 }
215 ++currRowIndex;
216 }
217 // The matrix might end with one or more empty row groups
218 if (!hasTrivialRowGrouping()) {
219 while (currRowIndex >= *rowGroupIndexIt) {
220 matrixBuilder.newRowGroup(currRowIndex);
221 ++rowGroupIndexIt;
222 }
223 }
224 return matrixBuilder.build();
225}
226
227template<typename ValueType>
229 storm::storage::BitVector const& columnConstraint) {
230 uint_fast64_t numEntries = 0;
231 for (uint64_t rowIndex : rowConstraint) {
232 auto const& row = data[rowIndex];
233 for (auto const& entry : row) {
234 if (columnConstraint.get(entry.getColumn())) {
235 ++numEntries;
236 }
237 }
238 }
239 uint_fast64_t numRowGroups = 0;
240 if (!hasTrivialRowGrouping()) {
241 auto lastRowGroupIndexIt = getRowGroupIndices().end() - 1;
242 auto rowGroupIndexIt = getRowGroupIndices().begin();
243 while (rowGroupIndexIt != lastRowGroupIndexIt) {
244 // Check whether the rowGroup will be nonempty
245 uint64_t nextSet = rowConstraint.getNextSetIndex(*rowGroupIndexIt);
246 ++rowGroupIndexIt;
247 if (nextSet < *rowGroupIndexIt) {
248 ++numRowGroups;
249 }
250 }
251 }
252
253 std::vector<uint_fast64_t> oldToNewColumnIndexMapping(getColumnCount(), getColumnCount());
254 uint_fast64_t newColumnIndex = 0;
255 for (uint64_t oldColumnIndex : columnConstraint) {
256 oldToNewColumnIndexMapping[oldColumnIndex] = newColumnIndex++;
257 }
258
259 storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder(rowConstraint.getNumberOfSetBits(), newColumnIndex, numEntries, true, !hasTrivialRowGrouping(),
260 numRowGroups);
261 uint_fast64_t currRowIndex = 0;
262 auto rowGroupIndexIt = getRowGroupIndices().begin();
263 for (uint64_t oldRowIndex : rowConstraint) {
264 if (!hasTrivialRowGrouping() && oldRowIndex >= *rowGroupIndexIt) {
265 matrixBuilder.newRowGroup(currRowIndex);
266 // Skip empty row groups
267 do {
268 ++rowGroupIndexIt;
269 } while (oldRowIndex >= *rowGroupIndexIt);
270 }
271 auto const& row = data[oldRowIndex];
272 for (auto const& entry : row) {
273 if (columnConstraint.get(entry.getColumn())) {
274 matrixBuilder.addNextValue(currRowIndex, oldToNewColumnIndexMapping[entry.getColumn()], entry.getValue());
275 }
276 }
277 ++currRowIndex;
278 }
279 return matrixBuilder.build();
280}
281
282template<typename ValueType>
284 for (auto const& entry : this->getRow(state)) {
285 if (entry.getColumn() < state) {
286 continue;
287 } else if (entry.getColumn() > state) {
288 return false;
289 } else if (entry.getColumn() == state) {
290 return true;
291 }
292 }
293 return false;
294}
295
296template<typename ValueType>
297std::ostream& FlexibleSparseMatrix<ValueType>::printRow(std::ostream& out, index_type const& rowIndex) const {
298 index_type columnIndex = 0;
299 row_type row = this->getRow(rowIndex);
300 for (index_type column = 0; column < this->getColumnCount(); ++column) {
301 if (columnIndex < row.size() && row[columnIndex].getColumn() == column) {
302 // Insert entry
303 out << row[columnIndex].getValue() << "\t";
304 ++columnIndex;
305 } else {
306 // Insert zero
307 out << "0\t";
308 }
309 }
310 return out;
311}
312
313template<typename ValueType>
314std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix<ValueType> const& matrix) {
315 typedef typename FlexibleSparseMatrix<ValueType>::index_type FlexibleIndex;
316
317 // Print column numbers in header.
318 out << "\t\t";
319 for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) {
320 out << i << "\t";
321 }
322 out << '\n';
323
324 if (!matrix.hasTrivialRowGrouping()) {
325 // Iterate over all row groups
326 FlexibleIndex rowGroupCount = matrix.getRowGroupCount();
327 for (FlexibleIndex rowGroup = 0; rowGroup < rowGroupCount; ++rowGroup) {
328 out << "\t---- group " << rowGroup << "/" << (rowGroupCount - 1) << " ---- \n";
329 FlexibleIndex endRow = matrix.rowGroupIndices[rowGroup + 1];
330 // Iterate over all rows.
331 for (FlexibleIndex row = matrix.rowGroupIndices[rowGroup]; row < endRow; ++row) {
332 // Print the actual row.
333 out << rowGroup << "\t(\t";
334 matrix.printRow(out, row);
335 out << "\t)\t" << rowGroup << '\n';
336 }
337 }
338
339 } else {
340 // Iterate over all rows
341 for (FlexibleIndex row = 0; row < matrix.getRowCount(); ++row) {
342 // Print the actual row.
343 out << row << "\t(\t";
344 matrix.printRow(out, row);
345 out << "\t)\t" << row << '\n';
346 }
347 }
348
349 // Print column numbers in footer.
350 out << "\t\t";
351 for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) {
352 out << i << "\t";
353 }
354 out << '\n';
355 return out;
356}
357
358// Explicitly instantiate the matrix.
359template class FlexibleSparseMatrix<double>;
360template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix<double> const& matrix);
361
363template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix<storm::RationalNumber> const& matrix);
364
366template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix<storm::RationalFunction> const& matrix);
367
368} // namespace storage
369} // namespace storm
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
The flexible sparse matrix is used during state elimination.
void reserveInRow(index_type row, index_type numberOfElements)
Reserves space for elements in row.
index_type getRowGroupSize(index_type group) const
Returns the size of the given row group.
index_type getColumnCount() const
Returns the number of columns of the matrix.
value_type getRowSum(index_type row) const
Computes the sum of the entries in a given row.
void updateDimensions()
Recomputes the number of columns and the number of non-zero entries.
index_type getNonzeroEntryCount() const
Returns the cached number of nonzero entries in the matrix.
std::ostream & printRow(std::ostream &out, index_type const &rowIndex) const
Print row.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
storm::storage::SparseMatrix< ValueType > createSparseMatrix()
Creates a sparse matrix from the flexible sparse matrix.
row_type & getRow(index_type)
Returns an object representing the given row.
bool empty() const
Checks if the matrix has no elements.
void filterEntries(storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint)
Erases all entries whose row and column does not satisfy the given rowConstraint and the given column...
index_type getRowCount() const
Returns the number of rows of the matrix.
FlexibleSparseMatrix()=default
Constructs an empty flexible sparse matrix.
bool hasTrivialRowGrouping() const
Retrieves whether the matrix has a (possibly) trivial row grouping.
index_type insertNewRowsAtEnd(index_type numRows)
Inserts new, empty rows at the end of the FlexibleSparseMatrix.
bool rowHasDiagonalElement(storm::storage::sparse::state_type state)
Checks whether the given state has a self-loop with an arbitrary probability in the probability matri...
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
std::vector< storm::storage::MatrixEntry< index_type, value_type > > row_type
This class represents a number of consecutive rows of the matrix.
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:50
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
std::ostream & operator<<(std::ostream &out, ParameterRegion< ParametricType > const &region)
bool isOne(ValueType const &a)
Definition constants.cpp:37
bool isZero(ValueType const &a)
Definition constants.cpp:42
ValueType zero()
Definition constants.cpp:24
ValueType one()
Definition constants.cpp:19