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,
typename SolutionType>
153template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
154typename ViOperatorMultiplier<ValueType, TrivialRowGrouping, SolutionType>::ViOpT&
155ViOperatorMultiplier<ValueType, TrivialRowGrouping, SolutionType>::initialize()
const {
156 if (!viOperatorFwd) {
157 return initialize(
false);
159 return *viOperatorFwd;
163template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
164typename ViOperatorMultiplier<ValueType, TrivialRowGrouping, SolutionType>::ViOpT&
165ViOperatorMultiplier<ValueType, TrivialRowGrouping, SolutionType>::initialize(
bool backwards)
const {
166 auto& viOp = backwards ? viOperatorBwd : viOperatorFwd;
168 viOp = std::make_unique<ViOpT>();
170 viOp->setMatrixBackwards(this->matrix);
172 viOp->setMatrixForwards(this->matrix);
178template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
180 std::vector<ValueType>
const* b, std::vector<SolutionType>& result)
const {
184 std::swap(result, tmpResult);
187 auto const& viOp = initialize();
192 viOp.apply(x, result, *b, backend);
198template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
200 std::vector<ValueType>
const* b,
bool backwards)
const {
201 STORM_LOG_THROW(TrivialRowGrouping, storm::exceptions::NotSupportedException,
202 "This multiplier does not support multiplications without reduction when invoked with non-trivial row groups");
204 auto const& viOp = initialize(backwards);
206 viOp.applyInPlace(x, *b, backend);
212template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
214 std::vector<uint64_t>
const& rowGroupIndices,
215 std::vector<SolutionType>
const& x, std::vector<ValueType>
const* b,
216 std::vector<SolutionType>& result,
218 std::vector<uint64_t>* choices)
const {
221 multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, uncertaintyResolutionMode, choices);
222 std::swap(result, tmpResult);
225 STORM_LOG_THROW(&rowGroupIndices == &this->
matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
226 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
227 auto const& viOp = initialize();
229 auto applyRobustDirection = [&]<
storm::OptimizationDirection Dir,
typename BT,
typename OffsetType>(BT& backend, OffsetType
const& offset) {
230 bool robustUncertainty =
false;
235 if (robustUncertainty) {
236 viOp.template applyRobust<invert(Dir)>(x, result, offset, backend);
238 viOp.template applyRobust<Dir>(x, result, offset, backend);
242 auto applyBackend = [&]<
typename OffsetType>(OffsetType
const& offset) {
246 this->
matrix.getRowGroupIndices());
247 applyRobustDirection.template operator()<OptimizationDirection::Minimize>(backend, offset);
250 applyRobustDirection.template operator()<OptimizationDirection::Minimize>(backend, offset);
255 this->
matrix.getRowGroupIndices());
256 applyRobustDirection.template operator()<OptimizationDirection::Maximize>(backend, offset);
259 applyRobustDirection.template operator()<OptimizationDirection::Maximize>(backend, offset);
271template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
274 std::vector<ValueType>
const* b, std::vector<uint_fast64_t>* choices,
bool backwards)
const {
275 STORM_LOG_THROW(&rowGroupIndices == &this->
matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException,
276 "The row group indices must be the same as the ones stored in the matrix of this multiplier");
277 auto const& viOp = initialize(backwards);
278 auto apply = [&]<
typename BT>(BT& backend) {
280 viOp.applyInPlace(x, *b, backend);
304template<
typename ValueType,
bool TrivialRowGrouping,
typename SolutionType>
306 viOperatorBwd.reset();
307 viOperatorFwd.reset();
Multiplier(storm::storage::SparseMatrix< ValueType > const &matrix)
std::vector< ValueType > & provideCachedVector(uint64_t size) const
virtual void clearCache() const
storm::storage::SparseMatrix< ValueType > const & matrix
virtual void multiplyAndReduceGaussSeidel(Environment const &env, OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< SolutionType > &x, std::vector< ValueType > const *b, std::vector< uint_fast64_t > *choices=nullptr, bool backwards=true) const override
virtual void multiplyAndReduce(Environment const &env, OptimizationDirection const &dir, std::vector< uint64_t > const &rowGroupIndices, std::vector< SolutionType > const &x, std::vector< ValueType > const *b, std::vector< SolutionType > &result, UncertaintyResolutionMode const &uncertaintyResolutionMode=UncertaintyResolutionMode::Unset, std::vector< uint_fast64_t > *choices=nullptr) const override
virtual void multiply(Environment const &env, std::vector< SolutionType > const &x, std::vector< ValueType > const *b, std::vector< SolutionType > &result) const override
ViOperatorMultiplier(storm::storage::SparseMatrix< ValueType > const &matrix)
virtual void multiplyGaussSeidel(Environment const &env, std::vector< SolutionType > &x, std::vector< ValueType > const *b, bool backwards=true) const override
virtual void clearCache() const override
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
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)
UncertaintyResolutionMode
bool isUncertaintyResolvedRobust(UncertaintyResolutionMode uncertaintyResolutionMode, OptimizationDirection optimizationDirection)
solver::OptimizationDirection OptimizationDirection
constexpr bool IsIntervalType
Helper to check if a type is an interval.