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>
61 return MatrixEntry(this->getColumn(), this->getValue() * factor);
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>
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) {
170 addNextValue(row, column, diagValue + value);
174 addNextValue(lastRow, diagColumn, diagValue);
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;
261 addNextValue(lastRow, diagColumn, diagValue);
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;
286 addNextValue(lastRow, diagColumn, diagValue);
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) {
549 this->updateNonzeroEntryCount();
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;
566 this->updateNonzeroEntryCount();
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;
611 equalityResult &= this->getRowCount() == other.
getRowCount();
612 if (!equalityResult) {
615 equalityResult &= this->getColumnCount() == other.
getColumnCount();
616 if (!equalityResult) {
624 if (!equalityResult) {
630 for (index_type row = 0; row < this->getRowCount(); ++row) {
631 for (const_iterator it1 = this->begin(row), ite1 = this->end(row), it2 = other.
begin(row), ite2 = other.
end(row); it1 != ite1 && it2 != ite2;
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>
676 if (!this->hasTrivialRowGrouping()) {
677 for (
auto row : this->getRowGroupIndices(group)) {
678 result += (this->rowIndications[row + 1] - this->rowIndications[row]);
681 result += (this->rowIndications[group + 1] - this->rowIndications[group]);
686template<
typename ValueType>
688 return nonzeroEntryCount;
691template<
typename ValueType>
693 this->nonzeroEntryCount = 0;
694 for (
auto const& element : *
this) {
695 if (element.getValue() != storm::utility::zero<ValueType>()) {
696 ++this->nonzeroEntryCount;
701template<
typename ValueType>
703 this->nonzeroEntryCount += difference;
706template<
typename ValueType>
708 this->nonzeroEntryCount = 0;
709 this->columnCount = 0;
710 for (
auto const& element : *this) {
711 if (element.getValue() != storm::utility::zero<ValueType>()) {
712 ++this->nonzeroEntryCount;
713 this->columnCount = std::max(element.getColumn() + 1, this->columnCount);
718template<
typename ValueType>
720 if (!this->hasTrivialRowGrouping()) {
721 return rowGroupIndices.get().size() - 1;
727template<
typename ValueType>
729 return this->getRowGroupIndices()[group + 1] - this->getRowGroupIndices()[group];
732template<
typename ValueType>
734 if (this->hasTrivialRowGrouping()) {
739 for (
auto const& i : rowGroupIndices.get()) {
740 res = std::max(res,
i - previousGroupStart);
741 previousGroupStart =
i;
746template<
typename ValueType>
748 if (this->hasTrivialRowGrouping()) {
753 while (rowGroupIndex < this->getRowGroupCount()) {
754 index_type start = this->getRowGroupIndices()[rowGroupIndex];
756 index_type end = this->getRowGroupIndices()[rowGroupIndex];
758 numRows += end - start;
764template<
typename ValueType>
767 if (!this->rowGroupIndices) {
768 STORM_LOG_ASSERT(trivialRowGrouping,
"Only trivial row-groupings can be constructed on-the-fly.");
771 return rowGroupIndices.get();
774template<
typename ValueType>
777 "Invalid row group index:" << group <<
". Only " << this->getRowGroupCount() <<
" row groups available.");
778 if (this->rowGroupIndices) {
779 return boost::irange(rowGroupIndices.get()[group], rowGroupIndices.get()[group + 1]);
781 return boost::irange(group, group + 1);
785template<
typename ValueType>
787 std::vector<index_type> result;
788 if (this->rowGroupIndices) {
789 result = std::move(rowGroupIndices.get());
790 rowGroupIndices = std::move(newRowGrouping);
795template<
typename ValueType>
797 trivialRowGrouping =
false;
798 rowGroupIndices = newRowGroupIndices;
801template<
typename ValueType>
803 return trivialRowGrouping;
806template<
typename ValueType>
808 if (trivialRowGrouping) {
811 "Row grouping is supposed to be trivial but actually it is not.");
813 trivialRowGrouping =
true;
814 rowGroupIndices = boost::none;
818template<
typename ValueType>
821 for (
auto group : groupConstraint) {
822 res.
setMultiple(getRowGroupIndices()[group], getRowGroupSize(group));
827template<
typename ValueType>
831 for (
auto group : groupConstraint) {
832 for (
auto row : this->getRowGroupIndices(group)) {
833 bool choiceSatisfiesColumnConstraint =
true;
834 for (
auto const& entry : this->getRow(row)) {
835 if (!columnConstraint.
get(entry.getColumn())) {
836 choiceSatisfiesColumnConstraint =
false;
840 if (choiceSatisfiesColumnConstraint) {
841 result.
set(row,
true);
848template<
typename ValueType>
850 STORM_LOG_ASSERT(!this->hasTrivialRowGrouping(),
"Tried to get a row group filter but this matrix does not have row groups");
852 auto const& groupIndices = this->getRowGroupIndices();
853 if (setIfForAllRowsInGroup) {
854 for (uint64_t group = 0; group < this->getRowGroupCount(); ++group) {
855 if (rowConstraint.
getNextUnsetIndex(groupIndices[group]) >= groupIndices[group + 1]) {
857 result.
set(group,
true);
861 for (uint64_t group = 0; group < this->getRowGroupCount(); ++group) {
862 if (rowConstraint.
getNextSetIndex(groupIndices[group]) < groupIndices[group + 1]) {
864 result.
set(group,
true);
871template<
typename ValueType>
875 for (
auto row : rows) {
876 makeRowDirac(row, row,
false);
878 if (dropZeroEntries) {
879 this->dropZeroEntries();
883template<
typename ValueType>
887 if (!this->hasTrivialRowGrouping()) {
888 for (
auto rowGroup : rowGroupConstraint) {
889 for (
index_type row = this->getRowGroupIndices()[rowGroup]; row < this->getRowGroupIndices()[rowGroup + 1]; ++row) {
890 makeRowDirac(row, rowGroup,
false);
894 for (
auto rowGroup : rowGroupConstraint) {
895 makeRowDirac(rowGroup, rowGroup,
false);
898 if (dropZeroEntries) {
899 this->dropZeroEntries();
903template<
typename ValueType>
905 iterator columnValuePtr = this->begin(row);
906 iterator columnValuePtrEnd = this->end(row);
910 if (columnValuePtr >= columnValuePtrEnd) {
911 throw storm::exceptions::InvalidStateException()
912 <<
"Illegal call to SparseMatrix::makeRowDirac: cannot make row " << row <<
" absorbing, because there is no entry in this row.";
914 iterator lastColumnValuePtr = this->end(row) - 1;
919 while (columnValuePtr->getColumn() < column && columnValuePtr != lastColumnValuePtr) {
921 --this->nonzeroEntryCount;
923 columnValuePtr->setValue(storm::utility::zero<ValueType>());
928 ++this->nonzeroEntryCount;
930 columnValuePtr->setValue(storm::utility::one<ValueType>());
931 columnValuePtr->setColumn(column);
932 for (++columnValuePtr; columnValuePtr != columnValuePtrEnd; ++columnValuePtr) {
934 --this->nonzeroEntryCount;
936 columnValuePtr->setValue(storm::utility::zero<ValueType>());
938 if (dropZeroEntries) {
939 this->dropZeroEntries();
943template<
typename ValueType>
949 for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
954 if (it1 == end1 && it2 == end2) {
960template<
typename ValueType>
963 for (
size_t rowgroup = 0; rowgroup < this->getRowGroupCount(); ++rowgroup) {
964 for (
size_t row1 = this->getRowGroupIndices().at(rowgroup); row1 < this->getRowGroupIndices().at(rowgroup + 1); ++row1) {
965 for (
size_t row2 = row1; row2 < this->getRowGroupIndices().at(rowgroup + 1); ++row2) {
966 if (compareRows(row1, row2)) {
975template<
typename ValueType>
982 index_type largerRow = getRow(row1).getNumberOfEntries() > getRow(row2).getNumberOfEntries() ? row1 : row2;
983 index_type smallerRow = largerRow == row1 ? row2 : row1;
984 index_type rowSizeDifference = getRow(largerRow).getNumberOfEntries() - getRow(smallerRow).getNumberOfEntries();
987 auto copyRow = getRow(largerRow);
988 std::vector<MatrixEntry<index_type, value_type>> largerRowContents(copyRow.begin(), copyRow.end());
990 if (largerRow < smallerRow) {
991 auto writeIt = getRows(largerRow, smallerRow + 1).begin();
994 for (
auto& smallerRowEntry : getRow(smallerRow)) {
995 *writeIt = std::move(smallerRowEntry);
1001 for (
auto& intermediateRowEntry : getRows(largerRow + 1, smallerRow)) {
1002 *writeIt = std::move(intermediateRowEntry);
1007 writeIt = getRow(smallerRow).begin();
1011 for (
auto& largerRowEntry : largerRowContents) {
1012 *writeIt = std::move(largerRowEntry);
1016 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).end(),
"Unexpected position of write iterator.");
1020 for (
index_type row = largerRow + 1; row <= smallerRow; ++row) {
1021 rowIndications[row] -= rowSizeDifference;
1025 auto writeIt = getRows(smallerRow, largerRow + 1).end() - 1;
1028 auto copyRow = getRow(smallerRow);
1029 for (
auto smallerRowEntryIt = copyRow.end() - 1; smallerRowEntryIt != copyRow.begin() - 1; --smallerRowEntryIt) {
1030 *writeIt = std::move(*smallerRowEntryIt);
1036 for (
auto intermediateRowEntryIt = getRows(smallerRow + 1, largerRow).end() - 1;
1037 intermediateRowEntryIt != getRows(smallerRow + 1, largerRow).begin() - 1; --intermediateRowEntryIt) {
1038 *writeIt = std::move(*intermediateRowEntryIt);
1043 writeIt = getRow(smallerRow).end() - 1;
1047 for (
auto largerRowEntryIt = largerRowContents.rbegin(); largerRowEntryIt != largerRowContents.rend(); ++largerRowEntryIt) {
1048 *writeIt = std::move(*largerRowEntryIt);
1052 STORM_LOG_ASSERT(writeIt == getRow(smallerRow).begin() - 1,
"Unexpected position of write iterator.");
1057 for (
index_type row = smallerRow + 1; row <= largerRow; ++row) {
1058 rowIndications[row] += rowSizeDifference;
1064template<
typename ValueType>
1066 std::vector<ValueType> result(this->getRowCount());
1069 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++row) {
1070 *resultIt = getRowSum(row);
1076template<
typename ValueType>
1078 ValueType result = storm::utility::zero<ValueType>();
1079 for (
const_iterator it = this->begin(row), ite = this->end(row); it != ite; ++it) {
1080 if (constraint.
get(it->getColumn())) {
1081 result += it->getValue();
1087template<
typename ValueType>
1092 for (
auto row : rowConstraint) {
1093 result[currentRowCount++] = getConstrainedRowSum(row, columnConstraint);
1098template<
typename ValueType>
1101 std::vector<ValueType> result;
1102 result.reserve(this->getNumRowsInRowGroups(rowGroupConstraint));
1103 if (!this->hasTrivialRowGrouping()) {
1104 for (
auto rowGroup : rowGroupConstraint) {
1105 for (
index_type row = this->getRowGroupIndices()[rowGroup]; row < this->getRowGroupIndices()[rowGroup + 1]; ++row) {
1106 result.push_back(getConstrainedRowSum(row, columnConstraint));
1110 for (
auto rowGroup : rowGroupConstraint) {
1111 result.push_back(getConstrainedRowSum(rowGroup, columnConstraint));
1117template<
typename ValueType>
1122 return getSubmatrix(rowConstraint, columnConstraint, this->getRowGroupIndices(), insertDiagonalElements, makeZeroColumns);
1125 std::vector<index_type> fakeRowGroupIndices(rowCount + 1);
1127 for (std::vector<index_type>::iterator it = fakeRowGroupIndices.begin(); it != fakeRowGroupIndices.end(); ++it, ++
i) {
1130 auto res = getSubmatrix(rowConstraint, columnConstraint, fakeRowGroupIndices, insertDiagonalElements, makeZeroColumns);
1134 if (!this->hasTrivialRowGrouping()) {
1135 std::vector<index_type> newRowGroupIndices;
1136 newRowGroupIndices.push_back(0);
1137 auto selectedRowIt = rowConstraint.
begin();
1140 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1142 while (*selectedRowIt < this->getRowGroupIndices()[group + 1]) {
1146 if (newRowCount > 0) {
1147 newRowGroupIndices.push_back(newRowGroupIndices.back() + newRowCount);
1151 res.trivialRowGrouping =
false;
1152 res.rowGroupIndices = newRowGroupIndices;
1159template<
typename ValueType>
1163 STORM_LOG_THROW(!rowGroupConstraint.
empty() && !columnConstraint.
empty(), storm::exceptions::InvalidArgumentException,
"Cannot build empty submatrix.");
1169 std::unique_ptr<std::vector<index_type>> tmp;
1170 if (rowGroupConstraint != columnConstraint) {
1173 std::vector<index_type>
const& rowBitsSetBeforeIndex = tmp ? *tmp : columnBitsSetBeforeIndex;
1179 for (
auto index : rowGroupConstraint) {
1180 subRows += rowGroupIndices[index + 1] - rowGroupIndices[index];
1181 for (
index_type i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1182 bool foundDiagonalElement =
false;
1184 for (
const_iterator it = this->begin(
i), ite = this->end(
i); it != ite; ++it) {
1185 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1188 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1189 foundDiagonalElement =
true;
1195 if (insertDiagonalEntries && !foundDiagonalElement && rowGroupCount < submatrixColumnCount) {
1203 SparseMatrixBuilder<ValueType> matrixBuilder(subRows, submatrixColumnCount, subEntries,
true, !this->hasTrivialRowGrouping());
1209 for (
auto index : rowGroupConstraint) {
1210 if (!this->hasTrivialRowGrouping()) {
1211 matrixBuilder.newRowGroup(rowCount);
1213 for (index_type i = rowGroupIndices[index];
i < rowGroupIndices[index + 1]; ++
i) {
1214 bool insertedDiagonalElement =
false;
1216 for (const_iterator it = this->begin(i), ite = this->end(i); it !=
ite; ++it) {
1217 if (columnConstraint.
get(it->getColumn()) && (makeZeroColumns.
size() == 0 || !makeZeroColumns.
get(it->getColumn()))) {
1218 if (columnBitsSetBeforeIndex[it->getColumn()] == rowBitsSetBeforeIndex[index]) {
1219 insertedDiagonalElement =
true;
1220 }
else if (insertDiagonalEntries && !insertedDiagonalElement && columnBitsSetBeforeIndex[it->getColumn()] > rowBitsSetBeforeIndex[index]) {
1221 matrixBuilder.addNextValue(rowCount, rowGroupCount, storm::utility::zero<ValueType>());
1222 insertedDiagonalElement =
true;
1225 matrixBuilder.addNextValue(rowCount, columnBitsSetBeforeIndex[it->getColumn()], it->getValue());
1228 if (insertDiagonalEntries && !insertedDiagonalElement && rowGroupCount < submatrixColumnCount) {
1229 matrixBuilder.addNextValue(rowCount, rowGroupCount, storm::utility::zero<ValueType>());
1236 return matrixBuilder.build();
1239template<
typename ValueType>
1245 for (
auto row : rowsToKeep) {
1246 entryCount += this->getRow(row).getNumberOfEntries();
1250 index_type firstTrailingEmptyRowGroup = this->getRowGroupCount();
1251 for (
auto groupIndexIt = this->getRowGroupIndices().rbegin() + 1; groupIndexIt != this->getRowGroupIndices().rend(); ++groupIndexIt) {
1255 --firstTrailingEmptyRowGroup;
1257 STORM_LOG_THROW(allowEmptyRowGroups || firstTrailingEmptyRowGroup == this->getRowGroupCount(), storm::exceptions::InvalidArgumentException,
1258 "Empty rows are not allowed, but row group " << firstTrailingEmptyRowGroup <<
" is empty.");
1263 for (
index_type rowGroup = 0; rowGroup < firstTrailingEmptyRowGroup; ++rowGroup) {
1266 bool rowGroupEmpty =
true;
1267 for (
index_type row = rowsToKeep.
getNextSetIndex(this->getRowGroupIndices()[rowGroup]); row < this->getRowGroupIndices()[rowGroup + 1];
1269 rowGroupEmpty =
false;
1270 for (
auto const& entry : this->getRow(row)) {
1271 builder.
addNextValue(newRow, entry.getColumn(), entry.getValue());
1275 STORM_LOG_THROW(allowEmptyRowGroups || !rowGroupEmpty, storm::exceptions::InvalidArgumentException,
1276 "Empty rows are not allowed, but row group " << rowGroup <<
" is empty.");
1284template<
typename ValueType>
1288 for (
auto row : rowFilter) {
1289 entryCount += getRow(row).getNumberOfEntries();
1294 for (
auto row : rowFilter) {
1295 for (
auto const& entry : getRow(row)) {
1296 builder.
addNextValue(row, entry.getColumn(), entry.getValue());
1302 if (!hasTrivialRowGrouping()) {
1308template<
typename ValueType>
1310 updateNonzeroEntryCount();
1311 if (getNonzeroEntryCount() != getEntryCount()) {
1313 for (
index_type row = 0; row < getRowCount(); ++row) {
1314 for (
auto const& entry : getRow(row)) {
1316 builder.
addNextValue(row, entry.getColumn(), entry.getValue());
1322 if (!hasTrivialRowGrouping()) {
1325 *
this = std::move(result);
1329template<
typename ValueType>
1331 bool insertDiagonalEntries)
const {
1335 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1337 STORM_LOG_ASSERT(rowGroupToRowIndexMapping[rowGroupIndex] < this->getRowGroupSize(rowGroupIndex),
1338 "Cannot point to row offset " << rowGroupToRowIndexMapping[rowGroupIndex] <<
" for rowGroup " << rowGroupIndex <<
" which starts at "
1339 << this->getRowGroupIndices()[rowGroupIndex] <<
" and ends at "
1340 << this->getRowGroupIndices()[rowGroupIndex + 1] <<
".");
1341 index_type rowToCopy = this->getRowGroupIndices()[rowGroupIndex] + rowGroupToRowIndexMapping[rowGroupIndex];
1344 bool foundDiagonalElement =
false;
1345 for (
const_iterator it = this->begin(rowToCopy), ite = this->end(rowToCopy); it != ite; ++it) {
1346 if (it->getColumn() == rowGroupIndex) {
1347 foundDiagonalElement =
true;
1351 if (insertDiagonalEntries && !foundDiagonalElement) {
1360 for (
index_type rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
1362 index_type rowToCopy = this->getRowGroupIndices()[rowGroupIndex] + rowGroupToRowIndexMapping[rowGroupIndex];
1366 bool insertedDiagonalElement =
false;
1367 for (
const_iterator it = this->begin(rowToCopy), ite = this->end(rowToCopy); it != ite; ++it) {
1368 if (it->getColumn() == rowGroupIndex) {
1369 insertedDiagonalElement =
true;
1370 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > rowGroupIndex) {
1371 matrixBuilder.
addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::zero<ValueType>());
1372 insertedDiagonalElement =
true;
1374 matrixBuilder.
addNextValue(rowGroupIndex, it->getColumn(), it->getValue());
1376 if (insertDiagonalEntries && !insertedDiagonalElement) {
1377 matrixBuilder.
addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::zero<ValueType>());
1382 return matrixBuilder.
build();
1385template<
typename ValueType>
1387 bool insertDiagonalEntries)
const {
1391 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1392 bool foundDiagonalElement =
false;
1393 for (
const_iterator it = this->begin(rowIndexSequence[row]), ite = this->end(rowIndexSequence[row]); it != ite; ++it) {
1394 if (it->getColumn() == row) {
1395 foundDiagonalElement =
true;
1399 if (insertDiagonalEntries && !foundDiagonalElement) {
1408 for (
index_type row = 0, rowEnd = rowIndexSequence.size(); row < rowEnd; ++row) {
1409 bool insertedDiagonalElement =
false;
1410 for (
const_iterator it = this->begin(rowIndexSequence[row]), ite = this->end(rowIndexSequence[row]); it != ite; ++it) {
1411 if (it->getColumn() == row) {
1412 insertedDiagonalElement =
true;
1413 }
else if (insertDiagonalEntries && !insertedDiagonalElement && it->getColumn() > row) {
1414 matrixBuilder.
addNextValue(row, row, storm::utility::zero<ValueType>());
1415 insertedDiagonalElement =
true;
1417 matrixBuilder.
addNextValue(row, it->getColumn(), it->getValue());
1419 if (insertDiagonalEntries && !insertedDiagonalElement) {
1420 matrixBuilder.
addNextValue(row, row, storm::utility::zero<ValueType>());
1425 return matrixBuilder.
build();
1428template<
typename ValueType>
1436 for (
index_type writeTo = 0; writeTo < inversePermutation.size(); ++writeTo) {
1437 index_type const& readFrom = inversePermutation[writeTo];
1438 auto row = this->getRow(readFrom);
1439 for (
auto const& entry : row) {
1440 matrixBuilder.
addNextValue(writeTo, entry.getColumn(), entry.getValue());
1444 auto result = matrixBuilder.
build();
1445 if (this->rowGroupIndices) {
1446 result.setRowGroupIndices(this->rowGroupIndices.get());
1451template<
typename ValueType>
1453 std::vector<index_type>
const& columnPermutation)
const {
1458 auto oldGroupIt = inverseRowGroupPermutation.cbegin();
1460 while (newRowIndex < rowCount) {
1461 if (!hasTrivialRowGrouping()) {
1464 for (
auto oldRowIndex : getRowGroupIndices(*oldGroupIt)) {
1465 for (
auto const& oldEntry : getRow(oldRowIndex)) {
1466 matrixBuilder.
addNextValue(newRowIndex, columnPermutation[oldEntry.getColumn()], oldEntry.getValue());
1472 return matrixBuilder.
build();
1475template<
typename ValueType>
1477 index_type rowCount = this->getColumnCount();
1478 index_type columnCount = joinGroups ? this->getRowGroupCount() : this->getRowCount();
1481 entryCount = this->getEntryCount();
1483 this->updateNonzeroEntryCount();
1484 entryCount = this->getNonzeroEntryCount();
1487 std::vector<index_type> rowIndications(rowCount + 1);
1488 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1491 for (
index_type group = 0; group < columnCount; ++group) {
1492 for (
auto const& transition : joinGroups ? this->getRowGroup(group) : this->getRow(group)) {
1493 if (transition.getValue() != storm::utility::zero<ValueType>() || keepZeros) {
1494 ++rowIndications[transition.getColumn() + 1];
1501 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1507 std::vector<index_type> nextIndices = rowIndications;
1510 for (
index_type group = 0; group < columnCount; ++group) {
1511 for (
auto const& transition : joinGroups ? this->getRowGroup(group) : this->getRow(group)) {
1512 if (transition.getValue() != storm::utility::zero<ValueType>() || keepZeros) {
1513 columnsAndValues[nextIndices[transition.getColumn()]] = std::make_pair(group, transition.getValue());
1514 nextIndices[transition.getColumn()]++;
1521 return transposedMatrix;
1524template<
typename ValueType>
1526 index_type rowCount = this->getColumnCount();
1527 index_type columnCount = this->getRowGroupCount();
1531 std::vector<index_type> rowIndications(columnCount + 1);
1532 auto rowGroupChoiceIt = rowGroupChoices.begin();
1533 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1534 for (
auto const& entry : this->getRow(rowGroup, *rowGroupChoiceIt)) {
1537 ++rowIndications[entry.getColumn() + 1];
1544 rowIndications[
i] = rowIndications[
i - 1] + rowIndications[
i];
1547 std::vector<MatrixEntry<index_type, ValueType>> columnsAndValues(entryCount);
1552 std::vector<index_type> nextIndices = rowIndications;
1555 rowGroupChoiceIt = rowGroupChoices.begin();
1556 for (
index_type rowGroup = 0; rowGroup < columnCount; ++rowGroup, ++rowGroupChoiceIt) {
1557 for (
auto const& entry : this->getRow(rowGroup, *rowGroupChoiceIt)) {
1559 columnsAndValues[nextIndices[entry.getColumn()]] = std::make_pair(rowGroup, entry.getValue());
1560 ++nextIndices[entry.getColumn()];
1568template<
typename ValueType>
1571 negateAllNonDiagonalEntries();
1574template<
typename ValueType>
1578 ValueType one = storm::utility::one<ValueType>();
1579 ValueType zero = storm::utility::zero<ValueType>();
1580 bool foundDiagonalElement =
false;
1581 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1582 for (
auto& entry : this->getRowGroup(group)) {
1583 if (entry.getColumn() == group) {
1584 if (entry.getValue() == one) {
1585 --this->nonzeroEntryCount;
1586 entry.setValue(zero);
1587 }
else if (entry.getValue() == zero) {
1588 ++this->nonzeroEntryCount;
1589 entry.setValue(one);
1591 entry.setValue(one - entry.getValue());
1593 foundDiagonalElement =
true;
1598 if (!foundDiagonalElement) {
1599 throw storm::exceptions::InvalidArgumentException() <<
"Illegal call to SparseMatrix::invertDiagonal: matrix is missing diagonal entries.";
1604template<
typename ValueType>
1607 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1608 for (
auto& entry : this->getRowGroup(group)) {
1609 if (entry.getColumn() != group) {
1610 entry.setValue(-entry.getValue());
1616template<
typename ValueType>
1619 for (
index_type group = 0; group < this->getRowGroupCount(); ++group) {
1620 for (
auto& entry : this->getRowGroup(group)) {
1621 if (entry.getColumn() == group) {
1622 --this->nonzeroEntryCount;
1623 entry.setValue(storm::utility::zero<ValueType>());
1627 if (dropZeroEntries) {
1628 this->dropZeroEntries();
1632template<
typename ValueType>
1634 STORM_LOG_THROW(this->getRowCount() == this->getColumnCount(), storm::exceptions::InvalidArgumentException,
1635 "Canno compute Jacobi decomposition of non-square matrix.");
1639 std::vector<ValueType> invertedDiagonal(rowCount);
1642 for (
index_type rowNumber = 0; rowNumber < rowCount; ++rowNumber) {
1643 for (
const_iterator it = this->begin(rowNumber), ite = this->end(rowNumber); it != ite; ++it) {
1644 if (it->getColumn() == rowNumber) {
1645 invertedDiagonal[rowNumber] = storm::utility::one<ValueType>() / it->getValue();
1647 luBuilder.
addNextValue(rowNumber, it->getColumn(), it->getValue());
1652 return std::make_pair(luBuilder.
build(), std::move(invertedDiagonal));
1657 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1663 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
1666template<
typename ValueType>
1667template<
typename OtherValueType,
typename ResultValueType>
1675 ResultValueType result = storm::utility::zero<ResultValueType>();
1676 for (; it1 != ite1 && it2 != ite2; ++it1) {
1677 if (it1->getColumn() < it2->getColumn()) {
1683 STORM_LOG_ASSERT(it1->getColumn() == it2->getColumn(),
"The given matrix is not a submatrix of this one.");
1684 result += it2->getValue() * OtherValueType(it1->getValue());
1691template<
typename ValueType>
1692template<
typename OtherValueType,
typename ResultValueType>
1694 std::vector<ResultValueType> result;
1695 result.reserve(rowCount);
1697 result.push_back(getPointwiseProductRowSum<OtherValueType, ResultValueType>(otherMatrix, row));
1702template<
typename ValueType>
1704 std::vector<value_type>
const* summand)
const {
1706 std::vector<ValueType>* target;
1707 std::vector<ValueType> temporary;
1708 if (&vector == &result) {
1709 STORM_LOG_WARN(
"Vectors are aliased. Using temporary, which is potentially slow.");
1710 temporary = std::vector<ValueType>(vector.size());
1711 target = &temporary;
1716 this->multiplyWithVectorForward(vector, *target, summand);
1718 if (target == &temporary) {
1719 std::swap(result, *target);
1723template<
typename ValueType>
1725 std::vector<value_type>
const* summand)
const {
1728 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1729 typename std::vector<ValueType>::iterator resultIterator = result.begin();
1730 typename std::vector<ValueType>::iterator resultIteratorEnd = result.end();
1731 typename std::vector<ValueType>::const_iterator summandIterator;
1733 summandIterator = summand->begin();
1736 for (; resultIterator != resultIteratorEnd; ++rowIterator, ++resultIterator, ++summandIterator) {
1739 newValue = *summandIterator;
1741 newValue = storm::utility::zero<ValueType>();
1744 for (ite = this->begin() + *(rowIterator + 1); it != ite; ++it) {
1745 newValue += it->getValue() * vector[it->getColumn()];
1748 *resultIterator = newValue;
1752template<
typename ValueType>
1754 std::vector<value_type>
const* summand)
const {
1757 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1758 typename std::vector<ValueType>::iterator resultIterator = result.end() - 1;
1759 typename std::vector<ValueType>::iterator resultIteratorEnd = result.begin() - 1;
1760 typename std::vector<ValueType>::const_iterator summandIterator;
1762 summandIterator = summand->end() - 1;
1765 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --summandIterator) {
1768 newValue = *summandIterator;
1770 newValue = storm::utility::zero<ValueType>();
1773 for (ite = this->begin() + *rowIterator - 1; it != ite; --it) {
1774 newValue += (it->getValue() * vector[it->getColumn()]);
1777 *resultIterator = newValue;
1781template<
typename ValueType>
1783 ValueType result = storm::utility::zero<ValueType>();
1785 for (
auto const& entry : this->getRow(row)) {
1786 result += entry.getValue() * vector[entry.getColumn()];
1791template<
typename ValueType>
1795 std::vector<index_type>::const_iterator rowIterator = rowIndications.end() - 2;
1796 typename std::vector<ValueType>::const_iterator bIt = b.end() - 1;
1797 typename std::vector<ValueType>::iterator resultIterator = x.end() - 1;
1798 typename std::vector<ValueType>::iterator resultIteratorEnd = x.begin() - 1;
1801 for (; resultIterator != resultIteratorEnd; --rowIterator, --resultIterator, --bIt) {
1803 ValueType tmpValue = storm::utility::zero<ValueType>();
1804 ValueType diagonalElement = storm::utility::zero<ValueType>();
1806 for (ite = this->begin() + *rowIterator - 1; it != ite; --it) {
1807 if (it->getColumn() != currentRow) {
1808 tmpValue += it->getValue() * x[it->getColumn()];
1810 diagonalElement += it->getValue();
1814 *resultIterator = ((storm::utility::one<ValueType>() - omega) * *resultIterator) + (omega / diagonalElement) * (*bIt - tmpValue);
1820 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1823template<
typename ValueType>
1825 std::vector<ValueType>
const& ax, std::vector<ValueType>& result)
const {
1828 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
1831 ValueType zero = storm::utility::zero<ValueType>();
1832 for (
auto& entry : result) {
1836 for (
index_type row = 0; row < rowCount; ++row, ++rowIterator) {
1837 for (ite = this->begin() + *(rowIterator + 1); it != ite; ++it) {
1838 result[it->getColumn()] += it->getValue() * (b[row] / ax[row]);
1842 auto xIterator = x.begin();
1843 auto sumsIterator = columnSums.begin();
1844 for (
auto& entry : result) {
1845 entry *= *xIterator / *sumsIterator;
1853 std::vector<Interval>
const& ax, std::vector<Interval>& result)
const {
1854 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1857template<
typename ValueType>
1859 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1860 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1861 if (dir == OptimizationDirection::Minimize) {
1862 multiplyAndReduceForward<storm::utility::ElementLess<ValueType>>(rowGroupIndices, vector, summand, result, choices);
1864 multiplyAndReduceForward<storm::utility::ElementGreater<ValueType>>(rowGroupIndices, vector, summand, result, choices);
1868template<
typename ValueType>
1869template<
typename Compare>
1871 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1872 std::vector<uint64_t>* choices)
const {
1874 auto elementIt = this->begin();
1875 auto rowGroupIt = rowGroupIndices.begin();
1876 auto rowIt = rowIndications.begin();
1877 typename std::vector<ValueType>::const_iterator summandIt;
1879 summandIt = summand->begin();
1881 typename std::vector<uint64_t>::iterator choiceIt;
1883 choiceIt = choices->begin();
1887 ValueType oldSelectedChoiceValue;
1888 uint64_t selectedChoice;
1890 uint64_t currentRow = 0;
1891 for (
auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt) {
1892 ValueType currentValue = storm::utility::zero<ValueType>();
1895 if (*rowGroupIt < *(rowGroupIt + 1)) {
1897 currentValue = *summandIt;
1901 for (
auto elementIte = this->begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1902 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
1907 if (*choiceIt == 0) {
1908 oldSelectedChoiceValue = currentValue;
1915 for (; currentRow < *(rowGroupIt + 1); ++rowIt, ++currentRow) {
1916 ValueType newValue = summand ? *summandIt : storm::utility::zero<ValueType>();
1917 for (
auto elementIte = this->begin() + *(rowIt + 1); elementIt != elementIte; ++elementIt) {
1918 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
1921 if (choices && currentRow == *choiceIt + *rowGroupIt) {
1922 oldSelectedChoiceValue = newValue;
1925 if (compare(newValue, currentValue)) {
1926 currentValue = newValue;
1928 selectedChoice = currentRow - *rowGroupIt;
1937 *resultIt = currentValue;
1938 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
1939 *choiceIt = selectedChoice;
1947 std::vector<storm::RationalFunction>
const& vector,
1948 std::vector<storm::RationalFunction>
const* b,
1949 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
1950 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
1953template<
typename ValueType>
1955 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand,
1956 std::vector<ValueType>& result, std::vector<uint64_t>* choices)
const {
1957 if (dir == storm::OptimizationDirection::Minimize) {
1958 multiplyAndReduceBackward<storm::utility::ElementLess<ValueType>>(rowGroupIndices, vector, summand, result, choices);
1960 multiplyAndReduceBackward<storm::utility::ElementGreater<ValueType>>(rowGroupIndices, vector, summand, result, choices);
1964template<
typename ValueType>
1965template<
typename Compare>
1967 std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
1968 std::vector<uint64_t>* choices)
const {
1970 auto elementIt = this->end() - 1;
1971 auto rowGroupIt = rowGroupIndices.
end() - 2;
1972 auto rowIt = rowIndications.end() - 2;
1973 typename std::vector<ValueType>::const_iterator summandIt;
1975 summandIt = summand->end() - 1;
1977 typename std::vector<uint64_t>::iterator choiceIt;
1979 choiceIt = choices->end() - 1;
1983 ValueType oldSelectedChoiceValue;
1984 uint64_t selectedChoice;
1986 uint64_t currentRow = this->getRowCount() - 1;
1987 for (
auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt) {
1988 ValueType currentValue = storm::utility::zero<ValueType>();
1991 if (*rowGroupIt < *(rowGroupIt + 1)) {
1993 currentValue = *summandIt;
1997 for (
auto elementIte = this->begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
1998 currentValue += elementIt->getValue() * vector[elementIt->getColumn()];
2001 selectedChoice = currentRow - *rowGroupIt;
2002 if (*choiceIt == selectedChoice) {
2003 oldSelectedChoiceValue = currentValue;
2009 for (uint64_t
i = *rowGroupIt + 1, end = *(rowGroupIt + 1);
i < end; --rowIt, --currentRow, ++
i, --summandIt) {
2010 ValueType newValue = summand ? *summandIt : storm::utility::zero<ValueType>();
2011 for (
auto elementIte = this->begin() + *rowIt - 1; elementIt != elementIte; --elementIt) {
2012 newValue += elementIt->getValue() * vector[elementIt->getColumn()];
2015 if (choices && currentRow == *choiceIt + *rowGroupIt) {
2016 oldSelectedChoiceValue = newValue;
2019 if (compare(newValue, currentValue)) {
2020 currentValue = newValue;
2022 selectedChoice = currentRow - *rowGroupIt;
2028 *resultIt = currentValue;
2029 if (choices && compare(currentValue, oldSelectedChoiceValue)) {
2030 *choiceIt = selectedChoice;
2038 std::vector<storm::RationalFunction>
const& vector,
2039 std::vector<storm::RationalFunction>
const* b,
2040 std::vector<storm::RationalFunction>& result, std::vector<uint64_t>* choices)
const {
2041 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"This operation is not supported.");
2044template<
typename ValueType>
2046 std::vector<ValueType>
const& vector, std::vector<ValueType>
const* summand, std::vector<ValueType>& result,
2047 std::vector<uint64_t>* choices)
const {
2049 std::vector<ValueType>* target;
2050 std::vector<ValueType> temporary;
2051 if (&vector == &result) {
2052 STORM_LOG_WARN(
"Vectors are aliased but are not allowed to be. Using temporary, which is potentially slow.");
2053 temporary = std::vector<ValueType>(vector.size());
2054 target = &temporary;
2059 this->multiplyAndReduceForward(dir, rowGroupIndices, vector, summand, *target, choices);
2061 if (target == &temporary) {
2062 std::swap(temporary, result);
2066template<
typename ValueType>
2070 std::vector<index_type>::const_iterator rowIterator = rowIndications.begin();
2071 std::vector<index_type>::const_iterator rowIteratorEnd = rowIndications.end();
2074 for (; rowIterator != rowIteratorEnd - 1; ++rowIterator) {
2075 for (ite = this->begin() + *(rowIterator + 1); it != ite; ++it) {
2076 result[it->getColumn()] += it->getValue() * vector[currentRow];
2082template<
typename ValueType>
2084 STORM_LOG_ASSERT(factors.size() == this->getRowCount(),
"Can not scale rows: Number of rows and number of scaling factors do not match.");
2086 for (
auto const& factor : factors) {
2087 for (
auto& entry : getRow(row)) {
2088 entry.setValue(entry.getValue() * factor);
2094template<
typename ValueType>
2096 STORM_LOG_ASSERT(divisors.size() == this->getRowCount(),
"Can not divide rows: Number of rows and number of divisors do not match.");
2098 for (
auto const& divisor : divisors) {
2100 for (
auto& entry : getRow(row)) {
2101 entry.setValue(entry.getValue() / divisor);
2109 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"This operation is not supported.");
2112template<
typename ValueType>
2114 return const_rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2117template<
typename ValueType>
2119 return rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow] - this->rowIndications[startRow]);
2122template<
typename ValueType>
2124 return getRows(row, row + 1);
2127template<
typename ValueType>
2129 return getRows(row, row + 1);
2132template<
typename ValueType>
2134 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(),
"Row group is out-of-bounds.");
2135 STORM_LOG_ASSERT(offset < this->getRowGroupSize(rowGroup),
"Row offset in row-group is out-of-bounds.");
2136 if (!this->hasTrivialRowGrouping()) {
2137 return getRow(this->getRowGroupIndices()[rowGroup] + offset);
2139 return getRow(this->getRowGroupIndices()[rowGroup] + offset);
2143template<
typename ValueType>
2145 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(),
"Row group is out-of-bounds.");
2146 STORM_LOG_ASSERT(offset < this->getRowGroupSize(rowGroup),
"Row offset in row-group is out-of-bounds.");
2147 if (!this->hasTrivialRowGrouping()) {
2148 return getRow(this->getRowGroupIndices()[rowGroup] + offset);
2151 return getRow(rowGroup + offset);
2155template<
typename ValueType>
2157 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(),
"Row group is out-of-bounds.");
2158 if (!this->hasTrivialRowGrouping()) {
2159 return getRows(this->getRowGroupIndices()[rowGroup], this->getRowGroupIndices()[rowGroup + 1]);
2161 return getRows(rowGroup, rowGroup + 1);
2165template<
typename ValueType>
2167 STORM_LOG_ASSERT(rowGroup < this->getRowGroupCount(),
"Row group is out-of-bounds.");
2168 if (!this->hasTrivialRowGrouping()) {
2169 return getRows(this->getRowGroupIndices()[rowGroup], this->getRowGroupIndices()[rowGroup + 1]);
2171 return getRows(rowGroup, rowGroup + 1);
2175template<
typename ValueType>
2177 STORM_LOG_ASSERT(row < this->getRowCount(),
"Row " << row <<
" exceeds row count " << this->getRowCount() <<
".");
2178 return this->columnsAndValues.begin() + this->rowIndications[row];
2181template<
typename ValueType>
2183 STORM_LOG_ASSERT(row < this->getRowCount(),
"Row " << row <<
" exceeds row count " << this->getRowCount() <<
".");
2184 return this->columnsAndValues.begin() + this->rowIndications[row];
2187template<
typename ValueType>
2189 return this->columnsAndValues.
begin();
2192template<
typename ValueType>
2194 return this->columnsAndValues.
begin();
2197template<
typename ValueType>
2199 STORM_LOG_ASSERT(row < this->getRowCount(),
"Row " << row <<
" exceeds row count " << this->getRowCount() <<
".");
2200 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2203template<
typename ValueType>
2205 STORM_LOG_ASSERT(row < this->getRowCount(),
"Row " << row <<
" exceeds row count " << this->getRowCount() <<
".");
2206 return this->columnsAndValues.begin() + this->rowIndications[row + 1];
2209template<
typename ValueType>
2211 return this->columnsAndValues.
begin() + this->rowIndications[rowCount];
2214template<
typename ValueType>
2216 return this->columnsAndValues.
begin() + this->rowIndications[rowCount];
2219template<
typename ValueType>
2221 ValueType sum = storm::utility::zero<ValueType>();
2222 for (
const_iterator it = this->begin(row), ite = this->end(row); it != ite; ++it) {
2223 sum += it->getValue();
2228template<
typename ValueType>
2231 for (
auto const& entry : *
this) {
2236 return nonConstEntries;
2239template<
typename ValueType>
2242 for (
index_type rowGroup = 0; rowGroup < this->getRowGroupCount(); ++rowGroup) {
2243 for (
auto const& entry : this->getRowGroup(rowGroup)) {
2245 ++nonConstRowGroups;
2250 return nonConstRowGroups;
2253template<
typename ValueType>
2256 for (
index_type row = 0; row < this->rowCount; ++row) {
2257 auto rowSum = getRowSum(row);
2258 if (!comparator.
isOne(rowSum)) {
2262 for (
auto const& entry : *
this) {
2272template<
typename ValueType>
2274 for (
auto const& entry : *
this) {
2282template<
typename ValueType>
2283template<
typename OtherValueType>
2300 for (
index_type row = 0; row < this->getRowCount(); ++row) {
2301 auto it2 = matrix.
begin(row);
2302 auto ite2 = matrix.
end(row);
2303 for (
const_iterator it1 = this->begin(row), ite1 = this->end(row); it1 != ite1; ++it1) {
2305 while (it2 != ite2 && it2->getColumn() < it1->getColumn()) {
2308 if (it2 == ite2 || it1->getColumn() != it2->getColumn()) {
2316template<
typename ValueType>
2318 if (this->getRowCount() != this->getColumnCount()) {
2321 if (this->getNonzeroEntryCount() != this->getRowCount()) {
2324 for (uint64_t row = 0; row < this->getRowCount(); ++row) {
2325 bool rowHasEntry =
false;
2326 for (
auto const& entry : this->getRow(row)) {
2327 if (entry.getColumn() == row) {
2345template<
typename ValueType>
2347 std::string result =
2348 std::to_string(getRowCount()) +
"x" + std::to_string(getColumnCount()) +
" matrix (" + std::to_string(getNonzeroEntryCount()) +
" non-zeroes";
2349 if (!hasTrivialRowGrouping()) {
2350 result +=
", " + std::to_string(getRowGroupCount()) +
" groups";
2356template<
typename ValueType>
2367 out <<
"\t---- group " << group <<
"/" << (matrix.
getRowGroupCount() - 1) <<
" ---- \n";
2375 out <<
i <<
"\t(\t";
2377 while (currentRealIndex < matrix.columnCount) {
2378 if (nextIndex < matrix.rowIndications[
i + 1] && currentRealIndex == matrix.columnsAndValues[nextIndex].getColumn()) {
2379 out << matrix.columnsAndValues[nextIndex].getValue() <<
"\t";
2386 out <<
"\t)\t" <<
i <<
'\n';
2400template<
typename ValueType>
2404 STORM_LOG_ASSERT(this->getRowGroupSize(group) == 1,
"Incorrect row group size.");
2411 while (currentRealIndex < this->columnCount) {
2412 if (nextIndex < this->rowIndications[
i + 1] && currentRealIndex == this->columnsAndValues[nextIndex].getColumn()) {
2413 out << this->columnsAndValues[nextIndex].getValue() <<
" ";
2425template<
typename ValueType>
2427 std::size_t result = 0;
2429 boost::hash_combine(result, this->getRowCount());
2430 boost::hash_combine(result, this->getColumnCount());
2431 boost::hash_combine(result, this->getEntryCount());
2432 boost::hash_combine(result, boost::hash_range(columnsAndValues.begin(), columnsAndValues.end()));
2433 boost::hash_combine(result, boost::hash_range(rowIndications.begin(), rowIndications.end()));
2434 if (!this->hasTrivialRowGrouping()) {
2435 boost::hash_combine(result, boost::hash_range(rowGroupIndices.get().begin(), rowGroupIndices.get().end()));
2466template std::ostream& operator<<(
2475#if defined(STORM_HAVE_CLN)
2488#if defined(STORM_HAVE_GMP)
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 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.
SparseMatrix()
Constructs an empty sparse matrix.
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 ...
const_iterator begin(index_type row) const
Retrieves an iterator that points to the beginning of the given row.
void setRowGroupIndices(std::vector< index_type > const &newRowGroupIndices)
Sets the row grouping to the given one.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the first row of the matrix.
const_iterator end(index_type row) const
Retrieves an iterator that points past the end of the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::vector< MatrixEntry< index_type, value_type > >::const_iterator const_iterator
bool hasTrivialRowGrouping() const
Retrieves whether the matrix has a trivial row grouping.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
std::vector< MatrixEntry< index_type, value_type > >::iterator iterator
index_type getRowCount() const
Returns the number of rows of the matrix.
SparseMatrixIndexType index_type
bool isOne(ValueType const &value) const
#define STORM_LOG_WARN(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
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)
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)
bool isNonNegative(ValueType const &a)