24template<
typename IndexType,
typename ValueType>
29template<
typename IndexType,
typename ValueType>
34template<
typename IndexType,
typename ValueType>
36 return this->entry.first;
39template<
typename IndexType,
typename ValueType>
41 this->entry.first = column;
44template<
typename IndexType,
typename ValueType>
46 return this->entry.second;
49template<
typename IndexType,
typename ValueType>
51 this->entry.second = value;
54template<
typename IndexType,
typename ValueType>
59template<
typename IndexType,
typename ValueType>
64template<
typename IndexType,
typename ValueType>
66 return this->entry.first == other.entry.first && this->entry.second == other.entry.second;
69template<
typename IndexType,
typename ValueType>
71 return !(*
this == other);
74template<
typename IndexTypePrime,
typename ValueTypePrime>
76 out <<
"(" << entry.getColumn() <<
", " << entry.getValue() <<
")";
80template<
typename ValueType>
83 : initialRowCountSet(rows != 0),
84 initialRowCount(rows),
85 initialColumnCountSet(columns != 0),
86 initialColumnCount(columns),
87 initialEntryCountSet(entries != 0),
88 initialEntryCount(entries),
89 forceInitialDimensions(forceDimensions),
90 hasCustomRowGrouping(hasCustomRowGrouping),
91 initialRowGroupCountSet(rowGroups != 0),
92 initialRowGroupCount(rowGroups),
100 currentRowGroupCount(0) {
102 if (initialRowCountSet) {
103 rowIndications.reserve(initialRowCount + 1);
105 if (initialEntryCountSet) {
106 columnsAndValues.reserve(initialEntryCount);
108 if (hasCustomRowGrouping) {
109 rowGroupIndices = std::vector<index_type>();
111 if (initialRowGroupCountSet && hasCustomRowGrouping) {
112 rowGroupIndices.get().reserve(initialRowGroupCount + 1);
114 rowIndications.push_back(0);
117template<
typename ValueType>
119 : initialRowCountSet(false),
121 initialColumnCountSet(false),
122 initialColumnCount(0),
123 initialEntryCountSet(false),
124 initialEntryCount(0),
125 forceInitialDimensions(false),
126 hasCustomRowGrouping(!matrix.trivialRowGrouping),
127 initialRowGroupCountSet(false),
128 initialRowGroupCount(0),
130 columnsAndValues(
std::move(matrix.columnsAndValues)),
131 rowIndications(
std::move(matrix.rowIndications)),
132 currentEntryCount(matrix.entryCount),
133 currentRowGroupCount() {
134 lastRow = matrix.rowCount == 0 ? 0 : matrix.rowCount - 1;
135 lastColumn = columnsAndValues.empty() ? 0 : columnsAndValues.back().getColumn();
136 highestColumn = matrix.getColumnCount() == 0 ? 0 : matrix.getColumnCount() - 1;
139 if (hasCustomRowGrouping) {
140 rowGroupIndices = std::move(matrix.rowGroupIndices);
141 if (!rowGroupIndices->empty()) {
142 rowGroupIndices.get().pop_back();
144 currentRowGroupCount = rowGroupIndices->empty() ? 0 : rowGroupIndices.get().size() - 1;
148 if (!rowIndications.empty()) {
149 rowIndications.pop_back();
153template<
typename ValueType>
156 STORM_LOG_THROW(row >= lastRow, storm::exceptions::InvalidArgumentException,
157 "Adding an element in row " << row <<
", but an element in row " << lastRow <<
" has already been added.");
158 STORM_LOG_ASSERT(columnsAndValues.size() == currentEntryCount,
"Unexpected size of columnsAndValues vector.");
161 if (pendingDiagonalEntry) {
162 index_type diagColumn = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
163 if (row > lastRow || column >= diagColumn) {
164 ValueType diagValue = std::move(pendingDiagonalEntry.get());
165 pendingDiagonalEntry = boost::none;
167 if (row == lastRow && column == diagColumn) {
181 bool fixCurrentRow = row == lastRow && column < lastColumn;
184 if (row == lastRow && column == lastColumn && rowIndications.back() < currentEntryCount) {
185 columnsAndValues.back().setValue(columnsAndValues.back().getValue() + value);
188 if (row != lastRow) {
190 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
191 rowIndications.resize(row + 1, currentEntryCount);
198 columnsAndValues.emplace_back(column, value);
199 highestColumn = std::max(highestColumn, column);
205 STORM_LOG_TRACE(
"Fix row " << row <<
" as column " << column <<
" is added out-of-order.");
207 std::sort(columnsAndValues.begin() + rowIndications.back(), columnsAndValues.end(),
209 return a.getColumn() < b.getColumn();
212 auto insertIt = columnsAndValues.begin() + rowIndications.back();
213 uint64_t elementsToRemove = 0;
214 for (
auto it = insertIt + 1; it != columnsAndValues.end(); ++it) {
216 if (it->getColumn() == insertIt->getColumn()) {
218 insertIt->setValue(insertIt->getValue() + it->getValue());
226 static_cast<void>(std::unique(columnsAndValues.begin() + rowIndications.back(), columnsAndValues.end(),
230 if (elementsToRemove > 0) {
231 STORM_LOG_WARN(
"Unordered insertion into matrix builder caused duplicate entries.");
232 currentEntryCount -= elementsToRemove;
233 columnsAndValues.resize(columnsAndValues.size() - elementsToRemove);
235 lastColumn = columnsAndValues.back().getColumn();
240 if (forceInitialDimensions) {
241 STORM_LOG_THROW(!initialRowCountSet || lastRow < initialRowCount, storm::exceptions::OutOfRangeException,
242 "Cannot insert value at illegal row " << lastRow <<
".");
243 STORM_LOG_THROW(!initialColumnCountSet || lastColumn < initialColumnCount, storm::exceptions::OutOfRangeException,
244 "Cannot insert value at illegal column " << lastColumn <<
".");
245 STORM_LOG_THROW(!initialEntryCountSet || currentEntryCount <= initialEntryCount, storm::exceptions::OutOfRangeException,
246 "Too many entries in matrix, expected only " << initialEntryCount <<
".");
250template<
typename ValueType>
252 STORM_LOG_THROW(hasCustomRowGrouping, storm::exceptions::InvalidStateException,
"Matrix was not created to have a custom row grouping.");
253 STORM_LOG_THROW(startingRow >= lastRow, storm::exceptions::InvalidStateException,
"Illegal row group with negative size.");
256 if (pendingDiagonalEntry) {
257 STORM_LOG_ASSERT(currentRowGroupCount > 0,
"Diagonal entry was set before opening the first row group.");
258 index_type diagColumn = currentRowGroupCount - 1;
259 ValueType diagValue = std::move(pendingDiagonalEntry.get());
260 pendingDiagonalEntry = boost::none;
264 rowGroupIndices.get().push_back(startingRow);
265 ++currentRowGroupCount;
268 if (lastRow + 1 < startingRow) {
270 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
271 rowIndications.resize(startingRow, currentEntryCount);
273 lastRow = startingRow - 1;
278template<
typename ValueType>
282 if (pendingDiagonalEntry) {
283 index_type diagColumn = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
284 ValueType diagValue = std::move(pendingDiagonalEntry.get());
285 pendingDiagonalEntry = boost::none;
289 bool hasEntries = currentEntryCount != 0;
291 uint_fast64_t rowCount = hasEntries ? lastRow + 1 : 0;
294 if (hasCustomRowGrouping) {
295 if (lastRow < rowGroupIndices->back()) {
300 if (initialRowCountSet && forceInitialDimensions) {
301 STORM_LOG_THROW(rowCount <= initialRowCount, storm::exceptions::InvalidStateException,
302 "Expected not more than " << initialRowCount <<
" rows, but got " << rowCount <<
".");
303 rowCount = std::max(rowCount, initialRowCount);
306 rowCount = std::max(rowCount, overriddenRowCount);
310 rowIndications.push_back(currentEntryCount);
317 rowIndications.push_back(currentEntryCount);
320 "Wrong sizes of row indications vector: (Rowcount) " << rowCount <<
" != " << (rowIndications.size() - 1) <<
" (Vector).");
321 uint_fast64_t columnCount = hasEntries ? highestColumn + 1 : 0;
322 if (initialColumnCountSet && forceInitialDimensions) {
323 STORM_LOG_THROW(columnCount <= initialColumnCount, storm::exceptions::InvalidStateException,
324 "Expected not more than " << initialColumnCount <<
" columns, but got " << columnCount <<
".");
325 columnCount = std::max(columnCount, initialColumnCount);
327 columnCount = std::max(columnCount, overriddenColumnCount);
329 uint_fast64_t entryCount = currentEntryCount;
330 if (initialEntryCountSet && forceInitialDimensions) {
331 STORM_LOG_THROW(entryCount == initialEntryCount, storm::exceptions::InvalidStateException,
332 "Expected " << initialEntryCount <<
" entries, but got " << entryCount <<
".");
336 if (hasCustomRowGrouping) {
337 uint_fast64_t rowGroupCount = currentRowGroupCount;
338 if (initialRowGroupCountSet && forceInitialDimensions) {
339 STORM_LOG_THROW(rowGroupCount <= initialRowGroupCount, storm::exceptions::InvalidStateException,
340 "Expected not more than " << initialRowGroupCount <<
" row groups, but got " << rowGroupCount <<
".");
341 rowGroupCount = std::max(rowGroupCount, initialRowGroupCount);
343 rowGroupCount = std::max(rowGroupCount, overriddenRowGroupCount);
345 for (
index_type i = currentRowGroupCount;
i <= rowGroupCount; ++
i) {
346 rowGroupIndices.get().push_back(rowCount);
350 return SparseMatrix<ValueType>(columnCount, std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices));
353template<
typename ValueType>
358template<
typename ValueType>
360 if (this->hasCustomRowGrouping) {
361 return currentRowGroupCount;
363 return getLastRow() + 1;
367template<
typename ValueType>
373template<
typename ValueType>
381 std::cout <<
"\t---- group " << group <<
"/" << (rowGroupIndices.size() - 1) <<
" ---- \n";
382 endGroups = group < rowGroupIndices.size() - 1 ? rowGroupIndices[group + 1] : rowIndications.size();
385 endRows =
i < rowIndications.size() - 1 ? rowIndications[
i + 1] : columnsAndValues.size();
387 std::cout <<
"Row " <<
i <<
" (" << rowIndications[
i] <<
" - " << endRows <<
")"
390 std::cout <<
"(" << columnsAndValues[pos].getColumn() <<
": " << columnsAndValues[pos].getValue() <<
") ";
397template<
typename ValueType>
401 for (
index_type row = 0; row < rowIndications.size(); ++row) {
402 bool changed =
false;
403 auto startRow = std::next(columnsAndValues.begin(), rowIndications[row]);
404 auto endRow = row < rowIndications.size() - 1 ? std::next(columnsAndValues.begin(), rowIndications[row + 1]) : columnsAndValues.
end();
405 for (
auto entry = startRow; entry != endRow; ++entry) {
406 if (entry->getColumn() >= offset) {
408 entry->setColumn(replacements[entry->getColumn() - offset]);
411 maxColumn = std::max(maxColumn, entry->getColumn());
415 std::sort(startRow, endRow,
422 "Columns not sorted.");
426 highestColumn = maxColumn;
427 lastColumn = columnsAndValues.empty() ? 0 : columnsAndValues.back().getColumn();
430template<
typename ValueType>
432 STORM_LOG_THROW(row >= lastRow, storm::exceptions::InvalidArgumentException,
433 "Adding a diagonal element in row " << row <<
", but an element in row " << lastRow <<
" has already been added.");
434 if (pendingDiagonalEntry) {
435 if (row == lastRow) {
437 pendingDiagonalEntry.get() += value;
441 index_type column = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
442 ValueType diagValue = std::move(pendingDiagonalEntry.get());
443 pendingDiagonalEntry = boost::none;
444 addNextValue(lastRow, column, diagValue);
447 pendingDiagonalEntry = value;
448 if (lastRow != row) {
449 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
450 rowIndications.resize(row + 1, currentEntryCount);
456template<
typename ValueType>
461template<
typename ValueType>
463 return beginIterator;
466template<
typename ValueType>
468 return beginIterator + entryCount;
471template<
typename ValueType>
473 return this->entryCount;
476template<
typename ValueType>
481template<
typename ValueType>
483 return beginIterator;
486template<
typename ValueType>
488 return beginIterator + entryCount;
491template<
typename ValueType>
493 return this->entryCount;
496template<
typename ValueType>
498 : rowCount(0), columnCount(0), entryCount(0), nonzeroEntryCount(0), columnsAndValues(), rowIndications(), rowGroupIndices() {
502template<
typename ValueType>
504 : rowCount(other.rowCount),
505 columnCount(other.columnCount),
506 entryCount(other.entryCount),
507 nonzeroEntryCount(other.nonzeroEntryCount),
508 columnsAndValues(other.columnsAndValues),
509 rowIndications(other.rowIndications),
510 trivialRowGrouping(other.trivialRowGrouping),
511 rowGroupIndices(other.rowGroupIndices) {
515template<
typename ValueType>
519 *
this = other.
getSubmatrix(
false, rowConstraint, columnConstraint, insertDiagonalElements);
522template<
typename ValueType>
524 : rowCount(other.rowCount),
525 columnCount(other.columnCount),
526 entryCount(other.entryCount),
527 nonzeroEntryCount(other.nonzeroEntryCount),
528 columnsAndValues(
std::move(other.columnsAndValues)),
529 rowIndications(
std::move(other.rowIndications)),
530 trivialRowGrouping(other.trivialRowGrouping),
531 rowGroupIndices(
std::move(other.rowGroupIndices)) {
534 other.columnCount = 0;
535 other.entryCount = 0;
538template<
typename ValueType>
541 boost::optional<std::vector<index_type>>
const& rowGroupIndices)
542 : rowCount(rowIndications.size() - 1),
543 columnCount(columnCount),
544 entryCount(columnsAndValues.size()),
545 nonzeroEntryCount(0),
546 columnsAndValues(columnsAndValues),
547 rowIndications(rowIndications),
548 trivialRowGrouping(!rowGroupIndices),
549 rowGroupIndices(rowGroupIndices) {
553template<
typename ValueType>
556 boost::optional<std::vector<index_type>>&& rowGroupIndices)
557 : columnCount(columnCount),
558 nonzeroEntryCount(0),
559 columnsAndValues(
std::move(columnsAndValues)),
560 rowIndications(
std::move(rowIndications)),
561 rowGroupIndices(
std::move(rowGroupIndices)) {
564 this->rowCount = this->rowIndications.size() - 1;
565 this->entryCount = this->columnsAndValues.size();
566 this->trivialRowGrouping = !this->rowGroupIndices;
570template<
typename ValueType>
573 if (
this != &other) {
574 rowCount = other.rowCount;
575 columnCount = other.columnCount;
576 entryCount = other.entryCount;
577 nonzeroEntryCount = other.nonzeroEntryCount;
579 columnsAndValues = other.columnsAndValues;
580 rowIndications = other.rowIndications;
581 rowGroupIndices = other.rowGroupIndices;
582 trivialRowGrouping = other.trivialRowGrouping;
587template<
typename ValueType>
590 if (
this != &other) {
591 rowCount = other.rowCount;
592 columnCount = other.columnCount;
593 entryCount = other.entryCount;
594 nonzeroEntryCount = other.nonzeroEntryCount;
596 columnsAndValues = std::move(other.columnsAndValues);
597 rowIndications = std::move(other.rowIndications);
598 rowGroupIndices = std::move(other.rowGroupIndices);
599 trivialRowGrouping = other.trivialRowGrouping;
604template<
typename ValueType>
606 if (
this == &other) {
610 bool equalityResult =
true;
612 equalityResult &= this->getRowCount() == other.
getRowCount();
613 if (!equalityResult) {
616 equalityResult &= this->getColumnCount() == other.
getColumnCount();
617 if (!equalityResult) {
625 if (!equalityResult) {
641 if ((it1 == ite1) || (it2 == ite2)) {
642 equalityResult = (it1 == ite1) ^ (it2 == ite2);
645 if (it1->getColumn() != it2->getColumn() || it1->getValue() != it2->getValue()) {
646 equalityResult =
false;
651 if (!equalityResult) {
656 return equalityResult;
659template<
typename ValueType>
664template<
typename ValueType>
669template<
typename ValueType>
674template<
typename ValueType>
687template<
typename ValueType>
689 return (this->rowIndications[row + 1] - this->rowIndications[row]);
692template<
typename ValueType>
694 return nonzeroEntryCount;
697template<
typename ValueType>
699 this->nonzeroEntryCount = 0;
700 for (
auto const& element : *
this) {
702 ++this->nonzeroEntryCount;
707template<
typename ValueType>
709 this->nonzeroEntryCount += difference;
712template<
typename ValueType>
714 this->nonzeroEntryCount = 0;
715 this->columnCount = 0;
716 for (
auto const& element : *
this) {
718 ++this->nonzeroEntryCount;
719 this->columnCount = std::max(element.getColumn() + 1, this->columnCount);
724template<
typename ValueType>
727 return rowGroupIndices.get().size() - 1;
733template<
typename ValueType>
738template<
typename ValueType>
745 for (
auto const&
i : rowGroupIndices.get()) {
746 res = std::max(res,
i - previousGroupStart);
747 previousGroupStart =
i;
752template<
typename ValueType>
770template<
typename ValueType>
773 if (!this->rowGroupIndices) {
774 STORM_LOG_ASSERT(trivialRowGrouping,
"Only trivial row-groupings can be constructed on-the-fly.");
777 return rowGroupIndices.get();
780template<
typename ValueType>
782 return rowIndications;
785template<
typename ValueType>
788 "Invalid row group index:" << group <<
". Only " << this->
getRowGroupCount() <<
" row groups available.");
789 if (this->rowGroupIndices) {
790 return boost::irange(rowGroupIndices.get()[group], rowGroupIndices.get()[group + 1]);
792 return boost::irange(group, group + 1);
796template<
typename ValueType>
798 std::vector<index_type> result;
799 if (this->rowGroupIndices) {
800 result = std::move(rowGroupIndices.get());
801 rowGroupIndices = std::move(newRowGrouping);
806template<
typename ValueType>
808 trivialRowGrouping =
false;
809 rowGroupIndices = newRowGroupIndices;
812template<
typename ValueType>
814 return trivialRowGrouping;
817template<
typename ValueType>
819 if (trivialRowGrouping) {
822 "Row grouping is supposed to be trivial but actually it is not.");
824 trivialRowGrouping =
true;
825 rowGroupIndices = boost::none;
829template<
typename ValueType>
832 for (uint64_t group : groupConstraint) {
838template<
typename ValueType>
842 for (uint64_t group : groupConstraint) {
844 bool choiceSatisfiesColumnConstraint =
true;
845 for (
auto const& entry : this->
getRow(row)) {
846 if (!columnConstraint.
get(entry.getColumn())) {
847 choiceSatisfiesColumnConstraint =
false;
851 if (choiceSatisfiesColumnConstraint) {
852 result.
set(row,
true);
859template<
typename ValueType>
864 if (setIfForAllRowsInGroup) {
868 result.
set(group,
true);
872 for (uint64_t group = 0; group < this->getRowGroupCount(); ++group) {
873 if (rowConstraint.
getNextSetIndex(groupIndices[group]) < groupIndices[group + 1]) {
875 result.
set(group,
true);
882template<
typename ValueType>
886 for (uint64_t row :
rows) {
890 this->dropZeroEntries();
894template<
typename ValueType>
899 for (uint64_t rowGroup : rowGroupConstraint) {
905 for (uint64_t rowGroup : rowGroupConstraint) {
906 makeRowDirac(rowGroup, rowGroup,
false);
909 if (dropZeroEntries) {
910 this->dropZeroEntries();
914template<
typename ValueType>
921 STORM_LOG_THROW(columnValuePtr < columnValuePtrEnd, storm::exceptions::InvalidStateException,
922 "Illegal call to SparseMatrix::makeRowDirac: cannot make row " << row <<
" absorbing, because there is no entry in this row.");
928 while (columnValuePtr->getColumn() < column && columnValuePtr != lastColumnValuePtr) {
930 --this->nonzeroEntryCount;
937 ++this->nonzeroEntryCount;
940 columnValuePtr->setColumn(column);
941 for (++columnValuePtr; columnValuePtr != columnValuePtrEnd; ++columnValuePtr) {
943 --this->nonzeroEntryCount;
947 if (dropZeroEntries) {
948 this->dropZeroEntries();
952template<
typename ValueType>
958 for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
963 if (it1 == end1 && it2 == end2) {
969template<
typename ValueType>
972 for (
size_t rowgroup = 0; rowgroup < this->
getRowGroupCount(); ++rowgroup) {
974 for (
size_t row2 = row1; row2 < this->
getRowGroupIndices().at(rowgroup + 1); ++row2) {
984template<
typename ValueType>
991 index_type largerRow =
getRow(row1).getNumberOfEntries() >
getRow(row2).getNumberOfEntries() ? row1 : row2;
992 index_type smallerRow = largerRow == row1 ? row2 : row1;
993 index_type rowSizeDifference =
getRow(largerRow).getNumberOfEntries() -
getRow(smallerRow).getNumberOfEntries();
996 auto copyRow =
getRow(largerRow);
997 std::vector<MatrixEntry<index_type, value_type>> largerRowContents(copyRow.begin(), copyRow.end());
999 if (largerRow < smallerRow) {
1000 auto writeIt =
getRows(largerRow, smallerRow + 1).begin();
1003 for (
auto& smallerRowEntry :
getRow(smallerRow)) {
1004 *writeIt = std::move(smallerRowEntry);
1010 for (
auto& intermediateRowEntry :
getRows(largerRow + 1, smallerRow)) {
1011 *writeIt = std::move(intermediateRowEntry);
1016 writeIt =
getRow(smallerRow).begin();
1020 for (
auto& largerRowEntry : largerRowContents) {
1021 *writeIt = std::move(largerRowEntry);
1030 rowIndications[row] -= rowSizeDifference;
1034 auto writeIt = getRows(smallerRow, largerRow + 1).end() - 1;
1037 auto copyRow = getRow(smallerRow);
1038 for (
auto smallerRowEntryIt = copyRow.end() - 1; smallerRowEntryIt != copyRow.begin() - 1; --smallerRowEntryIt) {
1039 *writeIt = std::move(*smallerRowEntryIt);
1045 for (
auto intermediateRowEntryIt =
getRows(smallerRow + 1, largerRow).
end() - 1;
1046 intermediateRowEntryIt !=
getRows(smallerRow + 1, largerRow).begin() - 1; --intermediateRowEntryIt) {
1047 *writeIt = std::move(*intermediateRowEntryIt);
1052 writeIt = getRow(smallerRow).end() - 1;
1056 for (
auto largerRowEntryIt = largerRowContents.rbegin(); largerRowEntryIt != largerRowContents.rend(); ++largerRowEntryIt) {
1057 *writeIt = std::move(*largerRowEntryIt);
1061 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).begin() - 1,
"Unexpected position of write iterator.");
1066 for (
index_type row = smallerRow + 1; row <= largerRow; ++row) {
1067 rowIndications[row] += rowSizeDifference;
1073template<
typename ValueType>
1075 std::vector<ValueType> result(this->
getRowCount());
1078 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++row) {
1085template<
typename ValueType>
1089 if (constraint.
get(it->getColumn())) {
1090 result += it->getValue();
1096template<
typename ValueType>
1101 for (uint64_t row : rowConstraint) {
1107template<
typename ValueType>
1110 std::vector<ValueType> result;
1113 for (uint64_t rowGroup : rowGroupConstraint) {
1119 for (uint64_t rowGroup : rowGroupConstraint) {
1126template<
typename ValueType>
1134 std::vector<index_type> fakeRowGroupIndices(rowCount + 1);
1136 for (std::vector<index_type>::iterator it = fakeRowGroupIndices.begin(); it != fakeRowGroupIndices.end(); ++it, ++
i) {
1139 auto res = getSubmatrix(rowConstraint, columnConstraint, fakeRowGroupIndices, insertDiagonalElements, makeZeroColumns);
1143 if (!this->hasTrivialRowGrouping()) {
1144 std::vector<index_type> newRowGroupIndices;
1145 newRowGroupIndices.push_back(0);
1146 auto selectedRowIt = rowConstraint.
begin();
1149 for (index_type group = 0; group < this->getRowGroupCount(); ++group) {
1150 index_type newRowCount = 0;
1151 while (*selectedRowIt < this->getRowGroupIndices()[group + 1]) {
1155 if (newRowCount > 0) {
1156 newRowGroupIndices.push_back(newRowGroupIndices.back() + newRowCount);
1160 res.trivialRowGrouping =
false;
1161 res.rowGroupIndices = newRowGroupIndices;
1168template<
typename ValueType>
1170 storm::storage::BitVector
const& columnConstraint, std::vector<index_type>
const& rowGroupIndices,
1171 bool insertDiagonalEntries, storm::storage::BitVector
const& makeZeroColumns)
const {
1172 STORM_LOG_THROW(!rowGroupConstraint.
empty() && !columnConstraint.
empty(), storm::exceptions::InvalidArgumentException,
"Cannot build empty submatrix.");
1178 std::unique_ptr<std::vector<index_type>> tmp;
1179 if (rowGroupConstraint != columnConstraint) {
1182 std::vector<index_type>
const& rowBitsSetBeforeIndex = tmp ? *tmp : columnBitsSetBeforeIndex;
1188 for (uint64_t index : rowGroupConstraint) {
1189 subRows += rowGroupIndices[index + 1] - rowGroupIndices[index];
1190 for (
index_type i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1191 bool foundDiagonalElement =
false;
1194 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1197 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1198 foundDiagonalElement =
true;
1204 if (insertDiagonalEntries && !foundDiagonalElement && rowGroupCount < submatrixColumnCount) {
1216 index_type rowCount = 0;
1218 for (uint64_t index : rowGroupConstraint) {
1219 if (!this->hasTrivialRowGrouping()) {
1220 matrixBuilder.newRowGroup(rowCount);
1222 for (index_type
i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1223 bool insertedDiagonalElement =
false;
1225 for (const_iterator it = this->begin(
i), ite = this->end(
i); it != ite; ++it) {
1226 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1227 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1228 insertedDiagonalElement =
true;
1229 }
else if (insertDiagonalEntries && !insertedDiagonalElement && columnBitsSetBeforeIndex[it->getColumn()] > rowBitsSetBeforeIndex[index]) {
1231 insertedDiagonalElement =
true;
1234 matrixBuilder.addNextValue(rowCount, columnBitsSetBeforeIndex[it->getColumn()], it->getValue());
1237 if (insertDiagonalEntries && !insertedDiagonalElement && rowGroupCount < submatrixColumnCount) {
1245 return matrixBuilder.build();
1248template<
typename ValueType>
1254 for (uint64_t row : rowsToKeep) {
1255 entryCount += this->
getRow(row).getNumberOfEntries();
1259 index_type firstTrailingEmptyRowGroup = this->getRowGroupCount();
1264 --firstTrailingEmptyRowGroup;
1266 STORM_LOG_THROW(allowEmptyRowGroups || firstTrailingEmptyRowGroup == this->getRowGroupCount(), storm::exceptions::InvalidArgumentException,
1267 "Empty rows are not allowed, but row group " << firstTrailingEmptyRowGroup <<
" is empty.");
1272 for (
index_type rowGroup = 0; rowGroup < firstTrailingEmptyRowGroup; ++rowGroup) {
1275 bool rowGroupEmpty =
true;
1278 rowGroupEmpty =
false;
1279 for (
auto const& entry : this->
getRow(row)) {
1280 builder.addNextValue(newRow, entry.getColumn(), entry.getValue());
1284 STORM_LOG_THROW(allowEmptyRowGroups || !rowGroupEmpty, storm::exceptions::InvalidArgumentException,
1285 "Empty rows are not allowed, but row group " << rowGroup <<
" is empty.");
1293template<
typename ValueType>
1297 for (uint64_t row : rowFilter) {
1298 entryCount +=
getRow(row).getNumberOfEntries();
1303 for (uint64_t row : rowFilter) {
1304 for (
auto const& entry :
getRow(row)) {
1305 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1317template<
typename ValueType>
1323 for (
auto const& entry :
getRow(row)) {
1325 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1334 *
this = std::move(result);
1338template<
typename ValueType>
1340 bool insertDiagonalEntries)
const {
1344 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1347 "Cannot point to row offset " << rowGroupToRowIndexMapping[rowGroupIndex] <<
" for rowGroup " << rowGroupIndex <<
" which starts at "
1353 bool foundDiagonalElement =
false;
1355 if (it->getColumn() == rowGroupIndex) {
1356 foundDiagonalElement =
true;
1360 if (insertDiagonalEntries && !foundDiagonalElement) {
1369 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1375 bool insertedDiagonalElement =
false;
1377 if (it->getColumn() == rowGroupIndex) {
1378 insertedDiagonalElement =
true;
1379 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > rowGroupIndex) {
1381 insertedDiagonalElement =
true;
1383 matrixBuilder.
addNextValue(rowGroupIndex, it->getColumn(), it->getValue());
1385 if (insertDiagonalEntries && !insertedDiagonalElement) {
1391 return matrixBuilder.
build();
1394template<
typename ValueType>
1396 bool insertDiagonalEntries)
const {
1400 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1401 bool foundDiagonalElement =
false;
1402 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1403 if (it->getColumn() == row) {
1404 foundDiagonalElement =
true;
1408 if (insertDiagonalEntries && !foundDiagonalElement) {
1417 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1418 bool insertedDiagonalElement =
false;
1419 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1420 if (it->getColumn() == row) {
1421 insertedDiagonalElement =
true;
1422 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > row) {
1424 insertedDiagonalElement =
true;
1426 matrixBuilder.
addNextValue(row, it->getColumn(), it->getValue());
1428 if (insertDiagonalEntries && !insertedDiagonalElement) {
1434 return matrixBuilder.
build();
1437template<
typename ValueType>
1445 for (
index_type writeTo = 0; writeTo < inversePermutation.size(); ++writeTo) {
1446 index_type const& readFrom = inversePermutation[writeTo];
1447 auto row = this->
getRow(readFrom);
1448 for (
auto const& entry : row) {
1449 matrixBuilder.
addNextValue(writeTo, entry.getColumn(), entry.getValue());
1453 auto result = matrixBuilder.
build();
1454 if (this->rowGroupIndices) {
1455 result.setRowGroupIndices(this->rowGroupIndices.get());
1460template<
typename ValueType>
1462 std::vector<index_type>
const& columnPermutation)
const {
1467 auto oldGroupIt = inverseRowGroupPermutation.cbegin();
1469 while (newRowIndex < rowCount) {
1474 for (
auto const& oldEntry :
getRow(oldRowIndex)) {
1475 matrixBuilder.
addNextValue(newRowIndex, columnPermutation[oldEntry.getColumn()], oldEntry.getValue());
1481 return matrixBuilder.
build();
1484template<
typename ValueType>
1496 std::vector<index_type> rowIndications(rowCount + 1);
1497 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1500 for (
index_type group = 0; group < columnCount; ++group) {
1501 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1503 ++rowIndications[transition.getColumn() + 1];
1510 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1516 std::vector<index_type> nextIndices = rowIndications;
1519 for (
index_type group = 0; group < columnCount; ++group) {
1520 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1522 columnsAndValues[nextIndices[transition.getColumn()]] = std::make_pair(group, transition.getValue());
1523 nextIndices[transition.getColumn()]++;
1530 return transposedMatrix;
1533template<
typename ValueType>
1536 index_type columnCount = this->getRowGroupCount();
1540 std::vector<index_type> rowIndications(columnCount + 1);
1541 auto rowGroupChoiceIt = rowGroupChoices.begin();
1542 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1543 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1546 ++rowIndications[entry.getColumn() + 1];
1553 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1556 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1561 std::vector<index_type> nextIndices = rowIndications;
1564 rowGroupChoiceIt = rowGroupChoices.begin();
1565 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1566 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1568 columnsAndValues[nextIndices[entry.getColumn()]] = std::make_pair(rowGroup, entry.getValue());
1569 ++nextIndices[entry.getColumn()];
1577template<
typename ValueType>
1583template<
typename ValueType>
1589 bool foundDiagonalElement =
false;
1590 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1592 if (entry.getColumn() == group) {
1593 if (entry.getValue() == one) {
1594 --this->nonzeroEntryCount;
1595 entry.setValue(zero);
1596 }
else if (entry.getValue() == zero) {
1597 ++this->nonzeroEntryCount;
1598 entry.setValue(one);
1600 entry.setValue(one - entry.getValue());
1602 foundDiagonalElement =
true;
1607 STORM_LOG_THROW(foundDiagonalElement, storm::exceptions::InvalidArgumentException,
1608 "Illegal call to SparseMatrix::invertDiagonal: matrix is missing diagonal entries.");
1612template<
typename ValueType>
1615 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1617 if (entry.getColumn() != group) {
1618 entry.setValue(-entry.getValue());
1624template<
typename ValueType>
1627 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1629 if (entry.getColumn() == group) {
1630 --this->nonzeroEntryCount;
1636 this->dropZeroEntries();
1640template<
typename ValueType>
1643 "Canno compute Jacobi decomposition of non-square matrix.");
1647 std::vector<ValueType> invertedDiagonal(rowCount);
1650 for (
index_type rowNumber = 0; rowNumber < rowCount; ++rowNumber) {
1652 if (it->getColumn() == rowNumber) {
1655 luBuilder.
addNextValue(rowNumber, it->getColumn(), it->getValue());
1660 return std::make_pair(luBuilder.
build(), std::move(invertedDiagonal));
1665 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1671 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1674template<
typename ValueType>
1675template<
typename OtherValueType,
typename ResultValueType>
1684 for (; it1 != ite1 && it2 != ite2; ++it1) {
1685 if (it1->getColumn() < it2->getColumn()) {
1691 STORM_LOG_ASSERT(it1->getColumn() == it2->getColumn(),
"The given matrix is not a submatrix of this one.");
1692 result += it2->getValue() * OtherValueType(it1->getValue());
1699template<
typename ValueType>
1700template<
typename OtherValueType,
typename ResultValueType>
1702 std::vector<ResultValueType> result;
1703 result.reserve(rowCount);
1710template<
typename ValueType>
1712 std::vector<value_type>
const* summand)
const {
1714 std::vector<ValueType>* target;
1715 std::vector<ValueType> temporary;
1716 if (&vector == &result) {
1717 STORM_LOG_WARN(
"Vectors are aliased. Using temporary, which is potentially slow.");
1718 temporary = std::vector<ValueType>(vector.size());
1719 target = &temporary;
1726 if (target == &temporary) {
1727 std::swap(result, *target);
1731template<
typename ValueType>
1733 std::vector<value_type>
const* summand)
const {
1736 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1737 typename std::vector<ValueType>::iterator resultIterator = result.begin();
1738 typename std::vector<ValueType>::iterator resultIteratorEnd = result.end();
1739 typename std::vector<ValueType>::const_iterator summandIterator;
1741 summandIterator = summand->begin();
1744 for (; resultIterator != resultIteratorEnd; ++rowIterator, ++resultIterator, ++summandIterator) {
1747 newValue = *summandIterator;
1752 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1753 newValue += it->getValue() * vector[it->getColumn()];
1756 *resultIterator = newValue;
1760template<
typename ValueType>
1762 std::vector<value_type>
const* summand)
const {
1765 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1766 typename std::vector<ValueType>::iterator resultIterator = result.end() - 1;
1767 typename std::vector<ValueType>::iterator resultIteratorEnd = result.begin() - 1;
1768 typename std::vector<ValueType>::const_iterator summandIterator;
1770 summandIterator = summand->end() - 1;
1773 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --summandIterator) {
1776 newValue = *summandIterator;
1781 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1782 newValue += (it->getValue() * vector[it->getColumn()]);
1785 *resultIterator = newValue;
1789template<
typename ValueType>
1793 for (
auto const& entry : this->
getRow(row)) {
1794 result += entry.getValue() * vector[entry.getColumn()];
1799template<
typename ValueType>
1803 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1804 typename std::vector<ValueType>::const_iterator bIt = b.end() - 1;
1805 typename std::vector<ValueType>::iterator resultIterator = x.end() - 1;
1806 typename std::vector<ValueType>::iterator resultIteratorEnd = x.begin() - 1;
1809 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --bIt) {
1814 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1815 if (it->getColumn() != currentRow) {
1816 tmpValue += it->getValue() * x[it->getColumn()];
1818 diagonalElement += it->getValue();
1828 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1831template<
typename ValueType>
1833 std::vector<ValueType>
const& ax, std::vector<ValueType>& result)
const {
1836 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1840 for (
auto& entry : result) {
1844 for (
index_type row = 0; row < rowCount; ++row, ++rowIterator) {
1845 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1846 result[it->getColumn()] += it->getValue() * (b[row] / ax[row]);
1850 auto xIterator = x.begin();
1851 auto sumsIterator = columnSums.begin();
1852 for (
auto& entry : result) {
1853 entry *= *xIterator / *sumsIterator;
1861 std::vector<Interval>
const& ax, std::vector<Interval>& result)
const {
1862 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1865template<
typename ValueType>
1867 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1868 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1869 if (dir == OptimizationDirection::Minimize) {
1876template<
typename ValueType>
1877template<
typename Compare>
1879 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1880 std::vector<uint64_t>* choices)
const {
1882 auto elementIt = this->
begin();
1883 auto rowGroupIt = rowGroupIndices.begin();
1884 auto rowIt = rowIndications.begin();
1885 typename std::vector<ValueType>::const_iterator summandIt;
1887 summandIt = summand->begin();
1889 typename std::vector<uint64_t>::iterator choiceIt;
1891 choiceIt = choices->begin();
1895 ValueType oldSelectedChoiceValue;
1896 uint64_t selectedChoice;
1898 uint64_t currentRow = 0;
1899 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt) {
1903 if (*rowGroupIt < *(rowGroupIt + 1)) {
1905 currentValue = *summandIt;
1909 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1910 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
1915 if (*choiceIt == 0) {
1916 oldSelectedChoiceValue = currentValue;
1923 for (; currentRow < *(rowGroupIt + 1); ++rowIt, ++currentRow) {
1925 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1926 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
1929 if (choices && currentRow == *choiceIt + *rowGroupIt) {
1930 oldSelectedChoiceValue = newValue;
1933 if (compare(newValue, currentValue)) {
1934 currentValue = newValue;
1936 selectedChoice = currentRow - *rowGroupIt;
1945 *resultIt = currentValue;
1946 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
1947 *choiceIt = selectedChoice;
1955 std::vector<storm::RationalFunction>
const& vector,
1956 std::vector<storm::RationalFunction>
const* b,
1957 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
1958 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1961template<
typename ValueType>
1963 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1964 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1965 if (dir == storm::OptimizationDirection::Minimize) {
1972template<
typename ValueType>
1973template<
typename Compare>
1975 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1976 std::vector<uint64_t>* choices)
const {
1978 auto elementIt = this->
end() - 1;
1979 auto rowGroupIt = rowGroupIndices.end() - 2;
1980 auto rowIt = rowIndications.end() - 2;
1981 typename std::vector<ValueType>::const_iterator summandIt;
1983 summandIt = summand->end() - 1;
1985 typename std::vector<uint64_t>::iterator choiceIt;
1987 choiceIt = choices->end() - 1;
1991 ValueType oldSelectedChoiceValue;
1992 uint64_t selectedChoice;
1995 for (
auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt) {
1999 if (*rowGroupIt < *(rowGroupIt + 1)) {
2001 currentValue = *summandIt;
2005 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
2006 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
2009 selectedChoice = currentRow - *rowGroupIt;
2010 if (*choiceIt == selectedChoice) {
2011 oldSelectedChoiceValue = currentValue;
2017 for (uint64_t
i = *rowGroupIt + 1,
end = *(rowGroupIt + 1);
i <
end; --rowIt, --currentRow, ++
i, --summandIt) {
2019 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
2020 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
2023 if (choices && currentRow == *choiceIt + *rowGroupIt) {
2024 oldSelectedChoiceValue = newValue;
2027 if (compare(newValue, currentValue)) {
2028 currentValue = newValue;
2030 selectedChoice = currentRow - *rowGroupIt;
2036 *resultIt = currentValue;
2037 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
2038 *choiceIt = selectedChoice;
2046 std::vector<storm::RationalFunction>
const& vector,
2047 std::vector<storm::RationalFunction>
const* b,
2048 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
2049 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
2052template<
typename ValueType>
2054 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
2055 std::vector<uint64_t>* choices)
const {
2057 std::vector<ValueType>* target;
2058 std::vector<ValueType> temporary;
2059 if (&vector == &result) {
2060 STORM_LOG_WARN(
"Vectors are aliased but are not allowed to be. Using temporary, which is potentially slow.");
2061 temporary = std::vector<ValueType>(vector.size());
2062 target = &temporary;
2069 if (target == &temporary) {
2070 std::swap(temporary, result);
2074template<
typename ValueType>
2078 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
2079 std::vector<index_type>::const_iterator rowIteratorEnd = rowIndications.end();
2082 for (; rowIterator != rowIteratorEnd - 1; ++rowIterator) {
2083 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
2084 result[it->getColumn()] += it->getValue() * vector[currentRow];
2090template<
typename ValueType>
2092 STORM_LOG_ASSERT(factors.size() == this->getRowCount(),
"Can not scale rows: Number of rows and number of scaling factors do not match.");
2094 for (
auto const& factor : factors) {
2095 for (
auto& entry :
getRow(row)) {
2096 entry.setValue(entry.getValue() * factor);
2102template<
typename ValueType>
2104 STORM_LOG_ASSERT(divisors.size() == this->getRowCount(),
"Can not divide rows: Number of rows and number of divisors do not match.");
2106 for (
auto const& divisor : divisors) {
2108 for (
auto& entry :
getRow(row)) {
2109 entry.setValue(entry.getValue() / divisor);
2117 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
2120template<
typename ValueType>
2122 return const_rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2125template<
typename ValueType>
2127 return rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2130template<
typename ValueType>
2135template<
typename ValueType>
2140template<
typename ValueType>
2148 return getRow(rowGroup + offset);
2152template<
typename ValueType>
2160 return getRow(rowGroup + offset);
2164template<
typename ValueType>
2170 return getRows(rowGroup, rowGroup + 1);
2174template<
typename ValueType>
2180 return getRows(rowGroup, rowGroup + 1);
2184template<
typename ValueType>
2187 return this->columnsAndValues.begin() + this->rowIndications[row];
2190template<
typename ValueType>
2193 return this->columnsAndValues.begin() + this->rowIndications[row];
2196template<
typename ValueType>
2198 return this->columnsAndValues.begin();
2201template<
typename ValueType>
2203 return this->columnsAndValues.begin();
2206template<
typename ValueType>
2209 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2212template<
typename ValueType>
2215 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2218template<
typename ValueType>
2220 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2223template<
typename ValueType>
2225 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2228template<
typename ValueType>
2232 sum += it->getValue();
2237template<
typename ValueType>
2240 for (
auto const& entry : *
this) {
2245 return nonConstEntries;
2248template<
typename ValueType>
2251 for (
index_type rowGroup = 0; rowGroup < this->getRowGroupCount(); ++rowGroup) {
2252 for (
auto const& entry : this->
getRowGroup(rowGroup)) {
2254 ++nonConstRowGroups;
2259 return nonConstRowGroups;
2262template<
typename ValueType>
2266 auto toBaseType = [](ValueType
const& value) {
2267 if constexpr (std::is_same_v<ValueType, BaseType>) {
2278 auto isContained = [&toBaseType](ValueType
const& value, BaseType
const& lower, BaseType
const& upper) {
2283 return value.lower() <= upper && value.upper() >= lower;
2284 }
else if constexpr (std::is_same_v<ValueType, storm::RationalFunction>) {
2287 auto const constValue = toBaseType(value);
2288 return constValue <= upper && constValue >= lower;
2294 return value <= upper && value >= lower;
2298 auto toString = [](ValueType
const& value) {
2299 std::stringstream s;
2304 for (
index_type row = 0; row < this->rowCount; ++row) {
2306 for (
auto const& entry :
getRow(row)) {
2307 if (!isContained(entry.getValue(), zeroMinusTolerance, onePlusTolerance)) {
2309 *reason =
"Entry in row " + std::to_string(row) +
" is not a probability: " +
toString(entry.getValue());
2313 rowSum += entry.getValue();
2315 if (!isContained(rowSum, oneMinusTolerance, onePlusTolerance)) {
2326template<
typename ValueType>
2328 for (
auto const& entry : *
this) {
2336template<
typename ValueType>
2337template<
typename OtherValueType>
2342 (!this->hasTrivialRowGrouping() && this->getRowGroupIndices() != matrix.
getRowGroupIndices())) {
2348 auto it2 = matrix.
begin(row);
2349 auto ite2 = matrix.
end(row);
2352 while (it2 != ite2 && it2->getColumn() < it1->getColumn()) {
2355 if (it2 == ite2 || it1->getColumn() != it2->getColumn()) {
2363template<
typename ValueType>
2371 for (uint64_t row = 0; row < this->
getRowCount(); ++row) {
2372 bool rowHasEntry =
false;
2373 for (
auto const& entry : this->
getRow(row)) {
2374 if (entry.getColumn() == row) {
2392template<
typename ValueType>
2394 std::string result =
2403template<
typename ValueType>
2414 out <<
"\t---- group " << group <<
"/" << (matrix.
getRowGroupCount() - 1) <<
" ---- \n";
2422 out <<
i <<
"\t(\t";
2424 while (currentRealIndex < matrix.columnCount) {
2425 if (nextIndex < matrix.rowIndications[
i + 1] && currentRealIndex == matrix.columnsAndValues[nextIndex].getColumn()) {
2426 out << matrix.columnsAndValues[nextIndex].getValue() <<
"\t";
2433 out <<
"\t)\t" <<
i <<
'\n';
2447template<
typename ValueType>
2458 while (currentRealIndex < this->columnCount) {
2459 if (nextIndex < this->rowIndications[
i + 1] && currentRealIndex == this->columnsAndValues[nextIndex].getColumn()) {
2460 out << this->columnsAndValues[nextIndex].getValue() <<
" ";
2472template<
typename ValueType>
2474 std::size_t result = 0;
2479 boost::hash_combine(result, boost::hash_range(columnsAndValues.begin(), columnsAndValues.end()));
2480 boost::hash_combine(result, boost::hash_range(rowIndications.begin(), rowIndications.end()));
2482 boost::hash_combine(result, boost::hash_range(rowGroupIndices.get().begin(), rowGroupIndices.get().end()));
2522#if defined(STORM_HAVE_CLN)
2535#if defined(STORM_HAVE_GMP)
Helper class that optionally holds a reference to an object of type T.
A bit vector that is internally represented as a vector of 64-bit values.
void setMultiple(uint64_t bitIndex, uint64_t nrOfBits, bool newValue=true)
Sets multiple bits to the given value.
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.
std::vector< uint64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
uint64_t getNextUnsetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to false in the bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
MatrixEntry(index_type column, value_type value)
Constructs a matrix entry with the given column and value.
MatrixEntry operator*(value_type factor) const
Multiplies the entry with the given factor and returns the result.
value_type const & getValue() const
Retrieves the value of the matrix entry.
std::pair< index_type, value_type > const & getColumnValuePair() const
Retrieves a pair of column and value that characterizes this entry.
void setColumn(index_type const &column)
Sets the column of the current entry.
index_type const & getColumn() const
Retrieves the column of the matrix entry.
bool operator!=(MatrixEntry const &other) const
void setValue(value_type const &value)
Sets the value of the entry in the matrix.
bool operator==(MatrixEntry const &other) const
This class represents a number of consecutive rows of the matrix.
const_rows(const_iterator begin, index_type entryCount)
Constructs an object that represents the rows defined by the value of the first entry,...
const_iterator end() const
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the rows.
This class represents a number of consecutive rows of the matrix.
iterator end()
Retrieves an iterator that points past the last entry of the rows.
iterator begin()
Retrieves an iterator that points to the beginning of the rows.
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
rows(iterator begin, index_type entryCount)
Constructs an object that represents the rows defined by the value of the first entry,...
A class that can be used to build a sparse matrix by adding value by value.
index_type getCurrentRowGroupCount() const
Retrieves the current row group count.
index_type getLastRow() const
Retrieves the most recently used row.
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 replaceColumns(std::vector< index_type > const &replacements, index_type offset)
Replaces all columns with id > offset according to replacements.
SparseMatrixIndexType index_type
SparseMatrixBuilder(index_type rows=0, index_type columns=0, index_type entries=0, bool forceDimensions=true, bool hasCustomRowGrouping=false, index_type rowGroups=0)
Constructs a sparse matrix builder producing a matrix with the given number of rows,...
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
index_type getLastColumn() const
Retrieves the most recently used row.
void addDiagonalEntry(index_type row, ValueType const &value)
Makes sure that a diagonal entry will be inserted at the given row.
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.
void divideRowsInPlace(std::vector< value_type > const &divisors)
Divides each row of the matrix, i.e., divides each element in row i with divisors[i].
ResultValueType getPointwiseProductRowSum(storm::storage::SparseMatrix< OtherValueType > const &otherMatrix, index_type const &row) const
Performs a pointwise multiplication of the entries in the given row of this matrix and the entries of...
void convertToEquationSystem()
Transforms the matrix into an equation system.
SparseMatrix()
Constructs an empty sparse matrix.
void swapRows(index_type const &row1, index_type const &row2)
Swaps the two rows.
bool operator==(SparseMatrix< value_type > const &other) const
Determines whether the current and the given matrix are semantically equal.
const_rows getRow(index_type row) const
index_type getSizeOfLargestRowGroup() const
Returns the size of the largest row group of the matrix.
SparseMatrix selectRowsFromRowGroups(std::vector< index_type > const &rowGroupToRowIndexMapping, bool insertDiagonalEntries=true) const
Selects exactly one row from each row group of this matrix and returns the resulting matrix.
void multiplyWithVectorForward(std::vector< value_type > const &vector, std::vector< value_type > &result, std::vector< value_type > const *summand=nullptr) const
index_type getEntryCount() const
Returns the number of entries in the matrix.
bool isProbabilistic(ValueType const &tolerance, storm::OptionalRef< std::string > reason={}) const
Checks for each row whether (i) each entry is between zero and one and (ii) all entries sum to one.
const_rows getRows(index_type startRow, index_type endRow) const
Returns an object representing the consecutive rows given by the parameters.
index_type getNonconstantEntryCount() const
Returns the number of non-constant entries.
void multiplyVectorWithMatrix(std::vector< value_type > const &vector, std::vector< value_type > &result) const
Multiplies the vector to the matrix from the left and writes the result to the given result vector.
void multiplyAndReduceBackward(storm::solver::OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< ValueType > const &vector, std::vector< ValueType > const *b, std::vector< ValueType > &result, std::vector< uint64_t > *choices) const
index_type getNumRowsInRowGroups(storm::storage::BitVector const &groupConstraint) const
Returns the total number of rows that are in one of the specified row groups.
void makeRowsAbsorbing(storm::storage::BitVector const &rows, bool dropZeroEntries=false)
This function makes the given rows absorbing.
void multiplyWithVector(std::vector< value_type > const &vector, std::vector< value_type > &result, std::vector< value_type > const *summand=nullptr) const
Multiplies the matrix with the given vector and writes the result to the given result vector.
void updateNonzeroEntryCount() const
void multiplyWithVectorBackward(std::vector< value_type > const &vector, std::vector< value_type > &result, std::vector< value_type > const *summand=nullptr) const
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
void performWalkerChaeStep(std::vector< ValueType > const &x, std::vector< ValueType > const &columnSums, std::vector< ValueType > const &b, std::vector< ValueType > const &ax, std::vector< ValueType > &result) const
Performs one step of the Walker-Chae technique.
void updateDimensions() const
Recomputes the number of columns and the number of non-zero entries.
const_iterator begin(index_type row) const
void printAsMatlabMatrix(std::ostream &out) const
Prints the matrix in a dense format, as also used by e.g.
void performSuccessiveOverRelaxationStep(ValueType omega, std::vector< ValueType > &x, std::vector< ValueType > const &b) const
Performs one step of the successive over-relaxation technique.
std::vector< value_type > getConstrainedRowSumVector(storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose i-th entry is the sum of the entries in the i-th selected row where only thos...
BitVector duplicateRowsInRowgroups() const
Finds duplicate rows in a rowgroup.
bool compareRows(index_type i1, index_type i2) const
Compares two rows.
const_rows getRowGroup(index_type rowGroup) const
Returns an object representing the given row group.
SparseMatrix permuteRows(std::vector< index_type > const &inversePermutation) const
Permute rows of the matrix according to the vector.
void setRowGroupIndices(std::vector< index_type > const &newRowGroupIndices)
Sets the row grouping to the given one.
void negateAllNonDiagonalEntries()
Negates (w.r.t.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the first row of the matrix.
std::vector< index_type > swapRowGroupIndices(std::vector< index_type > &&newRowGrouping)
Swaps the grouping of rows of this matrix.
SparseMatrix restrictRows(storm::storage::BitVector const &rowsToKeep, bool allowEmptyRowGroups=false) const
Restrict rows in grouped rows matrix.
std::vector< ValueType > getRowSumVector() const
Sums the entries in all rows.
value_type multiplyRowWithVector(index_type row, std::vector< value_type > const &vector) const
Multiplies a single row of the matrix with the given vector and returns the result.
SparseMatrix< ValueType > transposeSelectedRowsFromRowGroups(std::vector< uint64_t > const &rowGroupChoices, bool keepZeros=false) const
Transposes the matrix w.r.t.
std::vector< index_type > const & getRowIndices() const
Returns the entry indices within the given row.
index_type getRowEntryCount(index_type const row) const
Returns the number of entries in the given row of the matrix.
void multiplyAndReduceForward(storm::solver::OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< ValueType > const &vector, std::vector< ValueType > const *b, std::vector< ValueType > &result, std::vector< uint64_t > *choices) const
value_type getRowSum(index_type row) const
const_iterator end(index_type row) const
SparseMatrix permuteRowGroupsAndColumns(std::vector< index_type > const &inverseRowGroupPermutation, std::vector< index_type > const &columnPermutation) const
Permutes row groups and columns of the matrix according to the given permutations.
void multiplyAndReduce(storm::solver::OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< ValueType > const &vector, std::vector< ValueType > const *summand, std::vector< ValueType > &result, std::vector< uint64_t > *choices) const
Multiplies the matrix with the given vector, reduces it according to the given direction and and writ...
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
void dropZeroEntries()
Removes all zero entries from this.
bool isSubmatrixOf(SparseMatrix< OtherValueType > const &matrix) const
Checks if the current matrix is a submatrix of the given matrix, where a matrix A is called a submatr...
SparseMatrix< value_type > & operator=(SparseMatrix< value_type > const &other)
Assigns the contents of the given matrix to the current one by deep-copying its contents.
void makeRowGroupsAbsorbing(storm::storage::BitVector const &rowGroupConstraint, bool dropZeroEntries=false)
This function makes the groups of rows given by the bit vector absorbing.
std::string getDimensionsAsString() const
Returns a string describing the dimensions of the matrix.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::pair< storm::storage::SparseMatrix< value_type >, std::vector< value_type > > getJacobiDecomposition() const
Calculates the Jacobi decomposition of this sparse matrix.
void makeRowDirac(index_type row, index_type column, bool dropZeroEntries=false)
This function makes the given row Dirac.
std::vector< MatrixEntry< index_type, value_type > >::const_iterator const_iterator
value_type getConstrainedRowSum(index_type row, storm::storage::BitVector const &columns) const
Sums the entries in the given row and columns.
std::vector< ResultValueType > getPointwiseProductRowSumVector(storm::storage::SparseMatrix< OtherValueType > const &otherMatrix) const
Performs a pointwise matrix multiplication of the matrix with the given matrix and returns a vector c...
void deleteDiagonalEntries(bool dropZeroEntries=false)
Sets all diagonal elements to zero.
bool hasTrivialRowGrouping() const
Retrieves whether the matrix has a trivial row grouping.
void invertDiagonal()
Inverts all entries on the diagonal, i.e.
storm::storage::BitVector getRowGroupFilter(storm::storage::BitVector const &rowConstraint, bool setIfForAllRowsInGroup) const
Returns the indices of all row groups selected by the row constraints.
void makeRowGroupingTrivial()
Makes the row grouping of this matrix trivial.
SparseMatrix selectRowsFromRowIndexSequence(std::vector< index_type > const &rowIndexSequence, bool insertDiagonalEntries=true) const
Selects the rows that are given by the sequence of row indices, allowing to select rows arbitrarily o...
std::size_t hash() const
Calculates a hash value over all values contained in the matrix.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
std::vector< MatrixEntry< index_type, value_type > >::iterator iterator
bool isIdentityMatrix() const
index_type getRowGroupSize(index_type group) const
Returns the size of the given row group.
std::vector< value_type > getConstrainedRowGroupSumVector(storm::storage::BitVector const &rowGroupConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose entries represent the sums of selected columns for all rows in selected row g...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
bool hasOnlyPositiveEntries() const
Checks whether each present entry is strictly positive (omitted entries are not considered).
index_type getRowCount() const
Returns the number of rows of the matrix.
SparseMatrixIndexType index_type
index_type getNonzeroEntryCount() const
Returns the cached number of nonzero entries in the matrix.
const_iterator end() const
Retrieves an iterator that points past the end of the last row of the matrix.
index_type getNonconstantRowGroupCount() const
Returns the number of rowGroups that contain a non-constant value.
void scaleRowsInPlace(std::vector< value_type > const &factors)
Scales each row of the matrix, i.e., multiplies each element in row i with factors[i].
index_type getRowGroupEntryCount(index_type const group) const
Returns the number of entries in the given row group of the matrix.
storm::storage::BitVector getRowFilter(storm::storage::BitVector const &groupConstraint) const
Returns a bitvector representing the set of rows, with all indices set that correspond to one of the ...
SparseMatrix filterEntries(storm::storage::BitVector const &rowFilter) const
Returns a copy of this matrix that only considers entries in the selected rows.
#define STORM_LOG_WARN(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
std::string toString(PomdpMemoryPattern const &pattern)
void print(std::vector< typename SparseMatrix< ValueType >::index_type > const &rowGroupIndices, std::vector< MatrixEntry< typename SparseMatrix< ValueType >::index_type, typename SparseMatrix< ValueType >::value_type > > const &columnsAndValues, std::vector< typename SparseMatrix< ValueType >::index_type > const &rowIndications)
std::ostream & operator<<(std::ostream &out, ParameterRegion< ParametricType > const ®ion)
bool isValidPermutation(std::vector< index_type > const &permutation)
Returns true if the given vector is a permutation of the numbers 0, 1, ..., n-1 for n = permutation....
std::vector< T > buildVectorForRange(T min, T max)
Constructs a vector [min, min+1, ...., max-1].
bool isPositive(ValueType const &a)
bool isOne(ValueType const &a)
bool isConstant(ValueType const &)
bool isZero(ValueType const &a)
TargetType convertNumber(SourceType const &number)
carl::Interval< storm::RationalNumber > RationalInterval
carl::Interval< double > Interval
Interval type.
solver::OptimizationDirection OptimizationDirection
constexpr bool IsIntervalType
Helper to check if a type is an interval.
carl::RationalFunction< Polynomial, true > RationalFunction
typename detail::IntervalMetaProgrammingHelper< ValueType >::BaseType IntervalBaseType
Helper to access the type in which interval boundaries are stored.