Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Model.cpp
Go to the documentation of this file.
2
3#include <boost/algorithm/string/join.hpp>
4#include <boost/algorithm/string/split.hpp>
5
11#include "storm/io/export.h"
19
20namespace storm {
21namespace models {
22namespace sparse {
23
24template<typename ValueType, typename RewardModelType>
26 : storm::models::Model<ValueType>(modelType),
27 transitionMatrix(components.transitionMatrix),
28 stateLabeling(components.stateLabeling),
29 rewardModels(components.rewardModels),
30 choiceLabeling(components.choiceLabeling),
31 stateValuations(components.stateValuations),
32 choiceOrigins(components.choiceOrigins) {
33 assertValidityOfComponents(components);
34}
35
36template<typename ValueType, typename RewardModelType>
38 : storm::models::Model<ValueType>(modelType),
39 transitionMatrix(std::move(components.transitionMatrix)),
40 stateLabeling(std::move(components.stateLabeling)),
41 rewardModels(std::move(components.rewardModels)),
42 choiceLabeling(std::move(components.choiceLabeling)),
43 stateValuations(std::move(components.stateValuations)),
44 choiceOrigins(std::move(components.choiceOrigins)) {
45 assertValidityOfComponents(components);
46}
48template<typename ValueType, typename RewardModelType>
51 // More costly checks are only asserted to avoid doing them in release mode.
52
53 uint_fast64_t stateCount = this->getNumberOfStates();
54 uint_fast64_t choiceCount = this->getTransitionMatrix().getRowCount();
55
56 // general components for all model types.
57 STORM_LOG_THROW(this->getTransitionMatrix().getColumnCount() == stateCount, storm::exceptions::IllegalArgumentException,
58 "Invalid column count of transition matrix.");
59 STORM_LOG_ASSERT(components.rateTransitions || this->hasParameters() || this->hasUncertainty() || this->getTransitionMatrix().isProbabilistic(),
60 "The matrix is not probabilistic.");
61 if (this->hasUncertainty()) {
62 STORM_LOG_ASSERT(this->getTransitionMatrix().hasOnlyPositiveEntries(), "Not all entries are (strictly) positive.");
63 }
64 STORM_LOG_THROW(this->getStateLabeling().getNumberOfItems() == stateCount, storm::exceptions::IllegalArgumentException,
65 "Invalid item count (" << this->getStateLabeling().getNumberOfItems() << ") of state labeling (states: " << stateCount << ").");
66 for (auto const& rewardModel : this->getRewardModels()) {
67 STORM_LOG_THROW(!rewardModel.second.hasStateRewards() || rewardModel.second.getStateRewardVector().size() == stateCount,
68 storm::exceptions::IllegalArgumentException,
69 "Invalid size (" << rewardModel.second.getStateRewardVector().size() << ") of state reward vector (states:" << stateCount << ").");
71 !rewardModel.second.hasStateActionRewards() || rewardModel.second.getStateActionRewardVector().size() == choiceCount,
72 storm::exceptions::IllegalArgumentException,
73 "Invalid size (" << rewardModel.second.getStateActionRewardVector().size() << ") of state action reward vector (expected:" << choiceCount << ").");
75 !rewardModel.second.hasTransitionRewards() || rewardModel.second.getTransitionRewardMatrix().isSubmatrixOf(this->getTransitionMatrix()),
76 "The transition reward matrix is not a submatrix of the transition matrix, i.e. there are rewards for transitions that do not exist.");
77 }
79 !this->hasChoiceLabeling() || this->getChoiceLabeling().getNumberOfItems() == choiceCount, storm::exceptions::IllegalArgumentException,
80 "Invalid choice count of choice labeling (choices: " << choiceCount << " vs. labeling:" << this->getChoiceLabeling().getNumberOfItems() << ").");
82 !this->hasStateValuations() || this->getStateValuations().getNumberOfStates() == stateCount, storm::exceptions::IllegalArgumentException,
83 "Invalid state count for state valuations (states: " << stateCount << " vs. valuations:" << this->getStateValuations().getNumberOfStates() << ").");
85 !this->hasChoiceOrigins() || this->getChoiceOrigins()->getNumberOfChoices() == choiceCount, storm::exceptions::IllegalArgumentException,
86 "Invalid choice count for choice origins. (choices: " << choiceCount << " vs. origins:" << this->getChoiceOrigins()->getNumberOfChoices() << ").");
87
88 // Branch on type of nondeterminism
89 if (this->isOfType(ModelType::Dtmc) || this->isOfType(ModelType::Ctmc)) {
90 STORM_LOG_THROW(this->getTransitionMatrix().hasTrivialRowGrouping(), storm::exceptions::IllegalArgumentException,
91 "Can not create deterministic model: Transition matrix has non-trivial row grouping.");
92 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getRowCount(), storm::exceptions::IllegalArgumentException,
93 "Can not create deterministic model: Number of rows of transition matrix does not match state count.");
94 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getColumnCount(), storm::exceptions::IllegalArgumentException,
95 "Can not create deterministic model: Number of columns of transition matrix does not match state count.");
96 STORM_LOG_ERROR_COND(!components.player1Matrix.is_initialized(), "Player 1 matrix given for a model that is no stochastic game (will be ignored).");
97 } else if (this->isOfType(ModelType::Mdp) || this->isOfType(ModelType::MarkovAutomaton) || this->isOfType(ModelType::Pomdp) ||
98 this->isOfType(ModelType::Smg)) {
99 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getRowGroupCount(), storm::exceptions::IllegalArgumentException,
100 "Can not create nondeterministic model: Number of row groups ("
101 << this->getTransitionMatrix().getRowGroupCount() << ") of transition matrix does not match state count (" << stateCount << ").");
102 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getColumnCount(), storm::exceptions::IllegalArgumentException,
103 "Can not create nondeterministic model: Number of columns of transition matrix does not match state count.");
104 STORM_LOG_ERROR_COND(!components.player1Matrix.is_initialized(), "Player 1 matrix given for a model that is no stochastic game (will be ignored).");
105 } else if (this->isOfType(ModelType::S2pg)) {
106 STORM_LOG_THROW(components.player1Matrix.is_initialized(), storm::exceptions::IllegalArgumentException,
107 "No player 1 matrix given for stochastic game.");
108 STORM_LOG_ASSERT(components.player1Matrix->isProbabilistic(),
109 "Can not create stochastic game: There is a row in the p1 matrix with not exactly one entry.");
110 STORM_LOG_THROW(stateCount == components.player1Matrix->getRowGroupCount(), storm::exceptions::IllegalArgumentException,
111 "Can not create stochastic game: Number of row groups of p1 matrix does not match state count.");
112 STORM_LOG_THROW(this->getTransitionMatrix().getRowGroupCount() == components.player1Matrix->getColumnCount(),
113 storm::exceptions::IllegalArgumentException,
114 "Can not create stochastic game: Number of row groups of p2 matrix does not match column count of p1 matrix.");
115 } else {
116 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Invalid model type.");
117 }
118
119 // Branch on continuous/discrete timing
120 if (this->isOfType(ModelType::Ctmc) || this->isOfType(ModelType::MarkovAutomaton)) {
121 STORM_LOG_THROW(components.rateTransitions || components.exitRates.is_initialized(), storm::exceptions::IllegalArgumentException,
122 "Can not create continuous time model: no rates are given.");
123 STORM_LOG_THROW(!components.exitRates.is_initialized() || components.exitRates->size() == stateCount, storm::exceptions::IllegalArgumentException,
124 "Size of exit rate vector does not match state count.");
125 STORM_LOG_THROW(this->isOfType(ModelType::Ctmc) || components.markovianStates.is_initialized(), storm::exceptions::IllegalArgumentException,
126 "Can not create Markov Automaton: no Markovian states given.");
127 } else {
128 STORM_LOG_WARN_COND(!components.rateTransitions && !components.exitRates.is_initialized(),
129 "Rates specified for discrete-time model. The rates will be ignored.");
131 STORM_LOG_WARN_COND(this->isOfType(ModelType::MarkovAutomaton) || !components.markovianStates.is_initialized(),
132 "Markovian states given for a model that is not a Markov automaton (will be ignored).");
133
134 // Treat stochastic multiplayer games
135 if (this->isOfType(ModelType::Smg)) {
136 STORM_LOG_THROW(components.statePlayerIndications.is_initialized(), storm::exceptions::IllegalArgumentException,
137 "Can not create stochastic multiplayer game: Missing player indications.");
138 // playerNameToIndexMap is optional.
140 stateCount == components.statePlayerIndications->size(), storm::exceptions::IllegalArgumentException,
141 "Size of state player indications (" << components.statePlayerIndications->size() << ") of SMG does not match state count (" << stateCount << ").");
142 } else {
143 STORM_LOG_WARN_COND(!components.statePlayerIndications.is_initialized(),
144 "statePlayerIndications given for a model that is not a stochastic multiplayer game (will be ignored).");
145 STORM_LOG_WARN_COND(!components.playerNameToIndexMap.is_initialized(),
146 "playerNameToIndexMap given for a model that is not a stochastic multiplayer game (will be ignored).");
147 }
148}
149
150template<typename ValueType, typename RewardModelType>
154
155template<typename ValueType, typename RewardModelType>
157 return this->getTransitionMatrix().getColumnCount();
159
160template<typename ValueType, typename RewardModelType>
162 return this->getTransitionMatrix().getNonzeroEntryCount();
163}
164
165template<typename ValueType, typename RewardModelType>
167 return this->getTransitionMatrix().getRowCount();
168}
169
170template<typename ValueType, typename RewardModelType>
172 return this->getStates("init");
173}
174
175template<typename ValueType, typename RewardModelType>
177 return this->getStateLabeling().setStates("init", states);
178}
180template<typename ValueType, typename RewardModelType>
182 return stateLabeling.getStates(label);
183}
184
185template<typename ValueType, typename RewardModelType>
186bool Model<ValueType, RewardModelType>::hasLabel(std::string const& label) const {
187 return stateLabeling.containsLabel(label);
188}
189
190template<typename ValueType, typename RewardModelType>
194
195template<typename ValueType, typename RewardModelType>
199
200template<typename ValueType, typename RewardModelType>
201bool Model<ValueType, RewardModelType>::hasRewardModel(std::string const& rewardModelName) const {
202 return this->rewardModels.find(rewardModelName) != this->rewardModels.end();
203}
204
205template<typename ValueType, typename RewardModelType>
207 STORM_LOG_ASSERT(this->hasRewardModel(rewardModelName), "Model has no reward model.");
208 return this->rewardModels.find(rewardModelName)->second;
209}
210
211template<typename ValueType, typename RewardModelType>
212RewardModelType const& Model<ValueType, RewardModelType>::getRewardModel(std::string const& rewardModelName) const {
213 auto it = this->rewardModels.find(rewardModelName);
214 if (it == this->rewardModels.end()) {
215 if (rewardModelName.empty()) {
216 if (this->hasUniqueRewardModel()) {
217 return this->getUniqueRewardModel();
218 } else {
219 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException,
220 "Unable to refer to default reward model, because there is no default model or it is not unique.");
221 }
222 } else {
223 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "The requested reward model '" << rewardModelName << "' does not exist.");
224 }
226 return it->second;
227}
228
229template<typename ValueType, typename RewardModelType>
231 auto it = this->rewardModels.find(rewardModelName);
232 if (it == this->rewardModels.end()) {
233 if (rewardModelName.empty()) {
234 if (this->hasUniqueRewardModel()) {
235 return this->getUniqueRewardModel();
236 } else {
237 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException,
238 "Unable to refer to default reward model, because there is no default model or it is not unique.");
240 } else {
241 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "The requested reward model '" << rewardModelName << "' does not exist.");
242 }
243 }
244 return it->second;
245}
246
247template<typename ValueType, typename RewardModelType>
248void Model<ValueType, RewardModelType>::addRewardModel(std::string const& rewardModelName, RewardModelType const& newRewardModel) {
249 if (this->hasRewardModel(rewardModelName)) {
250 STORM_LOG_THROW(!(this->hasRewardModel(rewardModelName)), storm::exceptions::IllegalArgumentException,
251 "A reward model with the given name '" << rewardModelName << "' already exists.");
252 }
253 STORM_LOG_ASSERT(newRewardModel.isCompatible(this->getNumberOfStates(), this->getTransitionMatrix().getRowCount()), "New reward model is not compatible.");
254 this->rewardModels.emplace(rewardModelName, newRewardModel);
255}
256
257template<typename ValueType, typename RewardModelType>
258bool Model<ValueType, RewardModelType>::removeRewardModel(std::string const& rewardModelName) {
259 auto it = this->rewardModels.find(rewardModelName);
260 bool res = (it != this->rewardModels.end());
261 if (res) {
262 this->rewardModels.erase(it->first);
263 }
264 return res;
265}
266
267template<typename ValueType, typename RewardModelType>
268void Model<ValueType, RewardModelType>::restrictRewardModels(std::set<std::string> const& keptRewardModels) {
269 std::set<std::string> removedRewardModels;
270 for (auto const& rewModel : this->getRewardModels()) {
271 if (keptRewardModels.find(rewModel.first) == keptRewardModels.end()) {
272 removedRewardModels.insert(rewModel.first);
273 }
274 }
275 for (auto const& rewModelName : removedRewardModels) {
276 this->removeRewardModel(rewModelName);
277 }
278}
279
280template<typename ValueType, typename RewardModelType>
282 return this->getNumberOfRewardModels() == 1;
284
285template<typename ValueType, typename RewardModelType>
287 STORM_LOG_THROW(this->getNumberOfRewardModels() == 1, storm::exceptions::IllegalFunctionCallException, "The reward model is not unique.");
288 return this->rewardModels.begin()->first;
289}
291template<typename ValueType, typename RewardModelType>
293 return !this->rewardModels.empty();
294}
295
296template<typename ValueType, typename RewardModelType>
298 STORM_LOG_THROW(this->getNumberOfRewardModels() == 1, storm::exceptions::IllegalFunctionCallException, "The reward model is not unique.");
299 return this->rewardModels.cbegin()->second;
300}
301
302template<typename ValueType, typename RewardModelType>
304 STORM_LOG_THROW(this->getNumberOfRewardModels() == 1, storm::exceptions::IllegalFunctionCallException, "The reward model is not unique.");
305 return this->rewardModels.begin()->second;
306}
307
308template<typename ValueType, typename RewardModelType>
310 return this->rewardModels.size();
311}
312template<typename ValueType, typename RewardModelType>
316
317template<typename ValueType, typename RewardModelType>
319 return stateLabeling;
320}
321
322template<typename ValueType, typename RewardModelType>
324 return static_cast<bool>(choiceLabeling);
325}
327template<typename ValueType, typename RewardModelType>
331
332template<typename ValueType, typename RewardModelType>
333std::optional<storm::models::sparse::ChoiceLabeling> const& Model<ValueType, RewardModelType>::getOptionalChoiceLabeling() const {
334 return choiceLabeling;
335}
336
337template<typename ValueType, typename RewardModelType>
338std::optional<storm::models::sparse::ChoiceLabeling>& Model<ValueType, RewardModelType>::getOptionalChoiceLabeling() {
339 return choiceLabeling;
340}
341
342template<typename ValueType, typename RewardModelType>
344 return static_cast<bool>(stateValuations);
345}
346
347template<typename ValueType, typename RewardModelType>
351
352template<typename ValueType, typename RewardModelType>
353std::optional<storm::storage::sparse::StateValuations> const& Model<ValueType, RewardModelType>::getOptionalStateValuations() const {
354 return stateValuations;
355}
356
357template<typename ValueType, typename RewardModelType>
358std::optional<storm::storage::sparse::StateValuations>& Model<ValueType, RewardModelType>::getOptionalStateValuations() {
359 return stateValuations;
360}
362template<typename ValueType, typename RewardModelType>
364 return static_cast<bool>(choiceOrigins);
366
367template<typename ValueType, typename RewardModelType>
368std::shared_ptr<storm::storage::sparse::ChoiceOrigins> const& Model<ValueType, RewardModelType>::getChoiceOrigins() const {
369 return choiceOrigins.value();
370}
371
372template<typename ValueType, typename RewardModelType>
373std::optional<std::shared_ptr<storm::storage::sparse::ChoiceOrigins>> const& Model<ValueType, RewardModelType>::getOptionalChoiceOrigins() const {
374 return choiceOrigins;
376
377template<typename ValueType, typename RewardModelType>
378std::optional<std::shared_ptr<storm::storage::sparse::ChoiceOrigins>>& Model<ValueType, RewardModelType>::getOptionalChoiceOrigins() {
379 return choiceOrigins;
380}
381
382template<typename ValueType, typename RewardModelType>
384 this->printModelInformationHeaderToStream(out);
385 this->printModelInformationFooterToStream(out);
386}
387
388template<typename ValueType, typename RewardModelType>
390 std::size_t seed = 0;
391 boost::hash_combine(seed, transitionMatrix.hash());
392 boost::hash_combine(seed, stateLabeling.hash());
393 for (auto const& rewModel : rewardModels) {
394 boost::hash_combine(seed, rewModel.second.hash());
395 }
396 if (choiceLabeling) {
397 boost::hash_combine(seed, choiceLabeling->hash());
398 }
399 if (stateValuations) {
400 boost::hash_combine(seed, stateValuations->hash());
401 }
402 if (choiceOrigins) {
403 boost::hash_combine(seed, choiceOrigins.value()->hash());
405 return seed;
406}
407
408template<typename ValueType, typename RewardModelType>
410 out << "-------------------------------------------------------------- \n";
411 out << "Model type: \t" << this->getType() << " (sparse)\n";
412 out << "States: \t" << this->getNumberOfStates() << '\n';
413 out << "Transitions: \t" << this->getNumberOfTransitions() << '\n';
414}
415
416template<typename ValueType, typename RewardModelType>
418 this->printRewardModelsInformationToStream(out);
419 out << "State Labels: \t";
420 this->getStateLabeling().printLabelingInformationToStream(out);
421 out << "Choice Labels: \t";
422 if (this->hasChoiceLabeling()) {
423 this->getChoiceLabeling().printLabelingInformationToStream(out);
424 } else {
425 out << "none\n";
427 out << "-------------------------------------------------------------- \n";
428}
429
430template<typename ValueType, typename RewardModelType>
432 if (this->rewardModels.size()) {
433 std::vector<std::string> rewardModelNames;
434 std::for_each(this->rewardModels.cbegin(), this->rewardModels.cend(),
435 [&rewardModelNames](typename std::pair<std::string, RewardModelType> const& nameRewardModelPair) {
436 if (nameRewardModelPair.first.empty()) {
437 rewardModelNames.push_back("(default)");
438 } else {
439 rewardModelNames.push_back(nameRewardModelPair.first);
440 }
441 });
442 out << "Reward Models: " << boost::join(rewardModelNames, ", ") << '\n';
443 } else {
444 out << "Reward Models: none\n";
445 }
446}
447
448template<typename ValueType, typename RewardModelType>
449void Model<ValueType, RewardModelType>::writeDotToStream(std::ostream& outStream, size_t maxWidthLabel, bool includeLabeling,
450 storm::storage::BitVector const* subsystem, std::vector<ValueType> const* firstValue,
451 std::vector<ValueType> const* secondValue, std::vector<uint_fast64_t> const* stateColoring,
452 std::vector<std::string> const* colors, std::vector<uint_fast64_t>*, bool finalizeOutput) const {
453 outStream << "digraph model {\n";
454
455 // Write all states to the stream.
456 for (uint_fast64_t state = 0, highestStateIndex = this->getNumberOfStates() - 1; state <= highestStateIndex; ++state) {
457 if (subsystem == nullptr || subsystem->get(state)) {
458 outStream << "\t" << state;
459 if (includeLabeling || firstValue != nullptr || secondValue != nullptr || stateColoring != nullptr || hasStateValuations()) {
460 outStream << " [ ";
461
462 // If we need to print some extra information, do so now.
463 if (includeLabeling || firstValue != nullptr || secondValue != nullptr || hasStateValuations()) {
464 outStream << "label = \"" << state;
465 if (hasStateValuations()) {
466 std::string stateInfo = getStateValuations().getStateInfo(state);
467 std::vector<std::string> results;
468 boost::split(results, stateInfo, [](char c) { return c == ','; });
469 storm::io::outputFixedWidth(outStream, results, maxWidthLabel);
470 }
471 outStream << ": ";
472
473 // Now print the state labeling to the stream if requested.
474 if (includeLabeling) {
475 outStream << "{";
476 storm::io::outputFixedWidth(outStream, this->getLabelsOfState(state), maxWidthLabel);
477 outStream << "}";
478 }
479
480 outStream << this->additionalDotStateInfo(state);
481
482 // If we are to include some values for the state as well, we do so now.
483 if (firstValue != nullptr || secondValue != nullptr) {
484 outStream << " [";
485 if (firstValue != nullptr) {
486 outStream << (*firstValue)[state];
487 if (secondValue != nullptr) {
488 outStream << ", ";
489 }
490 }
491 if (secondValue != nullptr) {
492 outStream << (*secondValue)[state];
493 }
494 outStream << "]";
495 }
496 outStream << "\"";
497
498 // Now, we color the states if there were colors given.
499 if (stateColoring != nullptr && colors != nullptr) {
500 outStream << ", ";
501 outStream << " style = filled, fillcolor = " << (*colors)[(*stateColoring)[state]];
502 }
503 }
504 outStream << " ]";
505 }
506 outStream << ";\n";
507 }
508 }
509
510 // If this methods has not been called from a derived class, we want to close the digraph here.
511 if (finalizeOutput) {
512 outStream << "}\n";
513 }
514}
515
516template<typename ValueType, typename RewardModelType>
517void Model<ValueType, RewardModelType>::writeJsonToStream(std::ostream& outStream) const {
518 STORM_LOG_WARN_COND(this->getNumberOfStates() < 10000 && this->getNumberOfTransitions() < 100000,
519 "Exporting a large model to json. This might take some time and will result in a very large file.");
520 using JsonValueType = storm::RationalNumber;
522 for (uint64_t state = 0; state < getNumberOfStates(); ++state) {
523 storm::json<JsonValueType> stateChoicesJson;
524 stateChoicesJson["id"] = state;
525 if (hasStateValuations()) {
526 stateChoicesJson["s"] = getStateValuations().template toJson<JsonValueType>(state);
527 }
528 auto labels = getLabelsOfState(state);
529 stateChoicesJson["lab"] = labels;
530 storm::json<JsonValueType> stateRewardsJson;
531 for (auto const& rm : rewardModels) {
532 if (rm.second.hasStateRewards()) {
533 auto const& r = rm.second.getStateReward(state);
534 if (!storm::utility::isZero(r)) {
535 stateRewardsJson[rm.first] = storm::utility::to_string(r);
536 }
537 }
538 }
539 if (!stateRewardsJson.empty()) {
540 stateChoicesJson["rew"] = std::move(stateRewardsJson);
541 }
542
543 // For CTMCs we need to scale the transition probabilities as the transition matrix contains rates.
544 // This is not the case for MA.
545 auto rateForProbabilityScaling = storm::utility::one<ValueType>();
546 if (this->isOfType(storm::models::ModelType::Ctmc)) {
547 auto const& ctmc = this->template as<storm::models::sparse::Ctmc<ValueType, RewardModelType>>();
548 rateForProbabilityScaling = ctmc->getExitRateVector()[state];
549 stateChoicesJson["rate"] = storm::utility::to_string(rateForProbabilityScaling);
550 } else if (this->isOfType(storm::models::ModelType::MarkovAutomaton)) {
551 auto const& ma = this->template as<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType>>();
552 if (ma->isMarkovianState(state)) {
553 stateChoicesJson["rate"] = storm::utility::to_string(ma->getExitRate(state)); // Only export rate for Markovian states
554 }
555 }
556
557 storm::json<JsonValueType> choicesJson;
558 for (uint64_t choiceIndex = getTransitionMatrix().getRowGroupIndices()[state]; choiceIndex < getTransitionMatrix().getRowGroupIndices()[state + 1];
559 ++choiceIndex) {
561 if (hasChoiceOrigins() && getChoiceOrigins()->getIdentifier(choiceIndex) != getChoiceOrigins()->getIdentifierForChoicesWithNoOrigin()) {
562 choiceJson["origin"] = getChoiceOrigins()->getChoiceAsJson(choiceIndex);
563 }
564 if (hasChoiceLabeling()) {
565 auto choiceLabels = getChoiceLabeling().getLabelsOfChoice(choiceIndex);
566 if (!choiceLabels.empty()) {
567 choiceJson["lab"] = choiceLabels;
568 }
569 }
570 choiceJson["id"] = choiceIndex;
571 storm::json<JsonValueType> choiceRewardsJson;
572 for (auto const& rm : rewardModels) {
573 if (rm.second.hasStateActionRewards()) {
574 auto r = rm.second.getStateActionReward(choiceIndex);
575 if (!storm::utility::isZero(r)) {
576 choiceRewardsJson[rm.first] = storm::utility::to_string(r);
577 }
578 }
579 }
580 if (!choiceRewardsJson.empty()) {
581 choiceRewardsJson["rew"] = std::move(choiceRewardsJson);
582 }
584 for (auto const& entry : transitionMatrix.getRow(choiceIndex)) {
586 successor["id"] = entry.getColumn();
587 successor["prob"] = storm::utility::to_string<ValueType>(entry.getValue() / rateForProbabilityScaling);
588 successors.push_back(successor);
589 }
590 choiceJson["succ"] = std::move(successors);
591 choicesJson.push_back(choiceJson);
592 }
593 stateChoicesJson["c"] = std::move(choicesJson);
594 output.push_back(std::move(stateChoicesJson));
595 }
596 outStream << storm::dumpJson(output);
597}
598
599template<>
601 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Json export not implemented for this model type.");
602}
603
604template<typename ValueType, typename RewardModelType>
606 return "";
607}
608
609template<typename ValueType, typename RewardModelType>
611 return this->stateLabeling.getLabelsOfState(state);
612}
613
614template<typename ValueType, typename RewardModelType>
616 for (auto const& entry : this->getTransitionMatrix().getRowGroup(state)) {
617 if (entry.getColumn() != state) {
618 return false;
619 }
620 if (!storm::utility::isOne(entry.getValue())) {
621 return false;
622 }
623 }
624 return true;
625}
626
627template<typename ValueType, typename RewardModelType>
629 return true;
630}
631
632template<typename ValueType, typename RewardModelType>
634 return std::is_same<ValueType, storm::RationalFunction>::value;
635}
636
637template<typename ValueType, typename RewardModelType>
639 return std::is_same<ValueType, storm::Interval>::value;
640}
641
642template<typename ValueType, typename RewardModelType>
644 if (!this->supportsParameters()) {
645 return false;
646 }
647 // Check for parameters
648 for (auto const& entry : this->getTransitionMatrix()) {
649 if (!storm::utility::isConstant(entry.getValue())) {
650 return true;
651 }
652 }
653 // Only constant values present
654 return false;
655}
656
657template<typename ValueType, typename RewardModelType>
659 if (!this->supportsUncertainty()) {
660 return false;
661 }
662 // Check for intervals
663 for (auto const& entry : this->getTransitionMatrix()) {
664 if (!storm::utility::isConstant(entry.getValue())) {
665 return true;
666 }
667 }
668 // Only constant values present
669 return false;
670}
671
672template<typename ValueType, typename RewardModelType>
676
677template<typename ValueType, typename RewardModelType>
678std::unordered_map<std::string, RewardModelType>& Model<ValueType, RewardModelType>::getRewardModels() {
679 return this->rewardModels;
680}
681
682template<typename ValueType, typename RewardModelType>
683std::unordered_map<std::string, RewardModelType> const& Model<ValueType, RewardModelType>::getRewardModels() const {
684 return this->rewardModels;
685}
686
687std::set<storm::RationalFunctionVariable> getProbabilityParameters(Model<storm::RationalFunction> const& model) {
689}
690
691std::set<storm::RationalFunctionVariable> getRewardParameters(Model<storm::RationalFunction> const& model) {
692 std::set<storm::RationalFunctionVariable> result;
693 for (auto rewModel : model.getRewardModels()) {
694 std::set<storm::RationalFunctionVariable> tmp = getRewardModelParameters(rewModel.second);
695 result.insert(tmp.begin(), tmp.end());
696 }
697 return result;
698}
699
700std::set<storm::RationalFunctionVariable> getRateParameters(Model<storm::RationalFunction> const& model) {
702 auto const& ctmc = model.template as<storm::models::sparse::Ctmc<storm::RationalFunction>>();
703 return storm::utility::vector::getVariables(ctmc->getExitRateVector());
705 auto const& ma = model.template as<storm::models::sparse::MarkovAutomaton<storm::RationalFunction>>();
706 return storm::utility::vector::getVariables(ma->getExitRates());
707 } else {
708 return {};
709 }
710}
711
712std::set<storm::RationalFunctionVariable> getAllParameters(Model<storm::RationalFunction> const& model) {
713 std::set<storm::RationalFunctionVariable> parameters = getProbabilityParameters(model);
714 std::set<storm::RationalFunctionVariable> rewardParameters = getRewardParameters(model);
715 parameters.insert(rewardParameters.begin(), rewardParameters.end());
716 std::set<storm::RationalFunctionVariable> rateParameters = getRewardParameters(model);
717 parameters.insert(rateParameters.begin(), rateParameters.end());
718 return parameters;
719}
720
721template class Model<double>;
723template class Model<storm::RationalNumber>;
724template class Model<storm::Interval>;
725template class Model<storm::RationalFunction>;
726} // namespace sparse
727} // namespace models
728} // namespace storm
virtual bool isExact() const
Checks whether the model is exact.
Definition ModelBase.cpp:62
virtual bool hasParameters() const
Checks whether the model has parameters.
Definition ModelBase.cpp:58
virtual bool isSparseModel() const
Checks whether the model is a sparse model.
Definition ModelBase.cpp:11
bool isOfType(storm::models::ModelType const &modelType) const
Checks whether the model is of the given type.
Definition ModelBase.cpp:27
virtual bool supportsUncertainty() const
Does it support uncertainty (e.g., via interval-valued entries).
Definition ModelBase.cpp:23
virtual bool supportsParameters() const
Checks whether the model supports parameters.
Definition ModelBase.cpp:54
This class manages the labeling of the choice space with a number of (atomic) labels.
Base class for all sparse models.
Definition Model.h:32
storm::models::sparse::ChoiceLabeling const & getChoiceLabeling() const
Retrieves the labels for the choices of the model.
Definition Model.cpp:328
RewardModelType const & getUniqueRewardModel() const
Retrieves the unique reward model, if there exists exactly one.
Definition Model.cpp:297
bool hasRewardModel() const
Retrieves whether the model has at least one reward model.
Definition Model.cpp:292
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:191
virtual std::size_t hash() const
Definition Model.cpp:389
Model(Model< ValueType, RewardModelType > const &other)=default
void setInitialStates(storm::storage::BitVector const &states)
Overwrites the initial states of the model.
Definition Model.cpp:176
void printModelInformationFooterToStream(std::ostream &out) const
Prints the information footer (reward models, labels and size in memory) of the model to the specifie...
Definition Model.cpp:417
virtual void printModelInformationToStream(std::ostream &out) const override
Prints information about the model to the specified stream.
Definition Model.cpp:383
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
Definition Model.cpp:683
void restrictRewardModels(std::set< std::string > const &keptRewardModels)
Removes all reward models whose name is not in the given set.
Definition Model.cpp:268
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
Definition Model.cpp:343
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the sets of states labeled with the given label.
Definition Model.cpp:181
bool removeRewardModel(std::string const &rewardModelName)
Removes the reward model with the given name from the model.
Definition Model.cpp:258
void printRewardModelsInformationToStream(std::ostream &out) const
Prints information about the reward models to the specified stream.
Definition Model.cpp:431
std::set< std::string > getLabelsOfState(storm::storage::sparse::state_type state) const
Retrieves the set of labels attached to the given state.
Definition Model.cpp:610
std::optional< std::shared_ptr< storm::storage::sparse::ChoiceOrigins > > const & getOptionalChoiceOrigins() const
Retrieves an optional value that contains the choice origins if there are some.
Definition Model.cpp:373
RewardModelType & rewardModel(std::string const &rewardModelName)
Definition Model.cpp:206
virtual uint_fast64_t getNumberOfChoices() const override
Returns the number of choices ine the model.
Definition Model.cpp:166
storm::storage::sparse::StateValuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
Definition Model.cpp:348
void addRewardModel(std::string const &rewardModelName, RewardModelType const &rewModel)
Adds a reward model to the model.
Definition Model.cpp:248
std::shared_ptr< storm::storage::sparse::ChoiceOrigins > const & getChoiceOrigins() const
Retrieves the origins of the choices of the model.
Definition Model.cpp:368
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
Definition Model.cpp:151
bool hasChoiceLabeling() const
Retrieves whether this model has a labeling of the choices.
Definition Model.cpp:323
uint_fast64_t getNumberOfRewardModels() const
Retrieves the number of reward models associated with this model.
Definition Model.cpp:309
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
Definition Model.cpp:313
void printModelInformationHeaderToStream(std::ostream &out) const
Prints the information header (number of states and transitions) of the model to the specified stream...
Definition Model.cpp:409
std::optional< storm::models::sparse::ChoiceLabeling > const & getOptionalChoiceLabeling() const
Retrieves an optional value that contains the choice labeling if there is one.
Definition Model.cpp:333
CRewardModelType RewardModelType
Definition Model.h:35
virtual bool hasUniqueRewardModel() const override
Retrieves whether the model has a unique reward model.
Definition Model.cpp:281
std::optional< storm::storage::sparse::StateValuations > const & getOptionalStateValuations() const
Retrieves an optional value that contains the state valuations if there are some.
Definition Model.cpp:353
virtual uint_fast64_t getNumberOfTransitions() const override
Returns the number of (non-zero) transitions of the model.
Definition Model.cpp:161
bool hasChoiceOrigins() const
Retrieves whether this model was build with choice origins.
Definition Model.cpp:363
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:156
bool hasLabel(std::string const &label) const
Retrieves whether the given label is a valid label in this model.
Definition Model.cpp:186
RewardModelType const & getRewardModel(std::string const &rewardModelName) const
Retrieves the reward model with the given name, if one exists.
Definition Model.cpp:212
virtual std::string const & getUniqueRewardModelName() const override
Retrieves the name of the unique reward model, if there exists exactly one.
Definition Model.cpp:286
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
Definition Model.cpp:171
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 get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that holds a possibly non-square matrix in the compressed row storage format.
const_iterator end(index_type row) const
Retrieves an iterator that points past the end of the given row.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void outputFixedWidth(std::ostream &stream, Container const &output, size_t maxWidth=30)
Output list of strings with linebreaks according to fixed width.
Definition export.h:60
std::set< storm::RationalFunctionVariable > getRateParameters(Model< storm::RationalFunction > const &model)
Get all parameters occurring in rates.
Definition Model.cpp:700
std::set< storm::RationalFunctionVariable > getRewardParameters(Model< storm::RationalFunction > const &model)
Get all parameters occurring in rewards.
Definition Model.cpp:691
std::set< storm::RationalFunctionVariable > getRewardModelParameters(StandardRewardModel< storm::RationalFunction > const &rewModel)
std::set< storm::RationalFunctionVariable > getProbabilityParameters(Model< storm::RationalFunction > const &model)
Get all probability parameters occurring on transitions.
Definition Model.cpp:687
std::set< storm::RationalFunctionVariable > getAllParameters(Model< storm::RationalFunction > const &model)
Get all parameters (probability, rewards, and rates) occurring in the model.
Definition Model.cpp:712
std::set< storm::RationalFunctionVariable > getVariables(SparseMatrix< storm::RationalFunction > const &matrix)
std::set< storm::RationalFunctionVariable > getVariables(std::vector< storm::RationalFunction > const &vector)
bool isOne(ValueType const &a)
Definition constants.cpp:37
bool isConstant(ValueType const &)
Definition constants.cpp:67
bool isZero(ValueType const &a)
Definition constants.cpp:42
std::string to_string(ValueType const &value)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:10
std::string dumpJson(storm::json< ValueType > const &j, bool compact)
Dumps the given json object, producing a String.