Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MarkovAutomaton.cpp
Go to the documentation of this file.
2
11#include "storm/utility/graph.h"
14
15namespace storm {
16namespace models {
17namespace sparse {
18
19template<typename ValueType, typename RewardModelType>
21 storm::models::sparse::StateLabeling const& stateLabeling,
22 storm::storage::BitVector const& markovianStates,
23 std::unordered_map<std::string, RewardModelType> const& rewardModels)
25 storm::storage::sparse::ModelComponents<ValueType, RewardModelType>(transitionMatrix, stateLabeling, rewardModels, true, markovianStates)) {
26 // Intentionally left empty
27}
28
29template<typename ValueType, typename RewardModelType>
31 storm::models::sparse::StateLabeling&& stateLabeling, storm::storage::BitVector&& markovianStates,
32 std::unordered_map<std::string, RewardModelType>&& rewardModels)
33 : MarkovAutomaton<ValueType, RewardModelType>(storm::storage::sparse::ModelComponents<ValueType, RewardModelType>(
34 std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), true, std::move(markovianStates))) {
35 // Intentionally left empty
36}
37
38template<typename ValueType, typename RewardModelType>
40 : NondeterministicModel<ValueType, RewardModelType>(ModelType::MarkovAutomaton, components), markovianStates(components.markovianStates.get()) {
41 if (components.exitRates) {
42 exitRates = components.exitRates.get();
43 }
44
45 if (components.rateTransitions) {
46 this->turnRatesToProbabilities();
47 }
48 closed = this->checkIsClosed();
49}
50
51template<typename ValueType, typename RewardModelType>
54 markovianStates(std::move(components.markovianStates.get())) {
55 if (components.exitRates) {
56 exitRates = std::move(components.exitRates.get());
57 }
58
59 if (components.rateTransitions) {
60 this->turnRatesToProbabilities();
61 }
62 closed = this->checkIsClosed();
63}
64
65template<typename ValueType, typename RewardModelType>
67 return closed;
68}
69
70template<typename ValueType, typename RewardModelType>
72 if (!this->hasZenoCycle.is_initialized()) {
73 this->hasZenoCycle = this->checkContainsZenoCycle();
74 }
75 return this->hasZenoCycle.get();
76}
77
78template<typename ValueType, typename RewardModelType>
80 return isMarkovianState(state) && (this->getTransitionMatrix().getRowGroupSize(state) > 1);
81}
82
83template<typename ValueType, typename RewardModelType>
85 return this->markovianStates.get(state);
86}
87
88template<typename ValueType, typename RewardModelType>
90 return !this->markovianStates.get(state);
91}
92
93template<typename ValueType, typename RewardModelType>
94std::vector<ValueType> const& MarkovAutomaton<ValueType, RewardModelType>::getExitRates() const {
95 return this->exitRates;
96}
97
98template<typename ValueType, typename RewardModelType>
100 return this->exitRates;
101}
102
103template<typename ValueType, typename RewardModelType>
107
108template<typename ValueType, typename RewardModelType>
112
113template<typename ValueType, typename RewardModelType>
117
118template<typename ValueType, typename RewardModelType>
120 if (!closed) {
121 // Get the choices that we will keep
122 storm::storage::BitVector keptChoices(this->getNumberOfChoices(), true);
123 for (auto state : this->getMarkovianStates()) {
124 if (this->getTransitionMatrix().getRowGroupSize(state) > 1) {
125 // The state is hybrid, hence, we remove the first choice.
126 keptChoices.set(this->getTransitionMatrix().getRowGroupIndices()[state], false);
127 // Afterwards, the state will no longer be Markovian.
128 this->markovianStates.set(state, false);
129 exitRates[state] = storm::utility::zero<ValueType>();
130 }
131 }
132
133 if (!keptChoices.full()) {
134 *this = std::move(*storm::transformer::buildSubsystem(*this, storm::storage::BitVector(this->getNumberOfStates(), true), keptChoices, false)
135 .model->template as<MarkovAutomaton<ValueType, RewardModelType>>());
136 }
137
138 // Mark the automaton as closed.
139 closed = true;
140 }
141}
142
143template<typename ValueType, typename RewardModelType>
145 bool assertRates = (this->exitRates.size() == this->getNumberOfStates());
146 if (!assertRates) {
147 STORM_LOG_THROW(this->exitRates.empty(), storm::exceptions::InvalidArgumentException, "The specified exit rate vector has an unexpected size.");
148 this->exitRates.reserve(this->getNumberOfStates());
149 }
150
151 for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
152 uint_fast64_t row = this->getTransitionMatrix().getRowGroupIndices()[state];
153 if (this->markovianStates.get(state)) {
154 if (assertRates) {
155 STORM_LOG_THROW(this->exitRates[state] == this->getTransitionMatrix().getRowSum(row), storm::exceptions::InvalidArgumentException,
156 "The specified exit rate is inconsistent with the rate matrix. Difference is "
157 << (this->exitRates[state] - this->getTransitionMatrix().getRowSum(row)) << ".");
158 } else {
159 this->exitRates.push_back(this->getTransitionMatrix().getRowSum(row));
160 }
161 for (auto& transition : this->getTransitionMatrix().getRow(row)) {
162 transition.setValue(transition.getValue() / this->exitRates[state]);
163 }
164 ++row;
165 } else {
166 if (assertRates) {
167 STORM_LOG_THROW(storm::utility::isZero(this->exitRates[state]), storm::exceptions::InvalidArgumentException,
168 "The specified exit rate for (non-Markovian) choice should be 0.");
169 } else {
170 this->exitRates.push_back(storm::utility::zero<ValueType>());
171 }
172 }
173 }
174}
175
176template<typename ValueType, typename RewardModelType>
178 return isClosed() && markovianStates.full();
179}
180
181template<typename ValueType, typename RewardModelType>
183 // Check every state
184 for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
185 STORM_LOG_ASSERT(!isHybridState(state), "State is hybrid.");
186 if (this->getNumberOfChoices(state) > 1) {
187 // Non-deterministic choice present
188 STORM_LOG_ASSERT(isProbabilisticState(state), "State is not probabilistic.");
189 return false;
190 }
191 }
192 return true;
193}
194
195template<typename ValueType, typename RewardModelType>
197 for (auto state : markovianStates) {
198 if (this->getTransitionMatrix().getRowGroupSize(state) > 1) {
199 return false;
200 }
201 }
202 return true;
203}
204
205template<typename ValueType, typename RewardModelType>
206std::shared_ptr<storm::models::sparse::Ctmc<ValueType, RewardModelType>> MarkovAutomaton<ValueType, RewardModelType>::convertToCtmc() const {
207 STORM_LOG_THROW(isConvertibleToCtmc(), storm::exceptions::InvalidArgumentException, "MA cannot be converted to CTMC.");
208
209 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components(this->getTransitionMatrix(), this->getStateLabeling(),
210 this->getRewardModels(), false);
211 components.transitionMatrix.makeRowGroupingTrivial();
212 components.exitRates = this->getExitRates();
213 if (this->hasChoiceLabeling()) {
214 components.choiceLabeling = this->getChoiceLabeling();
215 }
216 if (this->hasStateValuations()) {
217 components.stateValuations = this->getStateValuations();
218 }
219 if (this->hasChoiceOrigins()) {
220 components.choiceOrigins = this->getChoiceOrigins();
221 }
222 return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(components));
223}
224
225template<typename ValueType, typename RewardModelType>
227 if (isClosed() && markovianStates.empty()) {
228 return true;
229 }
230 storm::storage::BitVector statesWithZenoCycle =
231 storm::utility::graph::performProb0E(*this, this->getBackwardTransitions(), ~markovianStates, markovianStates);
232 return !statesWithZenoCycle.empty();
233}
234
235template<typename ValueType, typename RewardModelType>
237 this->printModelInformationHeaderToStream(out);
238 out << "Choices: \t" << this->getNumberOfChoices() << '\n';
239 out << "Markovian St.: \t" << this->getMarkovianStates().getNumberOfSetBits() << '\n';
240 out << "Max. Rate: \t";
241 if (this->getMarkovianStates().empty()) {
242 out << "None";
243 } else {
244 out << this->getMaximalExitRate();
245 }
246 out << '\n';
247 this->printModelInformationFooterToStream(out);
248}
249
250template class MarkovAutomaton<double>;
255} // namespace sparse
256} // namespace models
257} // namespace storm
This class represents a Markov automaton.
void close()
Closes the Markov automaton.
MarkovAutomaton(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::models::sparse::StateLabeling const &stateLabeling, storm::storage::BitVector const &markovianStates, std::unordered_map< std::string, RewardModelType > const &rewardModels=std::unordered_map< std::string, RewardModelType >())
Constructs a model from the given data.
bool containsZenoCycle() const
Retrieves whether the Markov automaton contains Zeno cycles.
bool isClosed() const
Retrieves whether the Markov automaton is closed.
std::shared_ptr< storm::models::sparse::Ctmc< ValueType, RewardModelType > > convertToCtmc() const
Convert the MA to a CTMC.
bool isProbabilisticState(storm::storage::sparse::state_type state) const
Retrieves whether the given state is a probabilistic state.
bool isMarkovianState(storm::storage::sparse::state_type state) const
Retrieves whether the given state is a Markovian state.
bool isConvertibleToCtmc() const
Determines whether the Markov automaton can be converted to a CTMC without changing any measures.
virtual void printModelInformationToStream(std::ostream &out) const override
Prints information about the model to the specified stream.
std::vector< ValueType > const & getExitRates() const
Retrieves the vector representing the exit rates of the states.
storm::storage::BitVector const & getMarkovianStates() const
Retrieves the set of Markovian states of the model.
ValueType const & getExitRate(storm::storage::sparse::state_type state) const
Retrieves the exit rate of the given state.
ValueType getMaximalExitRate() const
Retrieves the maximal exit rate over all states of the model.
bool isHybridState(storm::storage::sparse::state_type state) const
Retrieves whether the given state is a hybrid state, i.e.
CRewardModelType RewardModelType
Definition Model.h:35
The base class of sparse nondeterministic models.
This class manages the labeling of the state space with a number of (atomic) labels.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
bool full() const
Retrieves whether all bits are set in this bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SubsystemBuilderReturnType< ValueType, RewardModelType > buildSubsystem(storm::models::sparse::Model< ValueType, RewardModelType > const &originalModel, storm::storage::BitVector const &subsystemStates, storm::storage::BitVector const &subsystemActions, bool keepUnreachableStates, SubsystemBuilderOptions options)
storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 of satisfying phi until psi under at least one po...
Definition graph.cpp:960
VT max_if(std::vector< VT > const &values, storm::storage::BitVector const &filter)
Computes the maximum of the entries from the values that are selected by the (non-empty) filter.
Definition vector.h:568
bool isZero(ValueType const &a)
Definition constants.cpp:39
std::optional< storm::storage::sparse::StateValuations > stateValuations
storm::storage::SparseMatrix< ValueType > transitionMatrix
std::optional< std::shared_ptr< storm::storage::sparse::ChoiceOrigins > > choiceOrigins
std::optional< storm::models::sparse::ChoiceLabeling > choiceLabeling
boost::optional< std::vector< ValueType > > exitRates