20template<
typename ValueType, BackendOptimizationDirection Dir = BackendOptimizationDirection::None,
bool TrackChoices = false>
24 requires(!TrackChoices)
25 : choiceTracking(
std::nullopt) {};
27 MultiplierBackend(std::vector<uint64_t>& choices, std::vector<uint64_t>
const& rowGroupIndices)
29 : choiceTracking({choices, rowGroupIndices}) {
37 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
38 best = std::move(value);
39 if constexpr (TrackChoices) {
40 choiceTracking.currentBestRow = row;
44 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
45 if constexpr (TrackChoices) {
47 choiceTracking.currentBestRow = row;
48 }
else if (*best == value) {
52 if (row == choiceTracking.choices[rowGroup] + choiceTracking.rowGroupIndices[rowGroup]) {
53 choiceTracking.currentBestRow = row;
56 }
else if constexpr (HasDir) {
59 STORM_LOG_ASSERT(
false,
"This backend does not support optimization direction.");
63 void applyUpdate(ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
64 if constexpr (HasDir) {
65 currValue = std::move(*best);
66 if constexpr (TrackChoices) {
67 choiceTracking.choices[rowGroup] = choiceTracking.currentBestRow - choiceTracking.rowGroupIndices[rowGroup];
70 currValue = std::move(best);
90 static_assert(!TrackChoices || HasDir,
"If TrackChoices is true, Dir must be set to either Minimize or Maximize.");
92 std::conditional_t<HasDir, storm::utility::Extremum<OptDir, ValueType>, ValueType> best;
94 struct SchedulerTrackingData {
95 std::vector<uint64_t>& choices;
96 std::vector<uint64_t>
const& rowGroupIndices;
97 uint64_t currentBestRow{0};
99 std::conditional_t<TrackChoices, SchedulerTrackingData, std::nullopt_t> choiceTracking;
106template<
typename ValueType>
115 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, uint64_t row) {
116 rowResults[row] = std::move(value);
119 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, uint64_t row) {
120 rowResults[row] = std::move(value);
123 void applyUpdate([[maybe_unused]] ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
140 std::vector<ValueType>& rowResults;
145template<
typename ValueType,
bool TrivialRowGrouping>
151template<
typename ValueType,
bool TrivialRowGrouping>
153 if (!viOperatorFwd) {
154 return initialize(
false);
156 return *viOperatorFwd;
160template<
typename ValueType,
bool TrivialRowGrouping>
161typename ViOperatorMultiplier<ValueType, TrivialRowGrouping>::ViOpT& ViOperatorMultiplier<ValueType, TrivialRowGrouping>::initialize(
bool backwards)
const {
162 auto& viOp = backwards ? viOperatorBwd : viOperatorFwd;
164 viOp = std::make_unique<ViOpT>();
166 viOp->setMatrixBackwards(this->matrix);
168 viOp->setMatrixForwards(this->matrix);
174template<
typename ValueType,
bool TrivialRowGrouping>
176 std::vector<ValueType>& result)
const {
178 auto& tmpResult = this->provideCachedVector(x.size());
179 multiply(env, x, b, tmpResult);
180 std::swap(result, tmpResult);
183 auto const& viOp = initialize();
188 viOp.apply(x, result, *b, backend);
190 viOp.apply(x, result, storm::utility::zero<ValueType>(), backend);
194template<
typename ValueType,
bool TrivialRowGrouping>
196 std::vector<ValueType>
const* b,
bool backwards)
const {
197 STORM_LOG_THROW(TrivialRowGrouping, storm::exceptions::NotSupportedException,
198 "This multiplier does not support multiplications without reduction when invoked with non-trivial row groups");
200 auto const& viOp = initialize(backwards);
202 viOp.applyInPlace(x, *b, backend);
204 viOp.applyInPlace(x, storm::utility::zero<ValueType>(), backend);
208template<
typename ValueType,
bool TrivialRowGrouping>
210 std::vector<uint64_t>
const& rowGroupIndices, std::vector<ValueType>
const& x,
211 std::vector<ValueType>
const* b, std::vector<ValueType>& result,
212 std::vector<uint64_t>* choices)
const {
214 auto& tmpResult = this->provideCachedVector(x.size());
215 multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, choices);
216 std::swap(result, tmpResult);
219 STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
220 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
221 auto const& viOp = initialize();
222 auto apply = [&]<
typename BT>(BT& backend) {
224 viOp.apply(x, result, *b, backend);
226 viOp.apply(x, result, storm::utility::zero<ValueType>(), backend);
248template<
typename ValueType,
bool TrivialRowGrouping>
250 std::vector<uint64_t>
const& rowGroupIndices, std::vector<ValueType>& x,
251 std::vector<ValueType>
const* b, std::vector<uint_fast64_t>* choices,
252 bool backwards)
const {
253 STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
254 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
255 auto const& viOp = initialize(backwards);
256 auto apply = [&]<
typename BT>(BT& backend) {
258 viOp.applyInPlace(x, *b, backend);
260 viOp.applyInPlace(x, storm::utility::zero<ValueType>(), backend);
282template<
typename ValueType,
bool TrivialRowGrouping>
284 viOperatorBwd.reset();
285 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)