12template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
13template<
bool Backward>
15 std::vector<IndexType>
const* rowGroupIndices) {
16 if constexpr (TrivialRowGrouping) {
18 STORM_LOG_ASSERT(rowGroupIndices ==
nullptr,
"Row groups given, but grouping is supposed to be trivial.");
19 this->rowGroupIndices =
nullptr;
21 if (rowGroupIndices) {
22 this->rowGroupIndices = rowGroupIndices;
27 this->backwards = Backward;
28 this->hasSkippedRows =
false;
31 matrixColumns.clear();
36 if constexpr (std::is_same<ValueType, storm::Interval>::value) {
37 applyCache.hasOnlyConstants.clear();
38 applyCache.hasOnlyConstants.grow(matrix.
getRowCount());
41 if constexpr (!TrivialRowGrouping) {
42 matrixColumns.push_back(StartOfRowGroupIndicator);
43 for (
auto groupIndex : indexRange<Backward>(0, this->rowGroupIndices->size() - 1)) {
44 STORM_LOG_ASSERT(this->rowGroupIndices->at(groupIndex) != this->rowGroupIndices->at(groupIndex + 1),
45 "There is an empty row group. This is not expected.");
46 for (
auto rowIndex : indexRange<false>((*this->rowGroupIndices)[groupIndex], (*this->rowGroupIndices)[groupIndex + 1])) {
47 for (
auto const& entry : matrix.
getRow(rowIndex)) {
48 matrixValues.push_back(entry.getValue());
49 matrixColumns.push_back(entry.getColumn());
51 matrixColumns.push_back(StartOfRowIndicator);
53 matrixColumns.back() = StartOfRowGroupIndicator;
56 if constexpr (std::is_same<ValueType, storm::Interval>::value) {
57 matrixColumns.push_back(StartOfRowIndicator);
58 for (
auto rowIndex : indexRange<Backward>(0, numRows)) {
59 bool hasOnlyConstants =
true;
60 for (
auto const& entry : matrix.
getRow(rowIndex)) {
61 ValueType value = entry.getValue();
62 hasOnlyConstants &= value.upper() == value.lower();
63 matrixValues.push_back(value);
64 matrixColumns.push_back(entry.getColumn());
66 applyCache.hasOnlyConstants.set(rowIndex, hasOnlyConstants);
67 matrixColumns.push_back(StartOfRowIndicator);
70 matrixColumns.push_back(StartOfRowIndicator);
71 for (
auto rowIndex : indexRange<Backward>(0, numRows)) {
72 for (
auto const& entry : matrix.
getRow(rowIndex)) {
73 matrixValues.push_back(entry.getValue());
74 matrixColumns.push_back(entry.getColumn());
76 matrixColumns.push_back(StartOfRowIndicator);
82template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
84 std::vector<IndexType>
const* rowGroupIndices) {
85 setMatrix<false>(matrix, rowGroupIndices);
88template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
90 std::vector<IndexType>
const* rowGroupIndices) {
91 setMatrix<true>(matrix, rowGroupIndices);
94template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
96 for (
auto& c : matrixColumns) {
97 if (c >= StartOfRowIndicator) {
98 c &= StartOfRowGroupIndicator;
101 hasSkippedRows =
false;
104template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
105template<
bool Backward>
107 std::function<
bool(IndexType, IndexType)>
const& ignore) {
108 STORM_LOG_ASSERT(!TrivialRowGrouping,
"Tried to ignroe rows but the row grouping is trivial.");
109 auto colIt = matrixColumns.begin();
110 for (
auto groupIndex : indexRange<Backward>(0, this->rowGroupIndices->size() - 1)) {
111 STORM_LOG_ASSERT(colIt != matrixColumns.end(),
"VI Operator in invalid state.");
112 STORM_LOG_ASSERT(*colIt >= StartOfRowGroupIndicator,
"VI Operator in invalid state.");
113 auto const rowIndexRange = useLocalRowIndices ? indexRange<false>(0ull, (*this->rowGroupIndices)[groupIndex + 1] - (*this->rowGroupIndices)[groupIndex])
114 : indexRange<false>((*this->rowGroupIndices)[groupIndex], (*this->rowGroupIndices)[groupIndex + 1]);
115 for (
auto const rowIndex : rowIndexRange) {
116 if (!ignore(groupIndex, rowIndex)) {
117 *colIt &= StartOfRowGroupIndicator;
118 moveToEndOfRow(colIt);
119 }
else if ((*colIt & SkipNumEntriesMask) == 0) {
120 auto currColIt = colIt;
121 moveToEndOfRow(colIt);
122 *currColIt += std::distance(currColIt, colIt);
125 !std::all_of(rowIndexRange.begin(), rowIndexRange.end(), [&ignore, &groupIndex](IndexType rowIndex) { return ignore(groupIndex, rowIndex); }),
126 "All rows in row group " << groupIndex <<
" are ignored.");
127 STORM_LOG_ASSERT(colIt != matrixColumns.end(),
"VI Operator in invalid state.");
128 STORM_LOG_ASSERT(*colIt >= StartOfRowIndicator,
"VI Operator in invalid state.");
130 STORM_LOG_ASSERT(*colIt == StartOfRowGroupIndicator,
"VI Operator in invalid state.");
132 hasSkippedRows =
true;
135template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
139 setIgnoredRows<true>(useLocalRowIndices, ignore);
141 setIgnoredRows<false>(useLocalRowIndices, ignore);
145template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
146std::vector<typename ValueIterationOperator<ValueType, TrivialRowGrouping, SolutionType>::IndexType>
const&
148 STORM_LOG_ASSERT(!TrivialRowGrouping,
"Tried to get row group indices for trivial row grouping");
149 return *rowGroupIndices;
152template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
154 uint64_t size, std::optional<SolutionType>
const& initialValue) {
155 STORM_LOG_ASSERT(!auxiliaryVectorUsedExternally,
"Auxiliary vector already in use.");
157 auxiliaryVector.assign(size, *initialValue);
159 auxiliaryVector.resize(size);
161 auxiliaryVectorUsedExternally =
true;
162 return auxiliaryVector;
165template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
167 auxiliaryVectorUsedExternally =
false;
170template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
174 }
while (*matrixColumnIt < StartOfRowIndicator);
177template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
178bool ValueIterationOperator<ValueType, TrivialRowGrouping, SolutionType>::skipIgnoredRow(std::vector<IndexType>::const_iterator& matrixColumnIt,
179 typename std::vector<ValueType>::const_iterator& matrixValueIt)
const {
180 if (IndexType entriesToSkip = (*matrixColumnIt & SkipNumEntriesMask)) {
181 matrixColumnIt += entriesToSkip;
182 matrixValueIt += entriesToSkip - 1;
188template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
189uint64_t ValueIterationOperator<ValueType, TrivialRowGrouping, SolutionType>::skipMultipleIgnoredRows(
190 std::vector<IndexType>::const_iterator& matrixColumnIt,
typename std::vector<ValueType>::const_iterator& matrixValueIt)
const {
192 while (skipIgnoredRow(matrixColumnIt, matrixValueIt)) {
194 STORM_LOG_ASSERT(*matrixColumnIt >= StartOfRowIndicator,
"Undexpected state of VI operator");
196 STORM_LOG_ASSERT(*matrixColumnIt < StartOfRowGroupIndicator,
"Undexpected state of VI operator");
201template class ValueIterationOperator<double, true>;
202template class ValueIterationOperator<double, false>;
203template class ValueIterationOperator<storm::RationalNumber, true>;
204template class ValueIterationOperator<storm::RationalNumber, false>;
205template class ValueIterationOperator<storm::Interval, true, double>;
206template class ValueIterationOperator<storm::Interval, false, double>;
This class represents the Value Iteration Operator (also known as Bellman operator).
std::vector< SolutionType > & allocateAuxiliaryVector(uint64_t size, std::optional< SolutionType > const &initialValue={})
Allocates additional storage that can be used e.g.
void unsetIgnoredRows()
Clears all ignored rows.
void setIgnoredRows(bool useLocalRowIndices, std::function< bool(IndexType, IndexType)> const &ignore)
Sets rows that will be skipped when applying the operator.
std::vector< IndexType > const & getRowGroupIndices() const
void setMatrix(storm::storage::SparseMatrix< ValueType > const &matrix, std::vector< IndexType > const *rowGroupIndices=nullptr)
Initializes this operator with the given data.
void freeAuxiliaryVector()
Clears the auxiliary vector, invalidating any references to it.
storm::storage::sparse::state_type IndexType
void setMatrixForwards(storm::storage::SparseMatrix< ValueType > const &matrix, std::vector< IndexType > const *rowGroupIndices=nullptr)
Initializes this operator with the given data for forward iterations (starting with the smallest row ...
void setMatrixBackwards(storm::storage::SparseMatrix< ValueType > const &matrix, std::vector< IndexType > const *rowGroupIndices=nullptr)
Initializes this operator with the given data for backward iterations (starting with the largest row ...
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
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.
index_type getRowCount() const
Returns the number of rows of the matrix.
index_type getNonzeroEntryCount() const
Returns the cached number of nonzero entries in the matrix.
#define STORM_LOG_ASSERT(cond, message)