Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ValueIterationHelper.cpp
Go to the documentation of this file.
2
8
9namespace storm::solver::helper {
10
11template<typename ValueType, storm::OptimizationDirection Dir, bool Relative>
13 public:
14 VIOperatorBackend(ValueType const& precision) : precision{precision} {
15 // intentionally empty
16 }
17
19 isConverged = true;
20 }
21
22 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
23 best = std::move(value);
24 }
25
26 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
27 best &= value;
28 }
29
30 void applyUpdate(ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
31 if (isConverged) {
32 if constexpr (Relative) {
33 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= storm::utility::abs<ValueType>(precision * currValue);
34 } else {
35 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= precision;
36 }
37 }
38 currValue = std::move(*best);
39 }
40
41 void endOfIteration() const {
42 // intentionally left empty.
43 }
44
45 bool converged() const {
46 return isConverged;
47 }
48
49 bool constexpr abort() const {
50 return false;
51 }
52
53 private:
55 ValueType const precision;
56 bool isConverged{true};
57};
58
59template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
65
66template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
67template<storm::OptimizationDirection Dir, bool Relative, storm::OptimizationDirection RobustDir>
68SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
69 uint64_t& numIterations, SolutionType const& precision,
70 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
71 MultiplicationStyle mult) const {
73 std::vector<SolutionType>* operand1{&operand};
74 std::vector<SolutionType>* operand2{&operand};
75 if (mult == MultiplicationStyle::Regular) {
76 operand2 = &viOperator->allocateAuxiliaryVector(operand.size());
77 }
78 bool resultInAuxVector{false};
80 while (status == SolverStatus::InProgress) {
81 ++numIterations;
82 bool applyResult = viOperator->template applyRobust<RobustDir>(*operand1, *operand2, offsets, backend);
83 if (applyResult) {
85 } else if (iterationCallback) {
86 status = iterationCallback(status);
87 }
88 if (mult == MultiplicationStyle::Regular) {
89 std::swap(operand1, operand2);
90 resultInAuxVector = !resultInAuxVector;
91 }
92 }
93 if (mult == MultiplicationStyle::Regular) {
94 if (resultInAuxVector) {
95 STORM_LOG_ASSERT(&operand == operand2, "Unexpected operand address");
96 std::swap(*operand1, *operand2);
97 }
98 viOperator->freeAuxiliaryVector();
99 }
100 return status;
101}
102
103template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
104template<storm::OptimizationDirection Dir, bool Relative>
105SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
106 uint64_t& numIterations, SolutionType const& precision,
107 const std::function<SolverStatus(const SolverStatus&)>& iterationCallback,
109 UncertaintyResolutionMode const& uncertaintyResolutionMode) const {
110 bool robustUncertainty = false;
111 if (storm::IsIntervalType<ValueType>) {
112 robustUncertainty = isUncertaintyResolvedRobust(uncertaintyResolutionMode, Dir);
113 }
114
115 if (robustUncertainty) {
116 return VI<Dir, Relative, invert(Dir)>(operand, offsets, numIterations, precision, iterationCallback, mult);
117 } else {
118 return VI<Dir, Relative, Dir>(operand, offsets, numIterations, precision, iterationCallback, mult);
119 }
120}
121
122template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
123SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
124 uint64_t& numIterations, bool relative, SolutionType const& precision,
125 std::optional<storm::OptimizationDirection> const& dir,
126 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
128 UncertaintyResolutionMode const& uncertaintyResolutionMode) const {
129 if (storm::IsIntervalType<ValueType>) {
130 STORM_LOG_THROW(uncertaintyResolutionMode != UncertaintyResolutionMode::Unset, storm::exceptions::IllegalFunctionCallException,
131 "Uncertainty resolution mode must be set for uncertain (interval) models.");
132 STORM_LOG_THROW(dir.has_value() || (uncertaintyResolutionMode != UncertaintyResolutionMode::Robust &&
133 uncertaintyResolutionMode != UncertaintyResolutionMode::Cooperative),
134 storm::exceptions::IllegalFunctionCallException,
135 "Robust or cooperative nature resolution modes cannot be used if optimization direction is not set.");
136 }
137
138 STORM_LOG_ASSERT(TrivialRowGrouping || dir.has_value(), "no optimization direction given!");
139 if (!dir.has_value() || maximize(*dir)) {
140 if (relative) {
141 return VI<storm::OptimizationDirection::Maximize, true>(operand, offsets, numIterations, precision, iterationCallback, mult,
142 uncertaintyResolutionMode);
143 } else {
144 return VI<storm::OptimizationDirection::Maximize, false>(operand, offsets, numIterations, precision, iterationCallback, mult,
145 uncertaintyResolutionMode);
146 }
147 } else {
148 if (relative) {
149 return VI<storm::OptimizationDirection::Minimize, true>(operand, offsets, numIterations, precision, iterationCallback, mult,
150 uncertaintyResolutionMode);
151 } else {
152 return VI<storm::OptimizationDirection::Minimize, false>(operand, offsets, numIterations, precision, iterationCallback, mult,
153 uncertaintyResolutionMode);
154 }
155 }
156}
157
158template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
159SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
160 bool relative, SolutionType const& precision,
161 std::optional<storm::OptimizationDirection> const& dir,
162 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
164 UncertaintyResolutionMode const& uncertaintyResolutionMode) const {
165 uint64_t numIterations = 0;
166 return VI(operand, offsets, numIterations, relative, precision, dir, iterationCallback, mult, uncertaintyResolutionMode);
167}
168
175
176} // namespace storm::solver::helper
void applyUpdate(ValueType &currValue, uint64_t rowGroup)
void nextRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
void firstRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
ValueIterationHelper(std::shared_ptr< ValueIterationOperator< ValueType, TrivialRowGrouping, SolutionType > > viOperator)
SolverStatus VI(std::vector< SolutionType > &operand, std::vector< ValueType > const &offsets, uint64_t &numIterations, SolutionType const &precision, std::function< SolverStatus(SolverStatus const &)> const &iterationCallback={}, MultiplicationStyle mult=MultiplicationStyle::GaussSeidel) const
This class represents the Value Iteration Operator (also known as Bellman operator).
Stores and manages an extremal (maximal or minimal) value.
Definition Extremum.h:15
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool constexpr maximize(OptimizationDirection d)
bool isUncertaintyResolvedRobust(UncertaintyResolutionMode uncertaintyResolutionMode, OptimizationDirection optimizationDirection)