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 assert(rowIndications.size() == lastRow + 1);
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 assert(rowIndications.size() == lastRow + 1);
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 <<
")" <<
": ";
389 std::cout <<
"(" << columnsAndValues[pos].getColumn() <<
": " << columnsAndValues[pos].getValue() <<
") ";
396template<
typename ValueType>
400 for (
index_type row = 0; row < rowIndications.size(); ++row) {
401 bool changed =
false;
402 auto startRow = std::next(columnsAndValues.begin(), rowIndications[row]);
403 auto endRow = row < rowIndications.size() - 1 ? std::next(columnsAndValues.begin(), rowIndications[row + 1]) : columnsAndValues.end();
404 for (
auto entry = startRow; entry != endRow; ++entry) {
405 if (entry->getColumn() >= offset) {
407 entry->setColumn(replacements[entry->getColumn() - offset]);
410 maxColumn = std::max(maxColumn, entry->getColumn());
414 std::sort(startRow, endRow,
421 "Columns not sorted.");
425 highestColumn = maxColumn;
426 lastColumn = columnsAndValues.empty() ? 0 : columnsAndValues.back().getColumn();
429template<
typename ValueType>
431 STORM_LOG_THROW(row >= lastRow, storm::exceptions::InvalidArgumentException,
432 "Adding a diagonal element in row " << row <<
", but an element in row " << lastRow <<
" has already been added.");
433 if (pendingDiagonalEntry) {
434 if (row == lastRow) {
436 pendingDiagonalEntry.get() += value;
440 index_type column = hasCustomRowGrouping ? currentRowGroupCount - 1 : lastRow;
441 ValueType diagValue = std::move(pendingDiagonalEntry.get());
442 pendingDiagonalEntry = boost::none;
443 addNextValue(lastRow, column, diagValue);
446 pendingDiagonalEntry = value;
447 if (lastRow != row) {
448 assert(rowIndications.size() == lastRow + 1);
449 rowIndications.resize(row + 1, currentEntryCount);
455template<
typename ValueType>
460template<
typename ValueType>
462 return beginIterator;
465template<
typename ValueType>
467 return beginIterator + entryCount;
470template<
typename ValueType>
472 return this->entryCount;
475template<
typename ValueType>
480template<
typename ValueType>
482 return beginIterator;
485template<
typename ValueType>
487 return beginIterator + entryCount;
490template<
typename ValueType>
492 return this->entryCount;
495template<
typename ValueType>
497 : rowCount(0), columnCount(0), entryCount(0), nonzeroEntryCount(0), columnsAndValues(), rowIndications(), rowGroupIndices() {
501template<
typename ValueType>
503 : rowCount(other.rowCount),
504 columnCount(other.columnCount),
505 entryCount(other.entryCount),
506 nonzeroEntryCount(other.nonzeroEntryCount),
507 columnsAndValues(other.columnsAndValues),
508 rowIndications(other.rowIndications),
509 trivialRowGrouping(other.trivialRowGrouping),
510 rowGroupIndices(other.rowGroupIndices) {
514template<
typename ValueType>
518 *
this = other.
getSubmatrix(
false, rowConstraint, columnConstraint, insertDiagonalElements);
521template<
typename ValueType>
523 : rowCount(other.rowCount),
524 columnCount(other.columnCount),
525 entryCount(other.entryCount),
526 nonzeroEntryCount(other.nonzeroEntryCount),
527 columnsAndValues(
std::move(other.columnsAndValues)),
528 rowIndications(
std::move(other.rowIndications)),
529 trivialRowGrouping(other.trivialRowGrouping),
530 rowGroupIndices(
std::move(other.rowGroupIndices)) {
533 other.columnCount = 0;
534 other.entryCount = 0;
537template<
typename ValueType>
540 boost::optional<std::vector<index_type>>
const& rowGroupIndices)
541 : rowCount(rowIndications.size() - 1),
542 columnCount(columnCount),
543 entryCount(columnsAndValues.size()),
544 nonzeroEntryCount(0),
545 columnsAndValues(columnsAndValues),
546 rowIndications(rowIndications),
547 trivialRowGrouping(!rowGroupIndices),
548 rowGroupIndices(rowGroupIndices) {
552template<
typename ValueType>
555 boost::optional<std::vector<index_type>>&& rowGroupIndices)
556 : columnCount(columnCount),
557 nonzeroEntryCount(0),
558 columnsAndValues(
std::move(columnsAndValues)),
559 rowIndications(
std::move(rowIndications)),
560 rowGroupIndices(
std::move(rowGroupIndices)) {
563 this->rowCount = this->rowIndications.size() - 1;
564 this->entryCount = this->columnsAndValues.size();
565 this->trivialRowGrouping = !this->rowGroupIndices;
569template<
typename ValueType>
572 if (
this != &other) {
573 rowCount = other.rowCount;
574 columnCount = other.columnCount;
575 entryCount = other.entryCount;
576 nonzeroEntryCount = other.nonzeroEntryCount;
578 columnsAndValues = other.columnsAndValues;
579 rowIndications = other.rowIndications;
580 rowGroupIndices = other.rowGroupIndices;
581 trivialRowGrouping = other.trivialRowGrouping;
586template<
typename ValueType>
589 if (
this != &other) {
590 rowCount = other.rowCount;
591 columnCount = other.columnCount;
592 entryCount = other.entryCount;
593 nonzeroEntryCount = other.nonzeroEntryCount;
595 columnsAndValues = std::move(other.columnsAndValues);
596 rowIndications = std::move(other.rowIndications);
597 rowGroupIndices = std::move(other.rowGroupIndices);
598 trivialRowGrouping = other.trivialRowGrouping;
603template<
typename ValueType>
605 if (
this == &other) {
609 bool equalityResult =
true;
612 if (!equalityResult) {
616 if (!equalityResult) {
624 if (!equalityResult) {
640 if ((it1 == ite1) || (it2 == ite2)) {
641 equalityResult = (it1 == ite1) ^ (it2 == ite2);
644 if (it1->getColumn() != it2->getColumn() || it1->getValue() != it2->getValue()) {
645 equalityResult =
false;
650 if (!equalityResult) {
655 return equalityResult;
658template<
typename ValueType>
663template<
typename ValueType>
668template<
typename ValueType>
673template<
typename ValueType>
682 return getRowEntryCount(group);
686template<
typename ValueType>
688 return (this->rowIndications[row + 1] - this->rowIndications[row]);
691template<
typename ValueType>
693 return nonzeroEntryCount;
696template<
typename ValueType>
698 this->nonzeroEntryCount = 0;
699 for (
auto const& element : *
this) {
701 ++this->nonzeroEntryCount;
706template<
typename ValueType>
708 this->nonzeroEntryCount += difference;
711template<
typename ValueType>
713 this->nonzeroEntryCount = 0;
714 this->columnCount = 0;
715 for (
auto const& element : *
this) {
717 ++this->nonzeroEntryCount;
718 this->columnCount = std::max(element.getColumn() + 1, this->columnCount);
723template<
typename ValueType>
726 return rowGroupIndices.get().size() - 1;
732template<
typename ValueType>
737template<
typename ValueType>
744 for (
auto const&
i : rowGroupIndices.get()) {
745 res = std::max(res,
i - previousGroupStart);
746 previousGroupStart =
i;
751template<
typename ValueType>
763 numRows +=
end - start;
769template<
typename ValueType>
772 if (!this->rowGroupIndices) {
773 STORM_LOG_ASSERT(trivialRowGrouping,
"Only trivial row-groupings can be constructed on-the-fly.");
776 return rowGroupIndices.get();
779template<
typename ValueType>
781 return rowIndications;
784template<
typename ValueType>
787 "Invalid row group index:" << group <<
". Only " << this->
getRowGroupCount() <<
" row groups available.");
788 if (this->rowGroupIndices) {
789 return boost::irange(rowGroupIndices.get()[group], rowGroupIndices.get()[group + 1]);
791 return boost::irange(group, group + 1);
795template<
typename ValueType>
797 std::vector<index_type> result;
798 if (this->rowGroupIndices) {
799 result = std::move(rowGroupIndices.get());
800 rowGroupIndices = std::move(newRowGrouping);
805template<
typename ValueType>
807 trivialRowGrouping =
false;
808 rowGroupIndices = newRowGroupIndices;
811template<
typename ValueType>
813 return trivialRowGrouping;
816template<
typename ValueType>
818 if (trivialRowGrouping) {
821 "Row grouping is supposed to be trivial but actually it is not.");
823 trivialRowGrouping =
true;
824 rowGroupIndices = boost::none;
828template<
typename ValueType>
831 for (
auto group : groupConstraint) {
837template<
typename ValueType>
841 for (
auto group : groupConstraint) {
843 bool choiceSatisfiesColumnConstraint =
true;
844 for (
auto const& entry : this->
getRow(row)) {
845 if (!columnConstraint.
get(entry.getColumn())) {
846 choiceSatisfiesColumnConstraint =
false;
850 if (choiceSatisfiesColumnConstraint) {
851 result.
set(row,
true);
858template<
typename ValueType>
863 if (setIfForAllRowsInGroup) {
865 if (rowConstraint.
getNextUnsetIndex(groupIndices[group]) >= groupIndices[group + 1]) {
867 result.
set(group,
true);
872 if (rowConstraint.
getNextSetIndex(groupIndices[group]) < groupIndices[group + 1]) {
874 result.
set(group,
true);
881template<
typename ValueType>
885 for (
auto row :
rows) {
889 this->dropZeroEntries();
893template<
typename ValueType>
898 for (
auto rowGroup : rowGroupConstraint) {
904 for (
auto rowGroup : rowGroupConstraint) {
905 makeRowDirac(rowGroup, rowGroup,
false);
908 if (dropZeroEntries) {
909 this->dropZeroEntries();
913template<
typename ValueType>
920 if (columnValuePtr >= columnValuePtrEnd) {
921 throw storm::exceptions::InvalidStateException()
922 <<
"Illegal call to SparseMatrix::makeRowDirac: cannot make row " << row <<
" absorbing, because there is no entry in this row.";
929 while (columnValuePtr->getColumn() < column && columnValuePtr != lastColumnValuePtr) {
931 --this->nonzeroEntryCount;
938 ++this->nonzeroEntryCount;
941 columnValuePtr->setColumn(column);
942 for (++columnValuePtr; columnValuePtr != columnValuePtrEnd; ++columnValuePtr) {
944 --this->nonzeroEntryCount;
948 if (dropZeroEntries) {
949 this->dropZeroEntries();
953template<
typename ValueType>
959 for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
964 if (it1 == end1 && it2 == end2) {
970template<
typename ValueType>
973 for (
size_t rowgroup = 0; rowgroup < this->
getRowGroupCount(); ++rowgroup) {
975 for (
size_t row2 = row1; row2 < this->
getRowGroupIndices().at(rowgroup + 1); ++row2) {
985template<
typename ValueType>
992 index_type largerRow =
getRow(row1).getNumberOfEntries() >
getRow(row2).getNumberOfEntries() ? row1 : row2;
993 index_type smallerRow = largerRow == row1 ? row2 : row1;
994 index_type rowSizeDifference =
getRow(largerRow).getNumberOfEntries() -
getRow(smallerRow).getNumberOfEntries();
997 auto copyRow =
getRow(largerRow);
998 std::vector<MatrixEntry<index_type, value_type>> largerRowContents(copyRow.begin(), copyRow.end());
1000 if (largerRow < smallerRow) {
1001 auto writeIt =
getRows(largerRow, smallerRow + 1).begin();
1004 for (
auto& smallerRowEntry :
getRow(smallerRow)) {
1005 *writeIt = std::move(smallerRowEntry);
1011 for (
auto& intermediateRowEntry :
getRows(largerRow + 1, smallerRow)) {
1012 *writeIt = std::move(intermediateRowEntry);
1017 writeIt =
getRow(smallerRow).begin();
1021 for (
auto& largerRowEntry : largerRowContents) {
1022 *writeIt = std::move(largerRowEntry);
1026 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).end(),
"Unexpected position of write iterator.");
1030 for (
index_type row = largerRow + 1; row <= smallerRow; ++row) {
1031 rowIndications[row] -= rowSizeDifference;
1035 auto writeIt = getRows(smallerRow, largerRow + 1).end() - 1;
1039 for (
auto smallerRowEntryIt = copyRow.end() - 1; smallerRowEntryIt != copyRow.begin() - 1; --smallerRowEntryIt) {
1040 *writeIt = std::move(*smallerRowEntryIt);
1046 for (
auto intermediateRowEntryIt =
getRows(smallerRow + 1, largerRow).
end() - 1;
1047 intermediateRowEntryIt !=
getRows(smallerRow + 1, largerRow).begin() - 1; --intermediateRowEntryIt) {
1048 *writeIt = std::move(*intermediateRowEntryIt);
1057 for (
auto largerRowEntryIt = largerRowContents.rbegin(); largerRowEntryIt != largerRowContents.rend(); ++largerRowEntryIt) {
1058 *writeIt = std::move(*largerRowEntryIt);
1062 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).begin() - 1,
"Unexpected position of write iterator.");
1067 for (
index_type row = smallerRow + 1; row <= largerRow; ++row) {
1068 rowIndications[row] += rowSizeDifference;
1074template<
typename ValueType>
1076 std::vector<ValueType> result(this->
getRowCount());
1079 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++row) {
1086template<
typename ValueType>
1090 if (constraint.
get(it->getColumn())) {
1091 result += it->getValue();
1097template<
typename ValueType>
1102 for (
auto row : rowConstraint) {
1108template<
typename ValueType>
1111 std::vector<ValueType> result;
1114 for (
auto rowGroup : rowGroupConstraint) {
1120 for (
auto rowGroup : rowGroupConstraint) {
1127template<
typename ValueType>
1135 std::vector<index_type> fakeRowGroupIndices(rowCount + 1);
1137 for (std::vector<index_type>::iterator it = fakeRowGroupIndices.begin(); it != fakeRowGroupIndices.end(); ++it, ++
i) {
1140 auto res = getSubmatrix(rowConstraint, columnConstraint, fakeRowGroupIndices, insertDiagonalElements, makeZeroColumns);
1144 if (!this->hasTrivialRowGrouping()) {
1145 std::vector<index_type> newRowGroupIndices;
1146 newRowGroupIndices.push_back(0);
1147 auto selectedRowIt = rowConstraint.
begin();
1150 for (index_type group = 0; group < this->getRowGroupCount(); ++group) {
1151 index_type newRowCount = 0;
1152 while (*selectedRowIt < this->getRowGroupIndices()[group + 1]) {
1156 if (newRowCount > 0) {
1157 newRowGroupIndices.push_back(newRowGroupIndices.back() + newRowCount);
1161 res.trivialRowGrouping =
false;
1162 res.rowGroupIndices = newRowGroupIndices;
1169template<
typename ValueType>
1171 storm::storage::BitVector
const& columnConstraint, std::vector<index_type>
const& rowGroupIndices,
1172 bool insertDiagonalEntries, storm::storage::BitVector
const& makeZeroColumns)
const {
1173 STORM_LOG_THROW(!rowGroupConstraint.
empty() && !columnConstraint.
empty(), storm::exceptions::InvalidArgumentException,
"Cannot build empty submatrix.");
1179 std::unique_ptr<std::vector<index_type>> tmp;
1180 if (rowGroupConstraint != columnConstraint) {
1183 std::vector<index_type>
const& rowBitsSetBeforeIndex = tmp ? *tmp : columnBitsSetBeforeIndex;
1189 for (
auto index : rowGroupConstraint) {
1190 subRows += rowGroupIndices[index + 1] - rowGroupIndices[index];
1191 for (
index_type i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1192 bool foundDiagonalElement =
false;
1195 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1198 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1199 foundDiagonalElement =
true;
1205 if (insertDiagonalEntries && !foundDiagonalElement && rowGroupCount < submatrixColumnCount) {
1217 index_type rowCount = 0;
1219 for (
auto index : rowGroupConstraint) {
1220 if (!this->hasTrivialRowGrouping()) {
1221 matrixBuilder.newRowGroup(rowCount);
1223 for (index_type
i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1224 bool insertedDiagonalElement =
false;
1226 for (const_iterator it = this->begin(
i), ite = this->end(
i); it != ite; ++it) {
1227 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1228 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1229 insertedDiagonalElement =
true;
1230 }
else if (insertDiagonalEntries && !insertedDiagonalElement && columnBitsSetBeforeIndex[it->getColumn()] > rowBitsSetBeforeIndex[index]) {
1232 insertedDiagonalElement =
true;
1235 matrixBuilder.addNextValue(rowCount, columnBitsSetBeforeIndex[it->getColumn()], it->getValue());
1238 if (insertDiagonalEntries && !insertedDiagonalElement && rowGroupCount < submatrixColumnCount) {
1246 return matrixBuilder.build();
1249template<
typename ValueType>
1255 for (
auto row : rowsToKeep) {
1256 entryCount += this->
getRow(row).getNumberOfEntries();
1260 index_type firstTrailingEmptyRowGroup = this->getRowGroupCount();
1265 --firstTrailingEmptyRowGroup;
1267 STORM_LOG_THROW(allowEmptyRowGroups || firstTrailingEmptyRowGroup == this->getRowGroupCount(), storm::exceptions::InvalidArgumentException,
1268 "Empty rows are not allowed, but row group " << firstTrailingEmptyRowGroup <<
" is empty.");
1273 for (
index_type rowGroup = 0; rowGroup < firstTrailingEmptyRowGroup; ++rowGroup) {
1276 bool rowGroupEmpty =
true;
1279 rowGroupEmpty =
false;
1280 for (
auto const& entry : this->
getRow(row)) {
1281 builder.addNextValue(newRow, entry.getColumn(), entry.getValue());
1285 STORM_LOG_THROW(allowEmptyRowGroups || !rowGroupEmpty, storm::exceptions::InvalidArgumentException,
1286 "Empty rows are not allowed, but row group " << rowGroup <<
" is empty.");
1294template<
typename ValueType>
1298 for (
auto row : rowFilter) {
1299 entryCount +=
getRow(row).getNumberOfEntries();
1304 for (
auto row : rowFilter) {
1305 for (
auto const& entry :
getRow(row)) {
1306 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1318template<
typename ValueType>
1324 for (
auto const& entry :
getRow(row)) {
1326 builder.addNextValue(row, entry.getColumn(), entry.getValue());
1335 *
this = std::move(result);
1339template<
typename ValueType>
1341 bool insertDiagonalEntries)
const {
1345 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1348 "Cannot point to row offset " << rowGroupToRowIndexMapping[rowGroupIndex] <<
" for rowGroup " << rowGroupIndex <<
" which starts at "
1354 bool foundDiagonalElement =
false;
1356 if (it->getColumn() == rowGroupIndex) {
1357 foundDiagonalElement =
true;
1361 if (insertDiagonalEntries && !foundDiagonalElement) {
1370 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1376 bool insertedDiagonalElement =
false;
1378 if (it->getColumn() == rowGroupIndex) {
1379 insertedDiagonalElement =
true;
1380 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > rowGroupIndex) {
1382 insertedDiagonalElement =
true;
1384 matrixBuilder.
addNextValue(rowGroupIndex, it->getColumn(), it->getValue());
1386 if (insertDiagonalEntries && !insertedDiagonalElement) {
1392 return matrixBuilder.
build();
1395template<
typename ValueType>
1397 bool insertDiagonalEntries)
const {
1401 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1402 bool foundDiagonalElement =
false;
1403 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1404 if (it->getColumn() == row) {
1405 foundDiagonalElement =
true;
1409 if (insertDiagonalEntries && !foundDiagonalElement) {
1418 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1419 bool insertedDiagonalElement =
false;
1420 for (
const_iterator it = this->
begin(rowIndexSequence[row]), ite = this->
end(rowIndexSequence[row]); it != ite; ++it) {
1421 if (it->getColumn() == row) {
1422 insertedDiagonalElement =
true;
1423 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > row) {
1425 insertedDiagonalElement =
true;
1427 matrixBuilder.
addNextValue(row, it->getColumn(), it->getValue());
1429 if (insertDiagonalEntries && !insertedDiagonalElement) {
1435 return matrixBuilder.
build();
1438template<
typename ValueType>
1446 for (
index_type writeTo = 0; writeTo < inversePermutation.size(); ++writeTo) {
1447 index_type const& readFrom = inversePermutation[writeTo];
1448 auto row = this->
getRow(readFrom);
1449 for (
auto const& entry : row) {
1450 matrixBuilder.
addNextValue(writeTo, entry.getColumn(), entry.getValue());
1454 auto result = matrixBuilder.
build();
1455 if (this->rowGroupIndices) {
1456 result.setRowGroupIndices(this->rowGroupIndices.get());
1461template<
typename ValueType>
1463 std::vector<index_type>
const& columnPermutation)
const {
1468 auto oldGroupIt = inverseRowGroupPermutation.cbegin();
1470 while (newRowIndex < rowCount) {
1475 for (
auto const& oldEntry :
getRow(oldRowIndex)) {
1476 matrixBuilder.
addNextValue(newRowIndex, columnPermutation[oldEntry.getColumn()], oldEntry.getValue());
1482 return matrixBuilder.
build();
1485template<
typename ValueType>
1497 std::vector<index_type> rowIndications(rowCount + 1);
1498 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1501 for (
index_type group = 0; group < columnCount; ++group) {
1502 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1504 ++rowIndications[transition.getColumn() + 1];
1511 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1517 std::vector<index_type> nextIndices = rowIndications;
1520 for (
index_type group = 0; group < columnCount; ++group) {
1521 for (
auto const& transition : joinGroups ? this->
getRowGroup(group) : this->
getRow(group)) {
1523 columnsAndValues[nextIndices[transition.getColumn()]] = std::make_pair(group, transition.getValue());
1524 nextIndices[transition.getColumn()]++;
1531 return transposedMatrix;
1534template<
typename ValueType>
1537 index_type columnCount = this->getRowGroupCount();
1541 std::vector<index_type> rowIndications(columnCount + 1);
1542 auto rowGroupChoiceIt = rowGroupChoices.begin();
1543 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1544 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1547 ++rowIndications[entry.getColumn() + 1];
1554 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1557 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1562 std::vector<index_type> nextIndices = rowIndications;
1565 rowGroupChoiceIt = rowGroupChoices.begin();
1566 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1567 for (
auto const& entry : this->
getRow(rowGroup, *rowGroupChoiceIt)) {
1569 columnsAndValues[nextIndices[entry.getColumn()]] = std::make_pair(rowGroup, entry.getValue());
1570 ++nextIndices[entry.getColumn()];
1578template<
typename ValueType>
1584template<
typename ValueType>
1590 bool foundDiagonalElement =
false;
1591 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1593 if (entry.getColumn() == group) {
1594 if (entry.getValue() == one) {
1595 --this->nonzeroEntryCount;
1596 entry.setValue(zero);
1597 }
else if (entry.getValue() == zero) {
1598 ++this->nonzeroEntryCount;
1599 entry.setValue(one);
1601 entry.setValue(one - entry.getValue());
1603 foundDiagonalElement =
true;
1608 if (!foundDiagonalElement) {
1609 throw storm::exceptions::InvalidArgumentException() <<
"Illegal call to SparseMatrix::invertDiagonal: matrix is missing diagonal entries.";
1614template<
typename ValueType>
1617 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1619 if (entry.getColumn() != group) {
1620 entry.setValue(-entry.getValue());
1626template<
typename ValueType>
1629 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1631 if (entry.getColumn() == group) {
1632 --this->nonzeroEntryCount;
1638 this->dropZeroEntries();
1642template<
typename ValueType>
1645 "Canno compute Jacobi decomposition of non-square matrix.");
1649 std::vector<ValueType> invertedDiagonal(rowCount);
1652 for (
index_type rowNumber = 0; rowNumber < rowCount; ++rowNumber) {
1654 if (it->getColumn() == rowNumber) {
1657 luBuilder.
addNextValue(rowNumber, it->getColumn(), it->getValue());
1662 return std::make_pair(luBuilder.
build(), std::move(invertedDiagonal));
1667 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1673 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1676template<
typename ValueType>
1677template<
typename OtherValueType,
typename ResultValueType>
1686 for (; it1 != ite1 && it2 != ite2; ++it1) {
1687 if (it1->getColumn() < it2->getColumn()) {
1693 STORM_LOG_ASSERT(it1->getColumn() == it2->getColumn(),
"The given matrix is not a submatrix of this one.");
1694 result += it2->getValue() * OtherValueType(it1->getValue());
1701template<
typename ValueType>
1702template<
typename OtherValueType,
typename ResultValueType>
1704 std::vector<ResultValueType> result;
1705 result.reserve(rowCount);
1712template<
typename ValueType>
1714 std::vector<value_type>
const* summand)
const {
1716 std::vector<ValueType>* target;
1717 std::vector<ValueType> temporary;
1718 if (&vector == &result) {
1719 STORM_LOG_WARN(
"Vectors are aliased. Using temporary, which is potentially slow.");
1720 temporary = std::vector<ValueType>(vector.size());
1721 target = &temporary;
1728 if (target == &temporary) {
1729 std::swap(result, *target);
1733template<
typename ValueType>
1735 std::vector<value_type>
const* summand)
const {
1738 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1739 typename std::vector<ValueType>::iterator resultIterator = result.begin();
1740 typename std::vector<ValueType>::iterator resultIteratorEnd = result.end();
1741 typename std::vector<ValueType>::const_iterator summandIterator;
1743 summandIterator = summand->begin();
1746 for (; resultIterator != resultIteratorEnd; ++rowIterator, ++resultIterator, ++summandIterator) {
1749 newValue = *summandIterator;
1754 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1755 newValue += it->getValue() * vector[it->getColumn()];
1758 *resultIterator = newValue;
1762template<
typename ValueType>
1764 std::vector<value_type>
const* summand)
const {
1767 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1768 typename std::vector<ValueType>::iterator resultIterator = result.end() - 1;
1769 typename std::vector<ValueType>::iterator resultIteratorEnd = result.begin() - 1;
1770 typename std::vector<ValueType>::const_iterator summandIterator;
1772 summandIterator = summand->end() - 1;
1775 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --summandIterator) {
1778 newValue = *summandIterator;
1783 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1784 newValue += (it->getValue() * vector[it->getColumn()]);
1787 *resultIterator = newValue;
1791template<
typename ValueType>
1795 for (
auto const& entry : this->
getRow(row)) {
1796 result += entry.getValue() * vector[entry.getColumn()];
1801template<
typename ValueType>
1805 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1806 typename std::vector<ValueType>::const_iterator bIt = b.end() - 1;
1807 typename std::vector<ValueType>::iterator resultIterator = x.end() - 1;
1808 typename std::vector<ValueType>::iterator resultIteratorEnd = x.begin() - 1;
1811 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --bIt) {
1816 for (ite = this->
begin() + *rowIterator - 1; it != ite; --it) {
1817 if (it->getColumn() != currentRow) {
1818 tmpValue += it->getValue() * x[it->getColumn()];
1820 diagonalElement += it->getValue();
1830 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1833template<
typename ValueType>
1835 std::vector<ValueType>
const& ax, std::vector<ValueType>& result)
const {
1838 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1842 for (
auto& entry : result) {
1846 for (
index_type row = 0; row < rowCount; ++row, ++rowIterator) {
1847 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
1848 result[it->getColumn()] += it->getValue() * (b[row] / ax[row]);
1852 auto xIterator = x.begin();
1853 auto sumsIterator = columnSums.begin();
1854 for (
auto& entry : result) {
1855 entry *= *xIterator / *sumsIterator;
1863 std::vector<Interval>
const& ax, std::vector<Interval>& result)
const {
1864 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1867template<
typename ValueType>
1869 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1870 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1871 if (dir == OptimizationDirection::Minimize) {
1878template<
typename ValueType>
1879template<
typename Compare>
1881 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1882 std::vector<uint64_t>* choices)
const {
1884 auto elementIt = this->
begin();
1885 auto rowGroupIt = rowGroupIndices.begin();
1886 auto rowIt = rowIndications.begin();
1887 typename std::vector<ValueType>::const_iterator summandIt;
1889 summandIt = summand->begin();
1891 typename std::vector<uint64_t>::iterator choiceIt;
1893 choiceIt = choices->begin();
1897 ValueType oldSelectedChoiceValue;
1898 uint64_t selectedChoice;
1900 uint64_t currentRow = 0;
1901 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt) {
1905 if (*rowGroupIt < *(rowGroupIt + 1)) {
1907 currentValue = *summandIt;
1911 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1912 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
1917 if (*choiceIt == 0) {
1918 oldSelectedChoiceValue = currentValue;
1925 for (; currentRow < *(rowGroupIt + 1); ++rowIt, ++currentRow) {
1927 for (
auto elementIte = this->
begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1928 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
1931 if (choices && currentRow == *choiceIt + *rowGroupIt) {
1932 oldSelectedChoiceValue = newValue;
1935 if (compare(newValue, currentValue)) {
1936 currentValue = newValue;
1938 selectedChoice = currentRow - *rowGroupIt;
1947 *resultIt = currentValue;
1948 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
1949 *choiceIt = selectedChoice;
1957 std::vector<storm::RationalFunction>
const& vector,
1958 std::vector<storm::RationalFunction>
const* b,
1959 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
1960 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1963template<
typename ValueType>
1965 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1966 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1967 if (dir == storm::OptimizationDirection::Minimize) {
1974template<
typename ValueType>
1975template<
typename Compare>
1977 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1978 std::vector<uint64_t>* choices)
const {
1980 auto elementIt = this->
end() - 1;
1981 auto rowGroupIt = rowGroupIndices.end() - 2;
1982 auto rowIt = rowIndications.end() - 2;
1983 typename std::vector<ValueType>::const_iterator summandIt;
1985 summandIt = summand->end() - 1;
1987 typename std::vector<uint64_t>::iterator choiceIt;
1989 choiceIt = choices->end() - 1;
1993 ValueType oldSelectedChoiceValue;
1994 uint64_t selectedChoice;
1997 for (
auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt) {
2001 if (*rowGroupIt < *(rowGroupIt + 1)) {
2003 currentValue = *summandIt;
2007 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
2008 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
2011 selectedChoice = currentRow - *rowGroupIt;
2012 if (*choiceIt == selectedChoice) {
2013 oldSelectedChoiceValue = currentValue;
2019 for (uint64_t
i = *rowGroupIt + 1,
end = *(rowGroupIt + 1);
i <
end; --rowIt, --currentRow, ++
i, --summandIt) {
2021 for (
auto elementIte = this->
begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
2022 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
2025 if (choices && currentRow == *choiceIt + *rowGroupIt) {
2026 oldSelectedChoiceValue = newValue;
2029 if (compare(newValue, currentValue)) {
2030 currentValue = newValue;
2032 selectedChoice = currentRow - *rowGroupIt;
2038 *resultIt = currentValue;
2039 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
2040 *choiceIt = selectedChoice;
2048 std::vector<storm::RationalFunction>
const& vector,
2049 std::vector<storm::RationalFunction>
const* b,
2050 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
2051 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
2054template<
typename ValueType>
2056 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
2057 std::vector<uint64_t>* choices)
const {
2059 std::vector<ValueType>* target;
2060 std::vector<ValueType> temporary;
2061 if (&vector == &result) {
2062 STORM_LOG_WARN(
"Vectors are aliased but are not allowed to be. Using temporary, which is potentially slow.");
2063 temporary = std::vector<ValueType>(vector.size());
2064 target = &temporary;
2071 if (target == &temporary) {
2072 std::swap(temporary, result);
2076template<
typename ValueType>
2080 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
2081 std::vector<index_type>::const_iterator rowIteratorEnd = rowIndications.end();
2084 for (; rowIterator != rowIteratorEnd - 1; ++rowIterator) {
2085 for (ite = this->
begin() + *(rowIterator + 1); it != ite; ++it) {
2086 result[it->getColumn()] += it->getValue() * vector[currentRow];
2092template<
typename ValueType>
2094 STORM_LOG_ASSERT(factors.size() == this->getRowCount(),
"Can not scale rows: Number of rows and number of scaling factors do not match.");
2096 for (
auto const& factor : factors) {
2097 for (
auto& entry :
getRow(row)) {
2098 entry.setValue(entry.getValue() * factor);
2104template<
typename ValueType>
2106 STORM_LOG_ASSERT(divisors.size() == this->getRowCount(),
"Can not divide rows: Number of rows and number of divisors do not match.");
2108 for (
auto const& divisor : divisors) {
2110 for (
auto& entry :
getRow(row)) {
2111 entry.setValue(entry.getValue() / divisor);
2119 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
2122template<
typename ValueType>
2124 return const_rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2127template<
typename ValueType>
2129 return rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2132template<
typename ValueType>
2137template<
typename ValueType>
2142template<
typename ValueType>
2153template<
typename ValueType>
2161 return getRow(rowGroup + offset);
2165template<
typename ValueType>
2171 return getRows(rowGroup, rowGroup + 1);
2175template<
typename ValueType>
2181 return getRows(rowGroup, rowGroup + 1);
2185template<
typename ValueType>
2188 return this->columnsAndValues.begin() + this->rowIndications[row];
2191template<
typename ValueType>
2194 return this->columnsAndValues.begin() + this->rowIndications[row];
2197template<
typename ValueType>
2199 return this->columnsAndValues.begin();
2202template<
typename ValueType>
2204 return this->columnsAndValues.begin();
2207template<
typename ValueType>
2210 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2213template<
typename ValueType>
2216 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2219template<
typename ValueType>
2221 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2224template<
typename ValueType>
2226 return this->columnsAndValues.begin() + this->rowIndications[rowCount];
2229template<
typename ValueType>
2233 sum += it->getValue();
2238template<
typename ValueType>
2241 for (
auto const& entry : *
this) {
2246 return nonConstEntries;
2249template<
typename ValueType>
2252 for (
index_type rowGroup = 0; rowGroup < this->getRowGroupCount(); ++rowGroup) {
2253 for (
auto const& entry : this->
getRowGroup(rowGroup)) {
2255 ++nonConstRowGroups;
2260 return nonConstRowGroups;
2263template<
typename ValueType>
2267 auto toBaseType = [](ValueType
const& value) {
2268 if constexpr (std::is_same_v<ValueType, BaseType>) {
2279 auto isContained = [&toBaseType](ValueType
const& value, BaseType
const& lower, BaseType
const& upper) {
2284 return value.lower() <= upper && value.upper() >= lower;
2285 }
else if constexpr (std::is_same_v<ValueType, storm::RationalFunction>) {
2288 auto const constValue = toBaseType(value);
2289 return constValue <= upper && constValue >= lower;
2295 return value <= upper && value >= lower;
2299 auto toString = [](ValueType
const& value) {
2300 std::stringstream s;
2305 for (
index_type row = 0; row < this->rowCount; ++row) {
2307 for (
auto const& entry :
getRow(row)) {
2308 if (!isContained(entry.getValue(), zeroMinusTolerance, onePlusTolerance)) {
2310 *reason =
"Entry in row " + std::to_string(row) +
" is not a probability: " +
toString(entry.getValue());
2314 rowSum += entry.getValue();
2316 if (!isContained(rowSum, oneMinusTolerance, onePlusTolerance)) {
2327template<
typename ValueType>
2329 for (
auto const& entry : *
this) {
2337template<
typename ValueType>
2338template<
typename OtherValueType>
2343 (!this->hasTrivialRowGrouping() && this->getRowGroupIndices() != matrix.
getRowGroupIndices())) {
2349 auto it2 = matrix.
begin(row);
2350 auto ite2 = matrix.
end(row);
2353 while (it2 != ite2 && it2->getColumn() < it1->getColumn()) {
2356 if (it2 == ite2 || it1->getColumn() != it2->getColumn()) {
2364template<
typename ValueType>
2372 for (uint64_t row = 0; row < this->
getRowCount(); ++row) {
2373 bool rowHasEntry =
false;
2374 for (
auto const& entry : this->
getRow(row)) {
2375 if (entry.getColumn() == row) {
2393template<
typename ValueType>
2395 std::string result =
2404template<
typename ValueType>
2415 out <<
"\t---- group " << group <<
"/" << (matrix.
getRowGroupCount() - 1) <<
" ---- \n";
2423 out <<
i <<
"\t(\t";
2425 while (currentRealIndex < matrix.columnCount) {
2426 if (nextIndex < matrix.rowIndications[
i + 1] && currentRealIndex == matrix.columnsAndValues[nextIndex].getColumn()) {
2427 out << matrix.columnsAndValues[nextIndex].getValue() <<
"\t";
2434 out <<
"\t)\t" <<
i <<
'\n';
2448template<
typename ValueType>
2459 while (currentRealIndex < this->columnCount) {
2460 if (nextIndex < this->rowIndications[
i + 1] && currentRealIndex == this->columnsAndValues[nextIndex].getColumn()) {
2461 out << this->columnsAndValues[nextIndex].getValue() <<
" ";
2473template<
typename ValueType>
2475 std::size_t result = 0;
2480 boost::hash_combine(result, boost::hash_range(columnsAndValues.begin(), columnsAndValues.end()));
2481 boost::hash_combine(result, boost::hash_range(rowIndications.begin(), rowIndications.end()));
2483 boost::hash_combine(result, boost::hash_range(rowGroupIndices.get().begin(), rowGroupIndices.get().end()));
2523#if defined(STORM_HAVE_CLN)
2536#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
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.
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
Returns an object representing the given row.
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
Recompute the nonzero entry count.
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
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.