22template<
typename ValueType, BackendOptimizationDirection Dir = BackendOptimizationDirection::None,
bool TrackChoices = false>
26 requires(!TrackChoices)
27 : choiceTracking(
std::nullopt) {};
29 MultiplierBackend(std::vector<uint64_t>& choices, std::vector<uint64_t>
const& rowGroupIndices)
31 : choiceTracking({choices, rowGroupIndices}) {
39 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
40 best = std::move(value);
41 if constexpr (TrackChoices) {
42 choiceTracking.currentBestRow = row;
46 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
47 if constexpr (TrackChoices) {
49 choiceTracking.currentBestRow = row;
50 }
else if (*best == value) {
54 if (row == choiceTracking.choices[rowGroup] + choiceTracking.rowGroupIndices[rowGroup]) {
55 choiceTracking.currentBestRow = row;
58 }
else if constexpr (HasDir) {
61 STORM_LOG_ASSERT(
false,
"This backend does not support optimization direction.");
65 void applyUpdate(ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
66 if constexpr (HasDir) {
67 currValue = std::move(*best);
68 if constexpr (TrackChoices) {
69 choiceTracking.choices[rowGroup] = choiceTracking.currentBestRow - choiceTracking.rowGroupIndices[rowGroup];
72 currValue = std::move(best);
92 static_assert(!TrackChoices || HasDir,
"If TrackChoices is true, Dir must be set to either Minimize or Maximize.");
94 std::conditional_t<HasDir, storm::utility::Extremum<OptDir, ValueType>, ValueType> best;
96 struct SchedulerTrackingData {
97 std::vector<uint64_t>& choices;
98 std::vector<uint64_t>
const& rowGroupIndices;
99 uint64_t currentBestRow{0};
101 std::conditional_t<TrackChoices, SchedulerTrackingData, std::nullopt_t> choiceTracking;
108template<
typename ValueType>
117 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, uint64_t row) {
118 rowResults[row] = std::move(value);
121 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, uint64_t row) {
122 rowResults[row] = std::move(value);
125 void applyUpdate([[maybe_unused]] ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
142 std::vector<ValueType>& rowResults;
147template<
typename ValueType,
bool TrivialRowGrouping>
153template<
typename ValueType,
bool TrivialRowGrouping>
155 if (!viOperatorFwd) {
156 return initialize(
false);
158 return *viOperatorFwd;
162template<
typename ValueType,
bool TrivialRowGrouping>
163typename ViOperatorMultiplier<ValueType, TrivialRowGrouping>::ViOpT& ViOperatorMultiplier<ValueType, TrivialRowGrouping>::initialize(
bool backwards)
const {
164 auto& viOp = backwards ? viOperatorBwd : viOperatorFwd;
166 viOp = std::make_unique<ViOpT>();
168 viOp->setMatrixBackwards(this->matrix);
170 viOp->setMatrixForwards(this->matrix);
176template<
typename ValueType,
bool TrivialRowGrouping>
178 std::vector<ValueType>& result)
const {
180 auto& tmpResult = this->provideCachedVector(x.size());
181 multiply(env, x, b, tmpResult);
182 std::swap(result, tmpResult);
185 auto const& viOp = initialize();
190 viOp.apply(x, result, *b, backend);
192 viOp.apply(x, result, storm::utility::zero<ValueType>(), backend);
196template<
typename ValueType,
bool TrivialRowGrouping>
198 std::vector<ValueType>
const* b,
bool backwards)
const {
199 STORM_LOG_THROW(TrivialRowGrouping, storm::exceptions::NotSupportedException,
200 "This multiplier does not support multiplications without reduction when invoked with non-trivial row groups");
202 auto const& viOp = initialize(backwards);
204 viOp.applyInPlace(x, *b, backend);
206 viOp.applyInPlace(x, storm::utility::zero<ValueType>(), backend);
210template<
typename ValueType,
bool TrivialRowGrouping>
212 std::vector<uint64_t>
const& rowGroupIndices, std::vector<ValueType>
const& x,
213 std::vector<ValueType>
const* b, std::vector<ValueType>& result,
214 std::vector<uint64_t>* choices)
const {
216 auto& tmpResult = this->provideCachedVector(x.size());
217 multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, choices);
218 std::swap(result, tmpResult);
221 STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
222 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
223 auto const& viOp = initialize();
224 auto apply = [&]<
typename BT>(BT& backend) {
226 viOp.apply(x, result, *b, backend);
228 viOp.apply(x, result, storm::utility::zero<ValueType>(), backend);
250template<
typename ValueType,
bool TrivialRowGrouping>
252 std::vector<uint64_t>
const& rowGroupIndices, std::vector<ValueType>& x,
253 std::vector<ValueType>
const* b, std::vector<uint_fast64_t>* choices,
254 bool backwards)
const {
255 STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
256 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
257 auto const& viOp = initialize(backwards);
258 auto apply = [&]<
typename BT>(BT& backend) {
260 viOp.applyInPlace(x, *b, backend);
262 viOp.applyInPlace(x, storm::utility::zero<ValueType>(), backend);
284template<
typename ValueType,
bool TrivialRowGrouping>
286 viOperatorBwd.reset();
287 viOperatorFwd.reset();
virtual void clearCache() const
virtual void multiplyAndReduceGaussSeidel(Environment const &env, OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< ValueType > &x, std::vector< ValueType > const *b, std::vector< uint_fast64_t > *choices=nullptr, bool backwards=true) const override
virtual void multiplyGaussSeidel(Environment const &env, std::vector< ValueType > &x, std::vector< ValueType > const *b, bool backwards=true) const override
Performs a matrix-vector multiplication in gauss-seidel style.
virtual void multiplyAndReduce(Environment const &env, OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< ValueType > const &x, std::vector< ValueType > const *b, std::vector< ValueType > &result, std::vector< uint_fast64_t > *choices=nullptr) const override
ViOperatorMultiplier(storm::storage::SparseMatrix< ValueType > const &matrix)
virtual void clearCache() const override
virtual void multiply(Environment const &env, std::vector< ValueType > const &x, std::vector< ValueType > const *b, std::vector< ValueType > &result) const override
Performs a matrix-vector multiplication x' = A*x + b.
This backend stores the best (maximal or minimal) value of the current row group.
void applyUpdate(ValueType &currValue, uint64_t rowGroup)
void firstRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
void nextRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
MultiplierBackend(std::vector< uint64_t > &choices, std::vector< uint64_t > const &rowGroupIndices)
bool constexpr abort() const
void endOfIteration() const
This backend simply stores the row results in a vector.
void applyUpdate(ValueType &currValue, uint64_t rowGroup)
PlainMultiplicationBackend(std::vector< ValueType > &rowResults)
void firstRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
void nextRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
bool constexpr abort() const
void endOfIteration() const
This class represents the Value Iteration Operator (also known as Bellman operator).
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
BackendOptimizationDirection
bool constexpr minimize(OptimizationDirection d)