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