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