Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ValueIterationHelper.cpp
Go to the documentation of this file.
2
6
7namespace storm::solver::helper {
8
9template<typename ValueType, storm::OptimizationDirection Dir, bool Relative>
11 public:
12 VIOperatorBackend(ValueType const& precision) : precision{precision} {
13 // intentionally empty
14 }
15
17 isConverged = true;
18 }
19
20 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
21 best = std::move(value);
22 }
23
24 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
25 best &= value;
26 }
27
28 void applyUpdate(ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
29 if (isConverged) {
30 if constexpr (Relative) {
31 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= storm::utility::abs<ValueType>(precision * currValue);
32 } else {
33 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= precision;
34 }
35 }
36 currValue = std::move(*best);
37 }
38
39 void endOfIteration() const {
40 // intentionally left empty.
41 }
42
43 bool converged() const {
44 return isConverged;
45 }
46
47 bool constexpr abort() const {
48 return false;
49 }
50
51 private:
53 ValueType const precision;
54 bool isConverged{true};
55};
56
57template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
63
64template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
65template<storm::OptimizationDirection Dir, bool Relative, storm::OptimizationDirection RobustDir>
66SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
67 uint64_t& numIterations, SolutionType const& precision,
68 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
69 MultiplicationStyle mult) const {
71 std::vector<SolutionType>* operand1{&operand};
72 std::vector<SolutionType>* operand2{&operand};
73 if (mult == MultiplicationStyle::Regular) {
74 operand2 = &viOperator->allocateAuxiliaryVector(operand.size());
75 }
76 bool resultInAuxVector{false};
78 while (status == SolverStatus::InProgress) {
79 ++numIterations;
80 bool applyResult = viOperator->template applyRobust<RobustDir>(*operand1, *operand2, offsets, backend);
81 if (applyResult) {
83 } else if (iterationCallback) {
84 status = iterationCallback(status);
85 }
86 if (mult == MultiplicationStyle::Regular) {
87 std::swap(operand1, operand2);
88 resultInAuxVector = !resultInAuxVector;
89 }
90 }
91 if (mult == MultiplicationStyle::Regular) {
92 if (resultInAuxVector) {
93 STORM_LOG_ASSERT(&operand == operand2, "Unexpected operand address");
94 std::swap(*operand1, *operand2);
95 }
96 viOperator->freeAuxiliaryVector();
97 }
98 return status;
99}
100
101template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
102template<storm::OptimizationDirection Dir, bool Relative>
103SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
104 uint64_t& numIterations, SolutionType const& precision,
105 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
106 MultiplicationStyle mult, bool robust) const {
107 if (robust) {
108 return VI<Dir, Relative, invert(Dir)>(operand, offsets, numIterations, precision, iterationCallback, mult);
109 } else {
110 return VI<Dir, Relative, Dir>(operand, offsets, numIterations, precision, iterationCallback, mult);
111 }
112}
113
114template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
115SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
116 uint64_t& numIterations, bool relative, SolutionType const& precision,
117 std::optional<storm::OptimizationDirection> const& dir,
118 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
119 MultiplicationStyle mult, bool robust) const {
120 STORM_LOG_ASSERT(TrivialRowGrouping || dir.has_value(), "no optimization direction given!");
121 if (!dir.has_value() || maximize(*dir)) {
122 if (relative) {
123 return VI<storm::OptimizationDirection::Maximize, true>(operand, offsets, numIterations, precision, iterationCallback, mult, robust);
124 } else {
125 return VI<storm::OptimizationDirection::Maximize, false>(operand, offsets, numIterations, precision, iterationCallback, mult, robust);
126 }
127 } else {
128 if (relative) {
129 return VI<storm::OptimizationDirection::Minimize, true>(operand, offsets, numIterations, precision, iterationCallback, mult, robust);
130 } else {
131 return VI<storm::OptimizationDirection::Minimize, false>(operand, offsets, numIterations, precision, iterationCallback, mult, robust);
132 }
133 }
134}
135
136template<typename ValueType, bool TrivialRowGrouping, typename SolutionType>
137SolverStatus ValueIterationHelper<ValueType, TrivialRowGrouping, SolutionType>::VI(std::vector<SolutionType>& operand, std::vector<ValueType> const& offsets,
138 bool relative, SolutionType const& precision,
139 std::optional<storm::OptimizationDirection> const& dir,
140 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
141 MultiplicationStyle mult, bool robust) const {
142 uint64_t numIterations = 0;
143 return VI(operand, offsets, numIterations, relative, precision, dir, iterationCallback, mult, robust);
144}
145
152
153} // 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
bool constexpr maximize(OptimizationDirection d)