Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MarkovAutomaton.cpp
Go to the documentation of this file.
2
12
13namespace storm {
14namespace models {
15namespace sparse {
16
17template<typename ValueType, typename RewardModelType>
19 storm::models::sparse::StateLabeling const& stateLabeling,
20 storm::storage::BitVector const& markovianStates,
21 std::unordered_map<std::string, RewardModelType> const& rewardModels)
23 storm::storage::sparse::ModelComponents<ValueType, RewardModelType>(transitionMatrix, stateLabeling, rewardModels, true, markovianStates)) {
24 // Intentionally left empty
25}
26
27template<typename ValueType, typename RewardModelType>
29 storm::models::sparse::StateLabeling&& stateLabeling, storm::storage::BitVector&& markovianStates,
30 std::unordered_map<std::string, RewardModelType>&& rewardModels)
31 : MarkovAutomaton<ValueType, RewardModelType>(storm::storage::sparse::ModelComponents<ValueType, RewardModelType>(
32 std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), true, std::move(markovianStates))) {
33 // Intentionally left empty
34}
35
36template<typename ValueType, typename RewardModelType>
38 : NondeterministicModel<ValueType, RewardModelType>(ModelType::MarkovAutomaton, components), markovianStates(components.markovianStates.get()) {
39 if (components.exitRates) {
40 exitRates = components.exitRates.get();
41 }
42
43 if (components.rateTransitions) {
44 this->turnRatesToProbabilities();
45 }
46 closed = this->checkIsClosed();
47}
48
49template<typename ValueType, typename RewardModelType>
52 markovianStates(std::move(components.markovianStates.get())) {
53 if (components.exitRates) {
54 exitRates = std::move(components.exitRates.get());
55 }
56
57 if (components.rateTransitions) {
58 this->turnRatesToProbabilities();
59 }
60 closed = this->checkIsClosed();
61}
62
63template<typename ValueType, typename RewardModelType>
65 return closed;
66}
67
68template<typename ValueType, typename RewardModelType>
70 if (!this->hasZenoCycle.is_initialized()) {
71 this->hasZenoCycle = this->checkContainsZenoCycle();
72 }
73 return this->hasZenoCycle.get();
74}
75
76template<typename ValueType, typename RewardModelType>
78 return isMarkovianState(state) && (this->getTransitionMatrix().getRowGroupSize(state) > 1);
79}
80
81template<typename ValueType, typename RewardModelType>
83 return this->markovianStates.get(state);
84}
85
86template<typename ValueType, typename RewardModelType>
88 return !this->markovianStates.get(state);
89}
90
91template<typename ValueType, typename RewardModelType>
92std::vector<ValueType> const& MarkovAutomaton<ValueType, RewardModelType>::getExitRates() const {
93 return this->exitRates;
94}
95
96template<typename ValueType, typename RewardModelType>
98 return this->exitRates;
99}
100
101template<typename ValueType, typename RewardModelType>
105
106template<typename ValueType, typename RewardModelType>
110
111template<typename ValueType, typename RewardModelType>
115
116template<typename ValueType, typename RewardModelType>
118 if (!closed) {
119 // Get the choices that we will keep
120 storm::storage::BitVector keptChoices(this->getNumberOfChoices(), true);
121 for (auto state : this->getMarkovianStates()) {
122 if (this->getTransitionMatrix().getRowGroupSize(state) > 1) {
123 // The state is hybrid, hence, we remove the first choice.
124 keptChoices.set(this->getTransitionMatrix().getRowGroupIndices()[state], false);
125 // Afterwards, the state will no longer be Markovian.
126 this->markovianStates.set(state, false);
127 exitRates[state] = storm::utility::zero<ValueType>();
128 }
129 }
130
131 if (!keptChoices.full()) {
132 *this = std::move(*storm::transformer::buildSubsystem(*this, storm::storage::BitVector(this->getNumberOfStates(), true), keptChoices, false)
133 .model->template as<MarkovAutomaton<ValueType, RewardModelType>>());
134 }
135
136 // Mark the automaton as closed.
137 closed = true;
138 }
139}
140
141template<typename ValueType, typename RewardModelType>
143 bool assertRates = (this->exitRates.size() == this->getNumberOfStates());
144 if (!assertRates) {
145 STORM_LOG_THROW(this->exitRates.empty(), storm::exceptions::InvalidArgumentException, "The specified exit rate vector has an unexpected size.");
146 this->exitRates.reserve(this->getNumberOfStates());
147 }
148
149 for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
150 uint_fast64_t row = this->getTransitionMatrix().getRowGroupIndices()[state];
151 if (this->markovianStates.get(state)) {
152 if (assertRates) {
153 STORM_LOG_THROW(this->exitRates[state] == this->getTransitionMatrix().getRowSum(row), storm::exceptions::InvalidArgumentException,
154 "The specified exit rate is inconsistent with the rate matrix. Difference is "
155 << (this->exitRates[state] - this->getTransitionMatrix().getRowSum(row)) << ".");
156 } else {
157 this->exitRates.push_back(this->getTransitionMatrix().getRowSum(row));
158 }
159 for (auto& transition : this->getTransitionMatrix().getRow(row)) {
160 transition.setValue(transition.getValue() / this->exitRates[state]);
161 }
162 ++row;
163 } else {
164 if (assertRates) {
165 STORM_LOG_THROW(storm::utility::isZero(this->exitRates[state]), storm::exceptions::InvalidArgumentException,
166 "The specified exit rate for (non-Markovian) choice should be 0.");
167 } else {
168 this->exitRates.push_back(storm::utility::zero<ValueType>());
169 }
170 }
171 }
172}
173
174template<typename ValueType, typename RewardModelType>
176 return isClosed() && markovianStates.full();
177}
178
179template<typename ValueType, typename RewardModelType>
181 // Check every state
182 for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) {
183 STORM_LOG_ASSERT(!isHybridState(state), "State is hybrid.");
184 if (this->getNumberOfChoices(state) > 1) {
185 // Non-deterministic choice present
186 STORM_LOG_ASSERT(isProbabilisticState(state), "State is not probabilistic.");
187 return false;
188 }
189 }
190 return true;
191}
192
193template<typename ValueType, typename RewardModelType>
195 for (auto state : markovianStates) {
196 if (this->getTransitionMatrix().getRowGroupSize(state) > 1) {
197 return false;
198 }
199 }
200 return true;
201}
202
203template<typename ValueType, typename RewardModelType>
204std::shared_ptr<storm::models::sparse::Ctmc<ValueType, RewardModelType>> MarkovAutomaton<ValueType, RewardModelType>::convertToCtmc() const {
205 STORM_LOG_THROW(isConvertibleToCtmc(), storm::exceptions::InvalidArgumentException, "MA cannot be converted to CTMC.");
206
207 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components(this->getTransitionMatrix(), this->getStateLabeling(),
208 this->getRewardModels(), false);
209 components.transitionMatrix.makeRowGroupingTrivial();
210 components.exitRates = this->getExitRates();
211 if (this->hasChoiceLabeling()) {
212 components.choiceLabeling = this->getChoiceLabeling();
213 }
214 if (this->hasStateValuations()) {
215 components.stateValuations = this->getStateValuations();
216 }
217 if (this->hasChoiceOrigins()) {
218 components.choiceOrigins = this->getChoiceOrigins();
219 }
220 return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(components));
221}
222
223template<typename ValueType, typename RewardModelType>
225 if (isClosed() && markovianStates.empty()) {
226 return true;
227 }
228 storm::storage::BitVector statesWithZenoCycle =
229 storm::utility::graph::performProb0E(*this, this->getBackwardTransitions(), ~markovianStates, markovianStates);
230 return !statesWithZenoCycle.empty();
231}
232
233template<typename ValueType, typename RewardModelType>
235 this->printModelInformationHeaderToStream(out);
236 out << "Choices: \t" << this->getNumberOfChoices() << '\n';
237 out << "Markovian St.: \t" << this->getMarkovianStates().getNumberOfSetBits() << '\n';
238 out << "Max. Rate: \t";
239 if (this->getMarkovianStates().empty()) {
240 out << "None";
241 } else {
242 out << this->getMaximalExitRate();
243 }
244 out << '\n';
245 this->printModelInformationFooterToStream(out);
246}
247
248template class MarkovAutomaton<double>;
253} // namespace sparse
254} // namespace models
255} // 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:966
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:572
bool isZero(ValueType const &a)
Definition constants.cpp:38
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