Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseInfiniteHorizonHelper.cpp
Go to the documentation of this file.
2
5
8
12
17
23
26
28
29namespace storm {
30namespace modelchecker {
31namespace helper {
32
33template<typename ValueType, bool Nondeterministic>
35 : _transitionMatrix(transitionMatrix),
36 _markovianStates(nullptr),
37 _exitRates(nullptr),
38 _backwardTransitions(nullptr),
39 _longRunComponentDecomposition(nullptr) {
40 // Intentionally left empty.
41}
42
43template<typename ValueType, bool Nondeterministic>
45 storm::storage::BitVector const& markovianStates,
46 std::vector<ValueType> const& exitRates)
47 : _transitionMatrix(transitionMatrix),
48 _markovianStates(&markovianStates),
49 _exitRates(&exitRates),
50 _backwardTransitions(nullptr),
51 _longRunComponentDecomposition(nullptr) {
52 // Intentionally left empty.
53}
54
55template<typename ValueType, bool Nondeterministic>
57 std::vector<ValueType> const& exitRates)
58 : _transitionMatrix(transitionMatrix),
59 _markovianStates(nullptr),
60 _exitRates(&exitRates),
61 _backwardTransitions(nullptr),
62 _longRunComponentDecomposition(nullptr) {
63 // Intentionally left empty.
64}
65
66template<typename ValueType, bool Nondeterministic>
68 STORM_LOG_WARN_COND(_backwardTransitions == nullptr, "Backwards transitions were provided but they were already computed or provided before.");
69 _backwardTransitions = &backwardTransitions;
70}
71
72template<typename ValueType, bool Nondeterministic>
75 STORM_LOG_WARN_COND(_longRunComponentDecomposition == nullptr,
76 "Long Run Component Decomposition was provided but it was already computed or provided before.");
77 _longRunComponentDecomposition = &decomposition;
78}
79
80template<typename ValueType, bool Nondeterministic>
82 Environment const& env, storm::storage::BitVector const& psiStates) {
83 return computeLongRunAverageValues(
84 env, [&psiStates](uint64_t stateIndex) { return psiStates.get(stateIndex) ? storm::utility::one<ValueType>() : storm::utility::zero<ValueType>(); },
85 [](uint64_t) { return storm::utility::zero<ValueType>(); });
86}
87
88template<typename ValueType, bool Nondeterministic>
91 ValueGetter stateRewardsGetter;
92 if (rewardModel.hasStateRewards()) {
93 stateRewardsGetter = [&rewardModel](uint64_t stateIndex) { return rewardModel.getStateReward(stateIndex); };
94 } else {
95 stateRewardsGetter = [](uint64_t) { return storm::utility::zero<ValueType>(); };
96 }
97 ValueGetter actionRewardsGetter;
98 if (rewardModel.hasStateActionRewards() || rewardModel.hasTransitionRewards()) {
99 if (rewardModel.hasTransitionRewards()) {
100 actionRewardsGetter = [&](uint64_t globalChoiceIndex) {
101 return rewardModel.getStateActionAndTransitionReward(globalChoiceIndex, this->_transitionMatrix);
102 };
103 } else {
104 actionRewardsGetter = [&](uint64_t globalChoiceIndex) { return rewardModel.getStateActionReward(globalChoiceIndex); };
105 }
106 } else {
107 actionRewardsGetter = [](uint64_t) { return storm::utility::zero<ValueType>(); };
108 }
109
110 return computeLongRunAverageValues(env, stateRewardsGetter, actionRewardsGetter);
111}
112
113template<typename ValueType, bool Nondeterministic>
115 std::vector<ValueType> const* stateValues,
116 std::vector<ValueType> const* actionValues) {
117 ValueGetter stateValuesGetter;
118 if (stateValues) {
119 stateValuesGetter = [&stateValues](uint64_t stateIndex) { return (*stateValues)[stateIndex]; };
120 } else {
121 stateValuesGetter = [](uint64_t) { return storm::utility::zero<ValueType>(); };
122 }
123 ValueGetter actionValuesGetter;
124 if (actionValues) {
125 actionValuesGetter = [&actionValues](uint64_t globalChoiceIndex) { return (*actionValues)[globalChoiceIndex]; };
126 } else {
127 actionValuesGetter = [](uint64_t) { return storm::utility::zero<ValueType>(); };
128 }
129
130 return computeLongRunAverageValues(env, stateValuesGetter, actionValuesGetter);
131}
132
133template<typename ValueType, bool Nondeterministic>
135 ValueGetter const& stateRewardsGetter,
136 ValueGetter const& actionRewardsGetter) {
137 // We will compute the long run average value for each MEC individually and then set-up an Equation system to compute the value also at non-mec states.
138 // For a description of this approach see, e.g., Guck et al.: Modelling and Analysis of Markov Reward Automata (ATVA'14),
139 // https://doi.org/10.1007/978-3-319-11936-6_13
140
141 // Prepare an environment for the underlying solvers.
142 auto underlyingSolverEnvironment = env;
143 if (env.solver().isForceSoundness()) {
144 // For sound computations, the error in the MECS plus the error in the remaining system should not exceed the user defined precsion.
145 storm::RationalNumber newPrecision = env.solver().lra().getPrecision() / storm::utility::convertNumber<storm::RationalNumber>(2);
146 underlyingSolverEnvironment.solver().minMax().setPrecision(newPrecision);
147 underlyingSolverEnvironment.solver().minMax().setRelativeTerminationCriterion(env.solver().lra().getRelativeTerminationCriterion());
148 underlyingSolverEnvironment.solver().setLinearEquationSolverPrecision(newPrecision, env.solver().lra().getRelativeTerminationCriterion());
149 underlyingSolverEnvironment.solver().lra().setPrecision(newPrecision);
150 }
151
152 // If requested, allocate memory for the choices made
153 if (Nondeterministic && this->isProduceSchedulerSet()) {
154 if (!_producedOptimalChoices.is_initialized()) {
155 _producedOptimalChoices.emplace();
156 }
157 _producedOptimalChoices->resize(_transitionMatrix.getRowGroupCount());
158 }
159 STORM_LOG_ASSERT(Nondeterministic || !this->isProduceSchedulerSet(), "Scheduler production enabled for deterministic model.");
160
161 // Decompose the model to their bottom components (MECS or BSCCS)
162 createDecomposition();
163
164 // Compute the long-run average for all components in isolation.
165 // Set up some logging
166 std::string const componentString = (Nondeterministic ? std::string("Maximal end") : std::string("Bottom strongly connected")) +
167 (_longRunComponentDecomposition->size() == 1 ? std::string(" component") : std::string(" components"));
168 storm::utility::ProgressMeasurement progress(componentString);
169 progress.setMaxCount(_longRunComponentDecomposition->size());
170 progress.startNewMeasurement(0);
171 STORM_LOG_INFO("Computing long run average values for " << _longRunComponentDecomposition->size() << " " << componentString << " individually...");
172 std::vector<ValueType> componentLraValues;
173 componentLraValues.reserve(_longRunComponentDecomposition->size());
174 for (auto const& c : *_longRunComponentDecomposition) {
175 componentLraValues.push_back(computeLraForComponent(underlyingSolverEnvironment, stateRewardsGetter, actionRewardsGetter, c));
176 progress.updateProgress(componentLraValues.size());
177 }
178
179 // Solve the resulting SSP where end components are collapsed into single auxiliary states
180 STORM_LOG_INFO("Solving stochastic shortest path problem.");
181 return buildAndSolveSsp(underlyingSolverEnvironment, componentLraValues);
182}
183
184template<typename ValueType, bool Nondeterministic>
186 STORM_LOG_ASSERT((_markovianStates == nullptr) || (_exitRates != nullptr), "Inconsistent information given: Have Markovian states but no exit rates.");
187 return _exitRates != nullptr;
188}
189
190template<typename ValueType, bool Nondeterministic>
192 if (this->_backwardTransitions == nullptr) {
193 this->_computedBackwardTransitions =
194 std::make_unique<storm::storage::SparseMatrix<ValueType>>(this->_transitionMatrix.transpose(true, false)); // will drop zeroes
195 this->_backwardTransitions = this->_computedBackwardTransitions.get();
196 }
197}
198
201
205
206} // namespace helper
207} // namespace modelchecker
208} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
LongRunAverageSolverEnvironment & lra()
Helper class for model checking queries that depend on the long run behavior of the (nondeterministic...
void provideBackwardTransitions(storm::storage::SparseMatrix< ValueType > const &backwardsTransitions)
Provides backward transitions that can be used during the computation.
std::vector< ValueType > computeLongRunAverageRewards(Environment const &env, storm::models::sparse::StandardRewardModel< ValueType > const &rewardModel)
Computes the long run average rewards, i.e., the average reward collected per time unit.
std::function< ValueType(uint64_t)> ValueGetter
Function mapping from indices to values.
void provideLongRunComponentDecomposition(storm::storage::Decomposition< LongRunComponentType > const &decomposition)
Provides the decomposition into long run components (BSCCs/MECs) that can be used during the computat...
SparseInfiniteHorizonHelper(storm::storage::SparseMatrix< ValueType > const &transitionMatrix)
Initializes the helper for a discrete time (i.e.
std::vector< ValueType > computeLongRunAverageProbabilities(Environment const &env, storm::storage::BitVector const &psiStates)
Computes the long run average probabilities, i.e., the fraction of the time we are in a psiState.
std::vector< ValueType > computeLongRunAverageValues(Environment const &env, std::vector< ValueType > const *stateValues=nullptr, std::vector< ValueType > const *actionValues=nullptr)
Computes the long run average value given the provided state and action-based rewards.
bool hasTransitionRewards() const
Retrieves whether the reward model has transition rewards.
ValueType const & getStateReward(uint_fast64_t state) const
ValueType const & getStateActionReward(uint_fast64_t choiceIndex) const
Retrieves the state-action reward for the given choice.
ValueType getStateActionAndTransitionReward(uint_fast64_t choiceIndex, storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix) const
bool hasStateRewards() const
Retrieves whether the reward model has state rewards.
bool hasStateActionRewards() const
Retrieves whether the reward model has state-action rewards.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
This class represents the decomposition of a model into blocks which are of the template type.
A class that holds a possibly non-square matrix in the compressed row storage format.
A class that provides convenience operations to display run times.
bool updateProgress(uint64_t count)
Updates the progress to the current count and prints it if the delay passed.
void setMaxCount(uint64_t maxCount)
Sets the maximal possible count.
void startNewMeasurement(uint64_t startCount)
Starts a new measurement, dropping all progress information collected so far.
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
LabParser.cpp.
Definition cli.cpp:18