Storm 1.11.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DiscountedValueIterationHelper.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 DiscountedVIOperatorBackend(ValueType const& precision, ValueType const& discountFactor, ValueType const& maximalAbsoluteReward)
13 : precision{precision},
14 discountFactor{discountFactor},
15 // We initialize the bound with a value guarantees preciseness when the difference between two iterations is less than it
16 // See Russell, Norvig: Artificial Intelligence: A Modern Approach, 4th ed., p.583
17 bound{(((storm::utility::one<ValueType>() - discountFactor) * precision) / (discountFactor))} {
18 auto upper = storm::utility::log<ValueType>((2 * maximalAbsoluteReward) / (precision * (1 - discountFactor)));
19 maxIterations = storm::utility::convertNumber<uint64_t>(storm::utility::ceil<ValueType>(upper / -storm::utility::log(discountFactor)));
20 STORM_LOG_DEBUG("Maximum number of iterations: " << maxIterations);
21 }
22
24 isConverged = true;
25 }
26
27 void firstRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
28 best = std::move(value);
29 }
30
31 void nextRow(ValueType&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
32 best &= value;
33 }
34
35 void applyUpdate(ValueType& currValue, [[maybe_unused]] uint64_t rowGroup) {
36 if (isConverged) {
37 if constexpr (Relative) {
38 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= storm::utility::abs<ValueType>(bound * currValue);
39 } else {
40 isConverged = storm::utility::abs<ValueType>(currValue - *best) <= bound;
41 }
42 // If we want to use the maximum number of iterations as the convergence criterion, we can use the following line
43 // isConverged = currentIteration >= maxIterations;
44 // In some preliminary experiments using only this criterion, performance was worse than with the check above.
45 }
46 currValue = std::move(*best);
47 }
48
50 ++currentIteration;
51 }
52
53 bool converged() const {
54 return isConverged;
55 }
56
57 bool constexpr abort() const {
58 return false;
59 }
60
61 private:
63 uint64_t currentIteration = 0;
64 uint64_t maxIterations = 0;
65 ValueType const precision;
66 ValueType const discountFactor;
67 ValueType const bound;
68 bool isConverged{true};
69};
70
71template<typename ValueType, bool TrivialRowGrouping>
74 : viOperator(viOperator) {
75 // Intentionally left empty
76}
77
78template<typename ValueType, bool TrivialRowGrouping>
79template<storm::OptimizationDirection Dir, bool Relative>
81 std::vector<ValueType>& operand, std::vector<ValueType> const& offsets, uint64_t& numIterations, ValueType const& precision,
82 ValueType const& discountFactor, ValueType const& maximalAbsoluteReward, std::function<SolverStatus(SolverStatus const&)> const& iterationCallback,
83 MultiplicationStyle mult) const {
84 DiscountedVIOperatorBackend<ValueType, Dir, Relative> backend{precision, discountFactor, maximalAbsoluteReward};
85 std::vector<ValueType>* operand1{&operand};
86 std::vector<ValueType>* operand2{&operand};
87 if (mult == MultiplicationStyle::Regular) {
88 operand2 = &viOperator->allocateAuxiliaryVector(operand.size());
89 }
90 bool resultInAuxVector{false};
92 while (status == SolverStatus::InProgress) {
93 ++numIterations;
94 if (viOperator->apply(*operand1, *operand2, offsets, backend)) {
96 } else if (iterationCallback) {
97 status = iterationCallback(status);
98 }
99 if (mult == MultiplicationStyle::Regular) {
100 std::swap(operand1, operand2);
101 resultInAuxVector = !resultInAuxVector;
102 }
103 }
104 if (mult == MultiplicationStyle::Regular) {
105 if (resultInAuxVector) {
106 STORM_LOG_ASSERT(&operand == operand2, "Unexpected operand address");
107 std::swap(*operand1, *operand2);
108 }
109 viOperator->freeAuxiliaryVector();
110 }
111 return status;
112}
113
114template<typename ValueType, bool TrivialRowGrouping>
116 std::vector<ValueType>& operand, std::vector<ValueType> const& offsets, uint64_t& numIterations, bool relative, ValueType const& precision,
117 ValueType const& discountFactor, ValueType const& maximalAbsoluteReward, std::optional<storm::OptimizationDirection> const& dir,
118 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback, MultiplicationStyle mult) const {
119 STORM_LOG_ASSERT(TrivialRowGrouping || dir.has_value(), "no optimization direction given!");
120 if (!dir.has_value() || maximize(*dir)) {
121 if (relative) {
122 return DiscountedVI<storm::OptimizationDirection::Maximize, true>(operand, offsets, numIterations, precision, discountFactor, maximalAbsoluteReward,
123 iterationCallback, mult);
124 } else {
125 return DiscountedVI<storm::OptimizationDirection::Maximize, false>(operand, offsets, numIterations, precision, discountFactor,
126 maximalAbsoluteReward, iterationCallback, mult);
127 }
128 } else {
129 if (relative) {
130 return DiscountedVI<storm::OptimizationDirection::Minimize, true>(operand, offsets, numIterations, precision, discountFactor, maximalAbsoluteReward,
131 iterationCallback, mult);
132 } else {
133 return DiscountedVI<storm::OptimizationDirection::Minimize, false>(operand, offsets, numIterations, precision, discountFactor,
134 maximalAbsoluteReward, iterationCallback, mult);
135 }
136 }
137}
138
139template<typename ValueType, bool TrivialRowGrouping>
141 std::vector<ValueType>& operand, std::vector<ValueType> const& offsets, bool relative, ValueType const& precision, ValueType const& discountFactor,
142 ValueType const& maximalAbsoluteReward, std::optional<storm::OptimizationDirection> const& dir,
143 std::function<SolverStatus(SolverStatus const&)> const& iterationCallback, MultiplicationStyle mult) const {
144 uint64_t numIterations = 0;
145 return DiscountedVI(operand, offsets, numIterations, relative, precision, discountFactor, maximalAbsoluteReward, dir, iterationCallback, mult);
146}
147
152
153} // namespace storm::solver::helper
void firstRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
DiscountedVIOperatorBackend(ValueType const &precision, ValueType const &discountFactor, ValueType const &maximalAbsoluteReward)
void applyUpdate(ValueType &currValue, uint64_t rowGroup)
void nextRow(ValueType &&value, uint64_t rowGroup, uint64_t row)
DiscountedValueIterationHelper(std::shared_ptr< ValueIterationOperator< ValueType, TrivialRowGrouping > > viOperator)
SolverStatus DiscountedVI(std::vector< ValueType > &operand, std::vector< ValueType > const &offsets, uint64_t &numIterations, ValueType const &precision, ValueType const &discountFactor, ValueType const &maximalAbsoluteReward, 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_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
bool constexpr maximize(OptimizationDirection d)
ValueType log(ValueType const &number)
LabParser.cpp.