27template<
typename IndexType,
typename ValueType>
32template<
typename IndexType,
typename ValueType>
37template<
typename IndexType,
typename ValueType>
39 return this->entry.first;
42template<
typename IndexType,
typename ValueType>
44 this->entry.first = column;
47template<
typename IndexType,
typename ValueType>
49 return this->entry.second;
52template<
typename IndexType,
typename ValueType>
54 this->entry.second = value;
57template<
typename IndexType,
typename ValueType>
62template<
typename IndexType,
typename ValueType>
67template<
typename IndexType,
typename ValueType>
69 return this->entry.first == other.entry.first && this->entry.second == other.entry.second;
72template<
typename IndexType,
typename ValueType>
74 return !(*
this == other);
77template<
typename IndexTypePrime,
typename ValueTypePrime>
79 out <<
"(" << entry.getColumn() <<
", " << entry.getValue() <<
")";
83template<
typename ValueType>
86 : initialRowCountSet(rows != 0),
87 initialRowCount(rows),
88 initialColumnCountSet(columns != 0),
89 initialColumnCount(columns),
90 initialEntryCountSet(entries != 0),
91 initialEntryCount(entries),
92 forceInitialDimensions(forceDimensions),
93 hasCustomRowGrouping(hasCustomRowGrouping),
94 initialRowGroupCountSet(rowGroups != 0),
95 initialRowGroupCount(rowGroups),
103 currentRowGroupCount(0) {
105 if (initialRowCountSet) {
106 rowIndications.reserve(initialRowCount + 1);
108 if (initialEntryCountSet) {
109 columnsAndValues.reserve(initialEntryCount);
111 if (hasCustomRowGrouping) {
112 rowGroupIndices = std::vector<index_type>();
114 if (initialRowGroupCountSet && hasCustomRowGrouping) {
115 rowGroupIndices.get().reserve(initialRowGroupCount + 1);
117 rowIndications.push_back(0);
120template<
typename ValueType>
122 : initialRowCountSet(false),
124 initialColumnCountSet(false),
125 initialColumnCount(0),
126 initialEntryCountSet(false),
127 initialEntryCount(0),
128 forceInitialDimensions(false),
129 hasCustomRowGrouping(!matrix.trivialRowGrouping),
130 initialRowGroupCountSet(false),
131 initialRowGroupCount(0),
133 columnsAndValues(
std::move(matrix.columnsAndValues)),
134 rowIndications(
std::move(matrix.rowIndications)),
135 currentEntryCount(matrix.entryCount),
136 currentRowGroupCount() {
137 lastRow = matrix.rowCount == 0 ? 0 : matrix.rowCount - 1;
138 lastColumn = columnsAndValues.empty() ? 0 : columnsAndValues.back().getColumn();
139 highestColumn = matrix.getColumnCount() == 0 ? 0 : matrix.getColumnCount() - 1;
142 if (hasCustomRowGrouping) {
143 rowGroupIndices = std::move(matrix.rowGroupIndices);
144 if (!rowGroupIndices->empty()) {
145 rowGroupIndices.get().pop_back();
147 currentRowGroupCount = rowGroupIndices->empty() ? 0 : rowGroupIndices.get().size() - 1;
151 if (!rowIndications.empty()) {
152 rowIndications.pop_back();
155 if (rowIndications.empty()) {
156 rowIndications.push_back(0);
166template<
typename ValueType>
171 case AccumulationMode::Sum:
172 return existingValue + newValue;
173 case AccumulationMode::ExpectSame:
174 STORM_LOG_THROW(existingValue == newValue, storm::exceptions::InvalidArgumentException,
175 "Multiple different values (" << existingValue <<
" and " << newValue <<
") added to matrix entry in row " << row <<
" and column "
176 << column <<
", but all values for the same entry are expected to be equal.");
177 return existingValue;
178 case AccumulationMode::ExpectNone:
180 "Multiple values added to matrix entry in row " << row <<
" and column " << column <<
", but no duplicate entries are expected.");
183 return existingValue;
187template<
typename ValueType>
189 accumulationMode = mode;
192template<
typename ValueType>
194 return accumulationMode;
197template<
typename ValueType>
200 STORM_LOG_THROW(row >= lastRow, storm::exceptions::InvalidArgumentException,
201 "Adding an element in row " << row <<
", but an element in row " << lastRow <<
" has already been added.");
202 STORM_LOG_ASSERT(columnsAndValues.size() == currentEntryCount,
"Unexpected size of columnsAndValues vector.");
205 if (pendingDiagonalEntry) {
206 index_type diagColumn = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
207 if (row > lastRow || column >= diagColumn) {
208 ValueType diagValue = std::move(pendingDiagonalEntry.get());
209 pendingDiagonalEntry = boost::none;
217 if (forceInitialDimensions) {
218 STORM_LOG_THROW(!initialRowCountSet || row < initialRowCount, storm::exceptions::OutOfRangeException,
219 "Cannot insert value at illegal row " << row <<
".");
220 STORM_LOG_THROW(!initialColumnCountSet || column < initialColumnCount, storm::exceptions::OutOfRangeException,
221 "Cannot insert value at illegal column " << column <<
".");
225 if (row != lastRow) {
226 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
227 rowIndications.resize(row + 1, currentEntryCount);
232 bool const rowHasEntries = rowIndications.back() < currentEntryCount;
233 if (!rowHasEntries || columnsAndValues.back().getColumn() < column) {
235 columnsAndValues.emplace_back(column, value);
237 }
else if (columnsAndValues.back().getColumn() == column) {
239 columnsAndValues.back().setValue(accumulate(accumulationMode, row, column, columnsAndValues.back().getValue(), value));
242 auto const rowBegin = columnsAndValues.begin() + rowIndications.back();
244 std::lower_bound(rowBegin, columnsAndValues.end(), column,
246 if (position != columnsAndValues.end() && position->getColumn() == column) {
247 position->setValue(accumulate(accumulationMode, row, column, position->getValue(), value));
249 STORM_LOG_TRACE(
"Column " << column <<
" is added out-of-order to row " << row <<
".");
250 columnsAndValues.emplace(position, column, value);
255 lastColumn = columnsAndValues.back().getColumn();
256 highestColumn = std::max(highestColumn, column);
258 if (forceInitialDimensions) {
259 STORM_LOG_THROW(!initialEntryCountSet || currentEntryCount <= initialEntryCount, storm::exceptions::OutOfRangeException,
260 "Too many entries in matrix, expected only " << initialEntryCount <<
".");
264template<
typename ValueType>
266 STORM_LOG_THROW(hasCustomRowGrouping, storm::exceptions::InvalidStateException,
"Matrix was not created to have a custom row grouping.");
267 STORM_LOG_THROW(startingRow >= lastRow, storm::exceptions::InvalidStateException,
"Illegal row group with negative size.");
270 if (pendingDiagonalEntry) {
271 STORM_LOG_ASSERT(currentRowGroupCount > 0,
"Diagonal entry was set before opening the first row group.");
272 index_type diagColumn = currentRowGroupCount - 1;
273 ValueType diagValue = std::move(pendingDiagonalEntry.get());
274 pendingDiagonalEntry = boost::none;
278 rowGroupIndices.get().push_back(startingRow);
279 ++currentRowGroupCount;
282 if (lastRow + 1 < startingRow) {
284 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
285 rowIndications.resize(startingRow, currentEntryCount);
287 lastRow = startingRow - 1;
292template<
typename ValueType>
296 if (pendingDiagonalEntry) {
297 index_type diagColumn = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
298 ValueType diagValue = std::move(pendingDiagonalEntry.get());
299 pendingDiagonalEntry = boost::none;
303 bool hasEntries = currentEntryCount != 0;
305 uint_fast64_t rowCount = hasEntries ? lastRow + 1 : 0;
308 if (hasCustomRowGrouping) {
309 if (lastRow < rowGroupIndices->back()) {
314 if (overriddenRowCount != 0) {
315 STORM_LOG_THROW(rowCount <= overriddenRowCount, storm::exceptions::InvalidStateException,
316 "Expected not more than " << overriddenRowCount <<
" rows, but got " << rowCount <<
".");
318 if (initialRowCountSet && forceInitialDimensions) {
319 STORM_LOG_THROW(rowCount <= initialRowCount, storm::exceptions::InvalidStateException,
320 "Expected not more than " << initialRowCount <<
" rows, but got " << rowCount <<
".");
321 rowCount = std::max(rowCount, initialRowCount);
323 rowCount = std::max(rowCount, overriddenRowCount);
327 rowIndications.push_back(currentEntryCount);
334 rowIndications.push_back(currentEntryCount);
337 "Wrong sizes of row indications vector: (Rowcount) " << rowCount <<
" != " << (rowIndications.size() - 1) <<
" (Vector).");
338 uint_fast64_t columnCount = hasEntries ? highestColumn + 1 : 0;
339 if (overriddenColumnCount != 0) {
340 STORM_LOG_THROW(columnCount <= overriddenColumnCount, storm::exceptions::InvalidStateException,
341 "Expected not more than " << overriddenColumnCount <<
" columns, but got " << columnCount <<
".");
343 if (initialColumnCountSet && forceInitialDimensions) {
344 STORM_LOG_THROW(columnCount <= initialColumnCount, storm::exceptions::InvalidStateException,
345 "Expected not more than " << initialColumnCount <<
" columns, but got " << columnCount <<
".");
346 columnCount = std::max(columnCount, initialColumnCount);
348 columnCount = std::max(columnCount, overriddenColumnCount);
350 uint_fast64_t entryCount = currentEntryCount;
351 if (initialEntryCountSet && forceInitialDimensions) {
352 STORM_LOG_THROW(entryCount == initialEntryCount, storm::exceptions::InvalidStateException,
353 "Expected " << initialEntryCount <<
" entries, but got " << entryCount <<
".");
357 if (hasCustomRowGrouping) {
358 uint_fast64_t rowGroupCount = currentRowGroupCount;
359 if (overriddenRowGroupCount != 0) {
360 STORM_LOG_THROW(rowGroupCount <= overriddenRowGroupCount, storm::exceptions::InvalidStateException,
361 "Expected not more than " << overriddenRowGroupCount <<
" row groups, but got " << rowGroupCount <<
".");
363 if (initialRowGroupCountSet && forceInitialDimensions) {
364 STORM_LOG_THROW(rowGroupCount <= initialRowGroupCount, storm::exceptions::InvalidStateException,
365 "Expected not more than " << initialRowGroupCount <<
" row groups, but got " << rowGroupCount <<
".");
366 rowGroupCount = std::max(rowGroupCount, initialRowGroupCount);
368 rowGroupCount = std::max(rowGroupCount, overriddenRowGroupCount);
370 for (
index_type i = currentRowGroupCount;
i <= rowGroupCount; ++
i) {
371 rowGroupIndices.get().push_back(rowCount);
375 return SparseMatrix<ValueType>(columnCount, std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices));
378template<
typename ValueType>
383template<
typename ValueType>
385 if (this->hasCustomRowGrouping) {
386 return currentRowGroupCount;
388 return getLastRow() + 1;
392template<
typename ValueType>
398template<
typename ValueType>
406 std::cout <<
"\t---- group " << group <<
"/" << (rowGroupIndices.size() - 1) <<
" ---- \n";
407 endGroups = group < rowGroupIndices.size() - 1 ? rowGroupIndices[group + 1] : rowIndications.size();
410 endRows =
i < rowIndications.size() - 1 ? rowIndications[
i + 1] : columnsAndValues.size();
412 std::cout <<
"Row " <<
i <<
" (" << rowIndications[
i] <<
" - " << endRows <<
")"
415 std::cout <<
"(" << columnsAndValues[pos].getColumn() <<
": " << columnsAndValues[pos].getValue() <<
") ";
422template<
typename ValueType>
426 for (
index_type row = 0; row < rowIndications.size(); ++row) {
427 bool changed =
false;
428 auto startRow = std::next(columnsAndValues.begin(), rowIndications[row]);
429 auto endRow = row < rowIndications.size() - 1 ? std::next(columnsAndValues.begin(), rowIndications[row + 1]) : columnsAndValues.end();
430 for (
auto entry = startRow; entry != endRow; ++entry) {
431 if (entry->getColumn() >= offset) {
433 entry->setColumn(replacements[entry->getColumn() - offset]);
436 maxColumn = std::max(maxColumn, entry->getColumn());
440 std::sort(startRow, endRow,
447 "Columns not sorted.");
451 highestColumn = maxColumn;
452 lastColumn = columnsAndValues.empty() ? 0 : columnsAndValues.back().getColumn();
455template<
typename ValueType>
457 STORM_LOG_THROW(row >= lastRow, storm::exceptions::InvalidArgumentException,
458 "Adding a diagonal element in row " << row <<
", but an element in row " << lastRow <<
" has already been added.");
459 if (pendingDiagonalEntry) {
460 if (row == lastRow) {
462 index_type column = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
463 pendingDiagonalEntry = accumulate(accumulationMode, row, column, pendingDiagonalEntry.get(), value);
467 index_type column = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
468 ValueType diagValue = std::move(pendingDiagonalEntry.get());
469 pendingDiagonalEntry = boost::none;
473 pendingDiagonalEntry = value;
474 if (lastRow != row) {
475 STORM_LOG_ASSERT(rowIndications.size() == lastRow + 1,
"Row indications size mismatch.");
476 rowIndications.resize(row + 1, currentEntryCount);
482template<
typename ValueType>
487template<
typename ValueType>
489 return beginIterator;
492template<
typename ValueType>
494 return beginIterator + entryCount;
497template<
typename ValueType>
499 return this->entryCount;
502template<
typename ValueType>
507template<
typename ValueType>
509 return beginIterator;
512template<
typename ValueType>
514 return beginIterator + entryCount;
517template<
typename ValueType>
519 return this->entryCount;
522template<
typename ValueType>
524 : rowCount(0), columnCount(0), entryCount(0), nonzeroEntryCount(0), columnsAndValues(), rowIndications(), rowGroupIndices() {
528template<
typename ValueType>
530 : rowCount(other.rowCount),
531 columnCount(other.columnCount),
532 entryCount(other.entryCount),
533 nonzeroEntryCount(other.nonzeroEntryCount),
534 columnsAndValues(other.columnsAndValues),
535 rowIndications(other.rowIndications),
536 trivialRowGrouping(other.trivialRowGrouping),
537 rowGroupIndices(other.rowGroupIndices) {
541template<
typename ValueType>
545 *
this = other.
getSubmatrix(
false, rowConstraint, columnConstraint, insertDiagonalElements);
548template<
typename ValueType>
550 : rowCount(other.rowCount),
551 columnCount(other.columnCount),
552 entryCount(other.entryCount),
553 nonzeroEntryCount(other.nonzeroEntryCount),
554 columnsAndValues(
std::move(other.columnsAndValues)),
555 rowIndications(
std::move(other.rowIndications)),
556 trivialRowGrouping(other.trivialRowGrouping),
557 rowGroupIndices(
std::move(other.rowGroupIndices)) {
560 other.columnCount = 0;
561 other.entryCount = 0;
564template<
typename ValueType>
567 boost::optional<std::vector<index_type>>
const& rowGroupIndices)
568 : rowCount(rowIndications.size() - 1),
569 columnCount(columnCount),
570 entryCount(columnsAndValues.size()),
571 nonzeroEntryCount(0),
572 columnsAndValues(columnsAndValues),
573 rowIndications(rowIndications),
574 trivialRowGrouping(!rowGroupIndices),
575 rowGroupIndices(rowGroupIndices) {
579template<
typename ValueType>
582 boost::optional<std::vector<index_type>>&& rowGroupIndices)
583 : columnCount(columnCount),
584 nonzeroEntryCount(0),
585 columnsAndValues(
std::move(columnsAndValues)),
586 rowIndications(
std::move(rowIndications)),
587 rowGroupIndices(
std::move(rowGroupIndices)) {
590 this->rowCount = this->rowIndications.size() - 1;
591 this->entryCount = this->columnsAndValues.size();
592 this->trivialRowGrouping = !this->rowGroupIndices;
596template<
typename ValueType>
599 if (
this != &other) {
600 rowCount = other.rowCount;
601 columnCount = other.columnCount;
602 entryCount = other.entryCount;
603 nonzeroEntryCount = other.nonzeroEntryCount;
605 columnsAndValues = other.columnsAndValues;
606 rowIndications = other.rowIndications;
607 rowGroupIndices = other.rowGroupIndices;
608 trivialRowGrouping = other.trivialRowGrouping;
613template<
typename ValueType>
616 if (
this != &other) {
617 rowCount = other.rowCount;
618 columnCount = other.columnCount;
619 entryCount = other.entryCount;
620 nonzeroEntryCount = other.nonzeroEntryCount;
622 columnsAndValues = std::move(other.columnsAndValues);
623 rowIndications = std::move(other.rowIndications);
624 rowGroupIndices = std::move(other.rowGroupIndices);
625 trivialRowGrouping = other.trivialRowGrouping;
630template<
typename ValueType>
632 if (
this == &other) {
636 bool equalityResult =
true;
639 if (!equalityResult) {
642 equalityResult &= this->getColumnCount() == other.
getColumnCount();
643 if (!equalityResult) {
651 if (!equalityResult) {
667 if (it1 == ite1 || it2 == ite2) {
669 if (it1 != ite1 || it2 != ite2) {
674 if (it1->getColumn() != it2->getColumn() || it1->getValue() != it2->getValue()) {
682 return equalityResult;
685template<
typename ValueType>
690template<
typename ValueType>
695template<
typename ValueType>
700template<
typename ValueType>
709 return getRowEntryCount(group);
713template<
typename ValueType>
715 return (this->rowIndications[row + 1] - this->rowIndications[row]);
718template<
typename ValueType>
720 return nonzeroEntryCount;
723template<
typename ValueType>
725 this->nonzeroEntryCount = 0;
726 for (
auto const& element : *
this) {
728 ++this->nonzeroEntryCount;
733template<
typename ValueType>
735 this->nonzeroEntryCount += difference;
738template<
typename ValueType>
740 this->nonzeroEntryCount = 0;
741 this->columnCount = 0;
742 for (
auto const& element : *
this) {
744 ++this->nonzeroEntryCount;
745 this->columnCount = std::max(element.getColumn() + 1, this->columnCount);
750template<
typename ValueType>
753 return rowGroupIndices.get().size() - 1;
759template<
typename ValueType>
764template<
typename ValueType>
770 index_type previousGroupStart = 0;
771 for (
auto const&
i : rowGroupIndices.get()) {
772 res = std::max(res,
i - previousGroupStart);
773 previousGroupStart =
i;
778template<
typename ValueType>
790 numRows +=
end - start;
796template<
typename ValueType>
799 if (!this->rowGroupIndices) {
800 STORM_LOG_ASSERT(trivialRowGrouping,
"Only trivial row-groupings can be constructed on-the-fly.");
803 return rowGroupIndices.get();
806template<
typename ValueType>
808 return rowIndications;
811template<
typename ValueType>
814 "Invalid row group index:" << group <<
". Only " << this->
getRowGroupCount() <<
" row groups available.");
815 if (this->rowGroupIndices) {
816 return boost::irange(rowGroupIndices.get()[group], rowGroupIndices.get()[group + 1]);
818 return boost::irange(group, group + 1);
822template<
typename ValueType>
824 std::vector<index_type> result;
825 if (this->rowGroupIndices) {
826 result = std::move(rowGroupIndices.get());
827 rowGroupIndices = std::move(newRowGrouping);
832template<
typename ValueType>
834 trivialRowGrouping =
false;
835 rowGroupIndices = newRowGroupIndices;
838template<
typename ValueType>
840 return trivialRowGrouping;
843template<
typename ValueType>
845 if (trivialRowGrouping) {
848 "Row grouping is supposed to be trivial but actually it is not.");
850 trivialRowGrouping =
true;
851 rowGroupIndices = boost::none;
855template<
typename ValueType>
858 for (uint64_t group : groupConstraint) {
864template<
typename ValueType>
868 for (uint64_t group : groupConstraint) {
870 bool choiceSatisfiesColumnConstraint =
true;
871 for (
auto const& entry : this->
getRow(row)) {
872 if (!columnConstraint.
get(entry.getColumn())) {
873 choiceSatisfiesColumnConstraint =
false;
877 if (choiceSatisfiesColumnConstraint) {
885template<
typename ValueType>
890 if (setIfForAllRowsInGroup) {
892 if (rowConstraint.
getNextUnsetIndex(groupIndices[group]) >= groupIndices[group + 1]) {
894 result.
set(group,
true);
898 for (uint64_t group = 0; group < this->getRowGroupCount(); ++group) {
901 result.
set(group,
true);
908template<
typename ValueType>
912 for (uint64_t row : rows) {
915 if (dropZeroEntries) {
916 this->dropZeroEntries();
920template<
typename ValueType>
925 for (uint64_t rowGroup : rowGroupConstraint) {
931 for (uint64_t rowGroup : rowGroupConstraint) {
932 makeRowDirac(rowGroup, rowGroup,
false);
935 if (dropZeroEntries) {
936 this->dropZeroEntries();
940template<
typename ValueType>
947 STORM_LOG_THROW(columnValuePtr < columnValuePtrEnd, storm::exceptions::InvalidStateException,
948 "Illegal call to SparseMatrix::makeRowDirac: cannot make row " << row <<
" absorbing, because there is no entry in this row.");
954 while (columnValuePtr->getColumn() < column && columnValuePtr != lastColumnValuePtr) {
956 --this->nonzeroEntryCount;
963 ++this->nonzeroEntryCount;
966 columnValuePtr->setColumn(column);
967 for (++columnValuePtr; columnValuePtr != columnValuePtrEnd; ++columnValuePtr) {
969 --this->nonzeroEntryCount;
973 if (dropZeroEntries) {
974 this->dropZeroEntries();
978template<
typename ValueType>
984 for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
989 if (it1 == end1 && it2 == end2) {
995template<
typename ValueType>
1000 for (
size_t row2 = row1; row2 < this->
getRowGroupIndices().at(rowgroup + 1); ++row2) {
1010template<
typename ValueType>
1017 index_type largerRow =
getRow(row1).getNumberOfEntries() >
getRow(row2).getNumberOfEntries() ? row1 : row2;
1018 index_type smallerRow = largerRow == row1 ? row2 : row1;
1019 index_type rowSizeDifference =
getRow(largerRow).getNumberOfEntries() -
getRow(smallerRow).getNumberOfEntries();
1022 auto copyRow =
getRow(largerRow);
1023 std::vector<MatrixEntry<index_type, value_type>> largerRowContents(copyRow.begin(), copyRow.end());
1025 if (largerRow < smallerRow) {
1026 auto writeIt =
getRows(largerRow, smallerRow + 1).begin();
1029 for (
auto& smallerRowEntry :
getRow(smallerRow)) {
1030 *writeIt = std::move(smallerRowEntry);
1036 for (
auto& intermediateRowEntry : getRows(largerRow + 1, smallerRow)) {
1037 *writeIt = std::move(intermediateRowEntry);
1042 writeIt = getRow(smallerRow).begin();
1046 for (
auto& largerRowEntry : largerRowContents) {
1047 *writeIt = std::move(largerRowEntry);
1051 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).end(),
"Unexpected position of write iterator.");
1055 for (
index_type row = largerRow + 1; row <= smallerRow; ++row) {
1056 rowIndications[row] -= rowSizeDifference;
1060 auto writeIt = getRows(smallerRow, largerRow + 1).end() - 1;
1063 auto copyRow =
getRow(smallerRow);
1064 for (
auto smallerRowEntryIt = copyRow.end() - 1; smallerRowEntryIt != copyRow.begin() - 1; --smallerRowEntryIt) {
1065 *writeIt = std::move(*smallerRowEntryIt);
1071 for (
auto intermediateRowEntryIt =
getRows(smallerRow + 1, largerRow).
end() - 1;
1072 intermediateRowEntryIt !=
getRows(smallerRow + 1, largerRow).begin() - 1; --intermediateRowEntryIt) {
1073 *writeIt = std::move(*intermediateRowEntryIt);
1078 writeIt = getRow(smallerRow).end() - 1;
1082 for (
auto largerRowEntryIt = largerRowContents.rbegin(); largerRowEntryIt != largerRowContents.rend(); ++largerRowEntryIt) {
1083 *writeIt = std::move(*largerRowEntryIt);
1092 for (
index_type row = smallerRow + 1; row <= largerRow; ++row) {
1093 rowIndications[row] += rowSizeDifference;
1099template<
typename ValueType>
1101 std::vector<ValueType> result(this->
getRowCount());
1104 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++row) {
1111template<
typename ValueType>
1115 if (constraint.
get(it->getColumn())) {
1116 result += it->getValue();
1122template<
typename ValueType>
1127 for (uint64_t row : rowConstraint) {
1133template<
typename ValueType>
1136 std::vector<ValueType> result;
1139 for (uint64_t rowGroup : rowGroupConstraint) {
1145 for (uint64_t rowGroup : rowGroupConstraint) {
1152template<
typename ValueType>
1158 if (makeZeroColumns.
size() > 0) {
1159 makeZeroColumnsRef.
reset(makeZeroColumns);
1162 return submatrixBuilder.
getByRowGroupConstraint(rowConstraint, columnConstraint, insertDiagonalElements, makeZeroColumnsRef);
1164 return submatrixBuilder.
getByRowConstraint(rowConstraint, columnConstraint, insertDiagonalElements, makeZeroColumnsRef);
1168template<
typename ValueType>
1174 for (uint64_t row : rowsToKeep) {
1175 entryCount += this->
getRow(row).getNumberOfEntries();
1184 --firstTrailingEmptyRowGroup;
1186 STORM_LOG_THROW(allowEmptyRowGroups || firstTrailingEmptyRowGroup == this->getRowGroupCount(), storm::exceptions::InvalidArgumentException,
1187 "Empty rows are not allowed, but row group " << firstTrailingEmptyRowGroup <<
" is empty.");
1190 SparseMatrixBuilder<ValueType>
builder(rowsToKeep.
getNumberOfSetBits(), this->getColumnCount(), entryCount,
true,
true, this->getRowGroupCount());
1191 index_type newRow = 0;
1192 for (index_type rowGroup = 0; rowGroup < firstTrailingEmptyRowGroup; ++rowGroup) {
1195 bool rowGroupEmpty =
true;
1196 for (index_type row = rowsToKeep.
getNextSetIndex(this->getRowGroupIndices()[rowGroup]); row < this->getRowGroupIndices()[rowGroup + 1];
1198 rowGroupEmpty =
false;
1199 for (
auto const& entry : this->
getRow(row)) {
1200 builder.addNextValue(newRow, entry.getColumn(), entry.getValue());
1204 STORM_LOG_THROW(allowEmptyRowGroups || !rowGroupEmpty, storm::exceptions::InvalidArgumentException,
1205 "Empty rows are not allowed, but row group " << rowGroup <<
" is empty.");
1209 SparseMatrix<ValueType> res =
builder.build();
1213template<
typename ValueType>
1217 for (uint64_t row : rowFilter) {
1218 entryCount +=
getRow(row).getNumberOfEntries();
1223 for (uint64_t row : rowFilter) {
1224 for (
auto const& entry :
getRow(row)) {
1225 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1231 if (!hasTrivialRowGrouping()) {
1237template<
typename ValueType>
1243 for (
auto const& entry :
getRow(row)) {
1245 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1254 *
this = std::move(result);
1258template<
typename ValueType>
1260 bool insertDiagonalEntries)
const {
1264 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1267 "Cannot point to row offset " << rowGroupToRowIndexMapping[rowGroupIndex] <<
" for rowGroup " << rowGroupIndex <<
" which starts at "
1273 bool foundDiagonalElement =
false;
1275 if (it->getColumn() == rowGroupIndex) {
1276 foundDiagonalElement =
true;
1280 if (insertDiagonalEntries && !foundDiagonalElement) {
1289 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1295 bool insertedDiagonalElement =
false;
1297 if (it->getColumn() == rowGroupIndex) {
1298 insertedDiagonalElement =
true;
1299 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > rowGroupIndex) {
1301 insertedDiagonalElement =
true;
1303 matrixBuilder.
addNextValue(rowGroupIndex, it->getColumn(), it->getValue());
1305 if (insertDiagonalEntries && !insertedDiagonalElement) {
1311 return matrixBuilder.
build();
1314template<
typename ValueType>
1316 bool insertDiagonalEntries)
const {
1320 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1321 bool foundDiagonalElement =
false;
1322 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1323 if (it->getColumn() == row) {
1324 foundDiagonalElement =
true;
1328 if (insertDiagonalEntries && !foundDiagonalElement) {
1337 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1338 bool insertedDiagonalElement =
false;
1339 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1340 if (it->getColumn() == row) {
1341 insertedDiagonalElement =
true;
1342 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > row) {
1344 insertedDiagonalElement =
true;
1346 matrixBuilder.
addNextValue(row, it->getColumn(), it->getValue());
1348 if (insertDiagonalEntries && !insertedDiagonalElement) {
1354 return matrixBuilder.
build();
1357template<
typename ValueType>
1365 for (
index_type writeTo = 0; writeTo < inversePermutation.size(); ++writeTo) {
1366 index_type const& readFrom = inversePermutation[writeTo];
1367 auto row = this->
getRow(readFrom);
1368 for (
auto const& entry : row) {
1369 matrixBuilder.
addNextValue(writeTo, entry.getColumn(), entry.getValue());
1373 auto result = matrixBuilder.
build();
1374 if (this->rowGroupIndices) {
1380template<
typename ValueType>
1382 std::vector<index_type>
const& columnPermutation)
const {
1387 auto oldGroupIt = inverseRowGroupPermutation.cbegin();
1389 while (newRowIndex < rowCount) {
1394 for (
auto const& oldEntry :
getRow(oldRowIndex)) {
1395 matrixBuilder.
addNextValue(newRowIndex, columnPermutation[oldEntry.getColumn()], oldEntry.getValue());
1401 return matrixBuilder.
build();
1404template<
typename ValueType>
1416 std::vector<index_type> rowIndications(rowCount + 1);
1417 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1420 for (
index_type group = 0; group < columnCount; ++group) {
1421 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1423 ++rowIndications[transition.getColumn() + 1];
1430 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1436 std::vector<index_type> nextIndices = rowIndications;
1439 for (
index_type group = 0; group < columnCount; ++group) {
1440 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1442 columnsAndValues[nextIndices[transition.getColumn()]] = std::make_pair(group, transition.getValue());
1443 nextIndices[transition.getColumn()]++;
1450 return transposedMatrix;
1453template<
typename ValueType>
1460 std::vector<index_type> rowIndications(columnCount + 1);
1461 auto rowGroupChoiceIt = rowGroupChoices.begin();
1462 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1463 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1466 ++rowIndications[entry.getColumn() + 1];
1473 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1476 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1481 std::vector<index_type> nextIndices = rowIndications;
1484 rowGroupChoiceIt = rowGroupChoices.begin();
1485 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1486 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1488 columnsAndValues[nextIndices[entry.getColumn()]] = std::make_pair(rowGroup, entry.getValue());
1489 ++nextIndices[entry.getColumn()];
1497template<
typename ValueType>
1503template<
typename ValueType>
1509 bool foundDiagonalElement =
false;
1512 if (entry.getColumn() == group) {
1513 if (entry.getValue() == one) {
1514 --this->nonzeroEntryCount;
1515 entry.setValue(zero);
1516 }
else if (entry.getValue() == zero) {
1517 ++this->nonzeroEntryCount;
1518 entry.setValue(one);
1520 entry.setValue(one - entry.getValue());
1522 foundDiagonalElement =
true;
1527 STORM_LOG_THROW(foundDiagonalElement, storm::exceptions::InvalidArgumentException,
1528 "Illegal call to SparseMatrix::invertDiagonal: matrix is missing diagonal entries.");
1532template<
typename ValueType>
1537 if (entry.getColumn() != group) {
1538 entry.setValue(-entry.getValue());
1544template<
typename ValueType>
1549 if (entry.getColumn() == group) {
1550 --this->nonzeroEntryCount;
1556 this->dropZeroEntries();
1560template<
typename ValueType>
1563 "Canno compute Jacobi decomposition of non-square matrix.");
1567 std::vector<ValueType> invertedDiagonal(rowCount);
1570 for (
index_type rowNumber = 0; rowNumber < rowCount; ++rowNumber) {
1572 if (it->getColumn() == rowNumber) {
1575 luBuilder.
addNextValue(rowNumber, it->getColumn(), it->getValue());
1580 return std::make_pair(luBuilder.
build(), std::move(invertedDiagonal));
1585 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1591 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1594template<
typename ValueType>
1595template<
typename OtherValueType,
typename ResultValueType>
1604 for (; it1 != ite1 && it2 != ite2; ++it1) {
1605 if (it1->getColumn() < it2->getColumn()) {
1611 STORM_LOG_ASSERT(it1->getColumn() == it2->getColumn(),
"The given matrix is not a submatrix of this one.");
1612 result += it2->getValue() * OtherValueType(it1->getValue());
1619template<
typename ValueType>
1620template<
typename OtherValueType,
typename ResultValueType>
1622 std::vector<ResultValueType> result;
1623 result.reserve(rowCount);
1630template<
typename ValueType>
1632 std::vector<value_type>
const* summand)
const {
1634 std::vector<ValueType>* target;
1635 std::vector<ValueType> temporary;
1636 if (&vector == &result) {
1637 STORM_LOG_WARN(
"Vectors are aliased. Using temporary, which is potentially slow.");
1638 temporary = std::vector<ValueType>(vector.size());
1639 target = &temporary;
1646 if (target == &temporary) {
1647 std::swap(result, *target);
1651template<
typename ValueType>
1653 std::vector<value_type>
const* summand)
const {
1656 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1657 typename std::vector<ValueType>::iterator resultIterator = result.begin();
1658 typename std::vector<ValueType>::iterator resultIteratorEnd = result.end();
1659 typename std::vector<ValueType>::const_iterator summandIterator;
1661 summandIterator = summand->begin();
1664 for (; resultIterator != resultIteratorEnd; ++rowIterator, ++resultIterator, ++summandIterator) {
1667 newValue = *summandIterator;
1672 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1673 newValue += it->getValue() * vector[it->getColumn()];
1676 *resultIterator = newValue;
1680template<
typename ValueType>
1682 std::vector<value_type>
const* summand)
const {
1685 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1686 typename std::vector<ValueType>::iterator resultIterator = result.end() - 1;
1687 typename std::vector<ValueType>::iterator resultIteratorEnd = result.begin() - 1;
1688 typename std::vector<ValueType>::const_iterator summandIterator;
1690 summandIterator = summand->end() - 1;
1693 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --summandIterator) {
1696 newValue = *summandIterator;
1701 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1702 newValue += (it->getValue() * vector[it->getColumn()]);
1705 *resultIterator = newValue;
1709template<
typename ValueType>
1713 for (
auto const& entry : this->
getRow(row)) {
1714 result += entry.getValue() * vector[entry.getColumn()];
1719template<
typename ValueType>
1723 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1724 typename std::vector<ValueType>::const_iterator bIt = b.end() - 1;
1725 typename std::vector<ValueType>::iterator resultIterator = x.end() - 1;
1726 typename std::vector<ValueType>::iterator resultIteratorEnd = x.begin() - 1;
1729 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --bIt) {
1734 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1735 if (it->getColumn() != currentRow) {
1736 tmpValue += it->getValue() * x[it->getColumn()];
1738 diagonalElement += it->getValue();
1748 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1751template<
typename ValueType>
1753 std::vector<ValueType>
const& ax, std::vector<ValueType>& result)
const {
1756 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1760 for (
auto& entry : result) {
1764 for (
index_type row = 0; row < rowCount; ++row, ++rowIterator) {
1765 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1766 result[it->getColumn()] += it->getValue() * (b[row] / ax[row]);
1770 auto xIterator = x.begin();
1771 auto sumsIterator = columnSums.begin();
1772 for (
auto& entry : result) {
1773 entry *= *xIterator / *sumsIterator;
1781 std::vector<Interval>
const& ax, std::vector<Interval>& result)
const {
1782 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1785template<
typename ValueType>
1787 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1788 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1789 if (dir == OptimizationDirection::Minimize) {
1796template<
typename ValueType>
1797template<
typename Compare>
1799 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1800 std::vector<uint64_t>* choices)
const {
1802 auto elementIt = this->
begin();
1803 auto rowGroupIt = rowGroupIndices.begin();
1804 auto rowIt = rowIndications.begin();
1805 typename std::vector<ValueType>::const_iterator summandIt;
1807 summandIt = summand->begin();
1809 typename std::vector<uint64_t>::iterator choiceIt;
1811 choiceIt = choices->begin();
1815 ValueType oldSelectedChoiceValue;
1816 uint64_t selectedChoice;
1818 uint64_t currentRow = 0;
1819 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt) {
1823 if (*rowGroupIt < *(rowGroupIt + 1)) {
1825 currentValue = *summandIt;
1829 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1830 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
1835 if (*choiceIt == 0) {
1836 oldSelectedChoiceValue = currentValue;
1843 for (; currentRow < *(rowGroupIt + 1); ++rowIt, ++currentRow) {
1845 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1846 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
1849 if (choices && currentRow == *choiceIt + *rowGroupIt) {
1850 oldSelectedChoiceValue = newValue;
1853 if (compare(newValue, currentValue)) {
1854 currentValue = newValue;
1856 selectedChoice = currentRow - *rowGroupIt;
1865 *resultIt = currentValue;
1866 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
1867 *choiceIt = selectedChoice;
1875 std::vector<storm::RationalFunction>
const& vector,
1876 std::vector<storm::RationalFunction>
const* b,
1877 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
1878 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1881template<
typename ValueType>
1883 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1884 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1885 if (dir == storm::OptimizationDirection::Minimize) {
1892template<
typename ValueType>
1893template<
typename Compare>
1895 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1896 std::vector<uint64_t>* choices)
const {
1898 auto elementIt = this->
end() - 1;
1899 auto rowGroupIt = rowGroupIndices.end() - 2;
1900 auto rowIt = rowIndications.end() - 2;
1901 typename std::vector<ValueType>::const_iterator summandIt;
1903 summandIt = summand->end() - 1;
1905 typename std::vector<uint64_t>::iterator choiceIt;
1907 choiceIt = choices->end() - 1;
1911 ValueType oldSelectedChoiceValue;
1912 uint64_t selectedChoice;
1915 for (
auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt) {
1919 if (*rowGroupIt < *(rowGroupIt + 1)) {
1921 currentValue = *summandIt;
1925 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
1926 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
1929 selectedChoice = currentRow - *rowGroupIt;
1930 if (*choiceIt == selectedChoice) {
1931 oldSelectedChoiceValue = currentValue;
1937 for (uint64_t
i = *rowGroupIt + 1,
end = *(rowGroupIt + 1);
i <
end; --rowIt, --currentRow, ++
i, --summandIt) {
1939 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
1940 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
1943 if (choices && currentRow == *choiceIt + *rowGroupIt) {
1944 oldSelectedChoiceValue = newValue;
1947 if (compare(newValue, currentValue)) {
1948 currentValue = newValue;
1950 selectedChoice = currentRow - *rowGroupIt;
1956 *resultIt = currentValue;
1957 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
1958 *choiceIt = selectedChoice;
1966 std::vector<storm::RationalFunction>
const& vector,
1967 std::vector<storm::RationalFunction>
const* b,
1968 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
1969 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1972template<
typename ValueType>
1974 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1975 std::vector<uint64_t>* choices)
const {
1977 std::vector<ValueType>* target;
1978 std::vector<ValueType> temporary;
1979 if (&vector == &result) {
1980 STORM_LOG_WARN(
"Vectors are aliased but are not allowed to be. Using temporary, which is potentially slow.");
1981 temporary = std::vector<ValueType>(vector.size());
1982 target = &temporary;
1989 if (target == &temporary) {
1990 std::swap(temporary, result);
1994template<
typename ValueType>
1998 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1999 std::vector<index_type>::const_iterator rowIteratorEnd = rowIndications.end();
2002 for (; rowIterator != rowIteratorEnd - 1; ++rowIterator) {
2003 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
2004 result[it->getColumn()] += it->getValue() * vector[currentRow];
2010template<
typename ValueType>
2012 STORM_LOG_ASSERT(factors.size() == this->getRowCount(),
"Can not scale rows: Number of rows and number of scaling factors do not match.");
2014 for (
auto const& factor : factors) {
2015 for (
auto& entry :
getRow(row)) {
2016 entry.setValue(entry.getValue() * factor);
2022template<
typename ValueType>
2024 STORM_LOG_ASSERT(divisors.size() == this->getRowCount(),
"Can not divide rows: Number of rows and number of divisors do not match.");
2026 for (
auto const& divisor : divisors) {
2028 for (
auto& entry :
getRow(row)) {
2029 entry.setValue(entry.getValue() / divisor);
2037 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
2040template<
typename ValueType>
2042 return const_rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2045template<
typename ValueType>
2047 return rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2050template<
typename ValueType>
2055template<
typename ValueType>
2060template<
typename ValueType>
2068 return getRow(rowGroup + offset);
2072template<
typename ValueType>
2080 return getRow(rowGroup + offset);
2084template<
typename ValueType>
2090 return getRows(rowGroup, rowGroup + 1);
2094template<
typename ValueType>
2100 return getRows(rowGroup, rowGroup + 1);
2104template<
typename ValueType>
2107 return this->columnsAndValues.begin() + this->rowIndications[row];
2110template<
typename ValueType>
2113 return this->columnsAndValues.begin() + this->rowIndications[row];
2116template<
typename ValueType>
2118 return this->columnsAndValues.begin();
2121template<
typename ValueType>
2123 return this->columnsAndValues.begin();
2126template<
typename ValueType>
2129 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2132template<
typename ValueType>
2135 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2138template<
typename ValueType>
2140 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2143template<
typename ValueType>
2145 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2148template<
typename ValueType>
2152 sum += it->getValue();
2157template<
typename ValueType>
2160 for (
auto const& entry : *
this) {
2165 return nonConstEntries;
2168template<
typename ValueType>
2172 for (
auto const& entry : this->
getRowGroup(rowGroup)) {
2174 ++nonConstRowGroups;
2179 return nonConstRowGroups;
2182template<
typename ValueType>
2189 auto toBaseType = [](ValueType
const& value) {
2190 if constexpr (std::is_same_v<ValueType, BaseType>) {
2201 auto isContained = [&toBaseType](ValueType
const& value, BaseType
const& lower, BaseType
const& upper) {
2206 return value.lower() <= upper && value.upper() >= lower;
2207 }
else if constexpr (std::is_same_v<ValueType, storm::RationalFunction>) {
2210 auto const constValue = toBaseType(value);
2211 return constValue <= upper && constValue >= lower;
2217 return value <= upper && value >= lower;
2221 auto toString = [](ValueType
const& value) {
2222 std::stringstream s;
2227 for (
index_type row = 0; row < this->rowCount; ++row) {
2229 for (
auto const& entry :
getRow(row)) {
2230 if (!isContained(entry.getValue(), zeroMinusTolerance, onePlusTolerance)) {
2232 *reason =
"Entry in row " + std::to_string(row) +
" is not a probability: " +
toString(entry.getValue());
2236 rowSum += entry.getValue();
2238 if (!isContained(rowSum, oneMinusTolerance, onePlusTolerance)) {
2249template<
typename ValueType>
2251 for (
auto const& entry : *
this) {
2259template<
typename ValueType>
2265 for (
auto const& entry : this->
getRow(row)) {
2266 sumOfUpperBounds += entry.getValue().upper();
2268 for (
auto const& entry : this->
getRow(row)) {
2270 BaseType
const tightenedLower =
2283template<
typename ValueType>
2284template<
typename OtherValueType>
2289 (!this->hasTrivialRowGrouping() && this->getRowGroupIndices() != matrix.
getRowGroupIndices())) {
2295 auto it2 = matrix.
begin(row);
2296 auto ite2 = matrix.
end(row);
2299 while (it2 != ite2 && it2->getColumn() < it1->getColumn()) {
2302 if (it2 == ite2 || it1->getColumn() != it2->getColumn()) {
2310template<
typename ValueType>
2318 for (uint64_t row = 0; row < this->
getRowCount(); ++row) {
2319 bool rowHasEntry =
false;
2320 for (
auto const& entry : this->
getRow(row)) {
2321 if (entry.getColumn() == row) {
2339template<
typename ValueType>
2341 std::string result =
2350template<
typename ValueType>
2361 out <<
"\t---- group " << group <<
"/" << (matrix.
getRowGroupCount() - 1) <<
" ---- \n";
2369 out <<
i <<
"\t(\t";
2371 while (currentRealIndex < matrix.columnCount) {
2372 if (nextIndex < matrix.rowIndications[
i + 1] && currentRealIndex == matrix.columnsAndValues[nextIndex].getColumn()) {
2373 out << matrix.columnsAndValues[nextIndex].getValue() <<
"\t";
2380 out <<
"\t)\t" <<
i <<
'\n';
2394template<
typename ValueType>
2405 while (currentRealIndex < this->columnCount) {
2406 if (nextIndex < this->rowIndications[
i + 1] && currentRealIndex == this->columnsAndValues[nextIndex].getColumn()) {
2407 out << this->columnsAndValues[nextIndex].getValue() <<
" ";
2419template<
typename ValueType>
2421 std::size_t result = 0;
2426 boost::hash_combine(result, boost::hash_range(columnsAndValues.begin(), columnsAndValues.end()));
2427 boost::hash_combine(result, boost::hash_range(rowIndications.begin(), rowIndications.end()));
2429 boost::hash_combine(result, boost::hash_range(rowGroupIndices.get().begin(), rowGroupIndices.get().end()));
Helper class that optionally holds a reference to an object of type T.
void reset()
Unsets the reference.
A bit vector that is internally represented as a vector of 64-bit values.
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.
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.
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
Retrieves an iterator that points past the last entry of the rows.
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.
AccumulationMode
Specifies how values that are added for the same row and column are combined.
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.
void setAccumulationMode(AccumulationMode mode)
Sets how values that are added for the same row and column are combined.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
AccumulationMode getAccumulationMode() const
Retrieves how values that are added for the same row and column are combined.
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
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
Computes the sum of the entries in a given row.
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)
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...
bool isProbabilisticGraphPreserving() const
Checks whether the support graph of the matrix is preserved by every way of resolving the uncertainty...
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.
Helper class to extract submatrices of a fixed sparse matrix.
SparseMatrix< ValueType > getByRowGroupConstraint(RowConstraintType const &rowGroupConstraint, ColumnConstraintType const &columnConstraint, bool const insertDiagonalElement, storm::OptionalRef< storm::storage::BitVector const > makeZeroColumns=storm::NullRef) const
Creates the submatrix that keeps only the given row groups and columns The row group structure of the...
SparseMatrix< ValueType > getByRowConstraint(RowConstraintType const &rowConstraint, ColumnConstraintType const &columnConstraint, bool const insertDiagonalElement, storm::OptionalRef< storm::storage::BitVector const > makeZeroColumns=storm::NullRef) const
Creates the submatrix that keeps only the given rows and columns If the matrix has a non-trivial row ...
#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.
static const bool IsExact