3#include <boost/algorithm/string/join.hpp>
4#include <boost/algorithm/string/split.hpp>
28template<
typename ValueType,
typename RewardModelType>
31 transitionMatrix(components.transitionMatrix),
32 stateLabeling(components.stateLabeling),
33 rewardModels(components.rewardModels),
34 choiceLabeling(components.choiceLabeling),
35 stateValuations(components.stateValuations),
36 choiceOrigins(components.choiceOrigins) {
37 assertValidityOfComponents(components);
40template<
typename ValueType,
typename RewardModelType>
43 transitionMatrix(
std::move(components.transitionMatrix)),
44 stateLabeling(
std::move(components.stateLabeling)),
45 rewardModels(
std::move(components.rewardModels)),
46 choiceLabeling(
std::move(components.choiceLabeling)),
47 stateValuations(
std::move(components.stateValuations)),
48 choiceOrigins(
std::move(components.choiceOrigins)) {
49 assertValidityOfComponents(components);
52template<
typename ValueType,
typename RewardModelType>
53void Model<ValueType, RewardModelType>::assertValidityOfComponents(
65 "Invalid column count of transition matrix.");
67 std::string reasonNotProbabilistic [[maybe_unused]];
69 "The matrix is not probabilistic. " << reasonNotProbabilistic);
71 STORM_LOG_THROW(this->getStateLabeling().getNumberOfItems() == stateCount, storm::exceptions::IllegalArgumentException,
72 "Invalid item count (" << this->getStateLabeling().getNumberOfItems() <<
") of state labeling (states: " << stateCount <<
").");
73 for (
auto const& rewardModel : this->getRewardModels()) {
74 STORM_LOG_THROW(!rewardModel.second.hasStateRewards() || rewardModel.second.getStateRewardVector().size() == stateCount,
75 storm::exceptions::IllegalArgumentException,
76 "Invalid size (" << rewardModel.second.getStateRewardVector().size() <<
") of state reward vector (states:" << stateCount <<
").");
78 !
rewardModel.second.hasStateActionRewards() ||
rewardModel.second.getStateActionRewardVector().size() == choiceCount,
79 storm::exceptions::IllegalArgumentException,
80 "Invalid size (" <<
rewardModel.second.getStateActionRewardVector().size() <<
") of state action reward vector (expected:" << choiceCount <<
").");
82 !
rewardModel.second.hasTransitionRewards() ||
rewardModel.second.getTransitionRewardMatrix().isSubmatrixOf(this->getTransitionMatrix()),
83 "The transition reward matrix is not a submatrix of the transition matrix, i.e. there are rewards for transitions that do not exist.");
86 !this->hasChoiceLabeling() || this->getChoiceLabeling().getNumberOfItems() == choiceCount, storm::exceptions::IllegalArgumentException,
87 "Invalid choice count of choice labeling (choices: " << choiceCount <<
" vs. labeling:" << this->getChoiceLabeling().getNumberOfItems() <<
").");
89 !this->hasStateValuations() || this->getStateValuations().getNumberOfStates() == stateCount, storm::exceptions::IllegalArgumentException,
90 "Invalid state count for state valuations (states: " << stateCount <<
" vs. valuations:" << this->getStateValuations().getNumberOfStates() <<
").");
98 "Can not create deterministic model: Transition matrix has non-trivial row grouping.");
100 "Can not create deterministic model: Number of rows of transition matrix does not match state count.");
102 "Can not create deterministic model: Number of columns of transition matrix does not match state count.");
106 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getRowGroupCount(), storm::exceptions::IllegalArgumentException,
107 "Can not create nondeterministic model: Number of row groups ("
108 << this->
getTransitionMatrix().getRowGroupCount() <<
") of transition matrix does not match state count (" << stateCount <<
").");
110 "Can not create nondeterministic model: Number of columns of transition matrix does not match state count.");
114 "No player 1 matrix given for stochastic game.");
116 "Can not create stochastic game: There is a row in the p1 matrix with not exactly one entry.");
118 "Can not create stochastic game: Number of row groups of p1 matrix does not match state count.");
120 storm::exceptions::IllegalArgumentException,
121 "Can not create stochastic game: Number of row groups of p2 matrix does not match column count of p1 matrix.");
123 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Invalid model type.");
129 "Can not create continuous time model: no rates are given.");
131 "Size of exit rate vector does not match state count.");
133 "Can not create Markov Automaton: no Markovian states given.");
136 "Rates specified for discrete-time model. The rates will be ignored.");
139 "Markovian states given for a model that is not a Markov automaton (will be ignored).");
144 "Can not create stochastic multiplayer game: Missing player indications.");
148 "Size of state player indications (" << components.
statePlayerIndications->size() <<
") of SMG does not match state count (" << stateCount <<
").");
151 "statePlayerIndications given for a model that is not a stochastic multiplayer game (will be ignored).");
153 "playerNameToIndexMap given for a model that is not a stochastic multiplayer game (will be ignored).");
157template<
typename ValueType,
typename RewardModelType>
162template<
typename ValueType,
typename RewardModelType>
167template<
typename ValueType,
typename RewardModelType>
172template<
typename ValueType,
typename RewardModelType>
177template<
typename ValueType,
typename RewardModelType>
182template<
typename ValueType,
typename RewardModelType>
187template<
typename ValueType,
typename RewardModelType>
189 return stateLabeling.getStates(label);
192template<
typename ValueType,
typename RewardModelType>
194 return stateLabeling.containsLabel(label);
197template<
typename ValueType,
typename RewardModelType>
199 return transitionMatrix;
202template<
typename ValueType,
typename RewardModelType>
204 return transitionMatrix;
207template<
typename ValueType,
typename RewardModelType>
209 return this->rewardModels.find(rewardModelName) != this->rewardModels.
end();
212template<
typename ValueType,
typename RewardModelType>
215 return this->rewardModels.find(rewardModelName)->second;
218template<
typename ValueType,
typename RewardModelType>
220 auto it = this->rewardModels.find(rewardModelName);
221 if (it == this->rewardModels.end()) {
222 if (rewardModelName.empty()) {
227 "Unable to refer to default reward model, because there is no default model or it is not unique.");
230 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"The requested reward model '" << rewardModelName <<
"' does not exist.");
236template<
typename ValueType,
typename RewardModelType>
238 auto it = this->rewardModels.find(rewardModelName);
239 if (it == this->rewardModels.end()) {
240 if (rewardModelName.empty()) {
245 "Unable to refer to default reward model, because there is no default model or it is not unique.");
248 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"The requested reward model '" << rewardModelName <<
"' does not exist.");
254template<
typename ValueType,
typename RewardModelType>
258 "A reward model with the given name '" << rewardModelName <<
"' already exists.");
260 STORM_LOG_ASSERT(newRewardModel.isCompatible(this->getNumberOfStates(), this->getTransitionMatrix().getRowCount()),
"New reward model is not compatible.");
261 this->rewardModels.emplace(rewardModelName, newRewardModel);
264template<
typename ValueType,
typename RewardModelType>
266 auto it = this->rewardModels.find(rewardModelName);
267 bool res = (it != this->rewardModels.end());
269 this->rewardModels.erase(it->first);
274template<
typename ValueType,
typename RewardModelType>
276 std::set<std::string> removedRewardModels;
278 if (keptRewardModels.find(rewModel.first) == keptRewardModels.end()) {
279 removedRewardModels.insert(rewModel.first);
282 for (
auto const& rewModelName : removedRewardModels) {
283 this->removeRewardModel(rewModelName);
287template<
typename ValueType,
typename RewardModelType>
292template<
typename ValueType,
typename RewardModelType>
295 return this->rewardModels.begin()->first;
298template<
typename ValueType,
typename RewardModelType>
300 return !this->rewardModels.empty();
303template<
typename ValueType,
typename RewardModelType>
306 return this->rewardModels.cbegin()->second;
309template<
typename ValueType,
typename RewardModelType>
312 return this->rewardModels.begin()->second;
315template<
typename ValueType,
typename RewardModelType>
317 return this->rewardModels.size();
319template<
typename ValueType,
typename RewardModelType>
321 return stateLabeling;
324template<
typename ValueType,
typename RewardModelType>
326 return stateLabeling;
329template<
typename ValueType,
typename RewardModelType>
331 return static_cast<bool>(choiceLabeling);
334template<
typename ValueType,
typename RewardModelType>
336 return choiceLabeling.value();
339template<
typename ValueType,
typename RewardModelType>
341 return choiceLabeling;
344template<
typename ValueType,
typename RewardModelType>
346 return choiceLabeling;
349template<
typename ValueType,
typename RewardModelType>
351 return static_cast<bool>(stateValuations);
354template<
typename ValueType,
typename RewardModelType>
356 return stateValuations.value();
359template<
typename ValueType,
typename RewardModelType>
361 return stateValuations;
364template<
typename ValueType,
typename RewardModelType>
366 return stateValuations;
369template<
typename ValueType,
typename RewardModelType>
371 return static_cast<bool>(choiceOrigins);
374template<
typename ValueType,
typename RewardModelType>
376 return choiceOrigins.value();
379template<
typename ValueType,
typename RewardModelType>
381 return choiceOrigins;
384template<
typename ValueType,
typename RewardModelType>
386 return choiceOrigins;
389template<
typename ValueType,
typename RewardModelType>
395template<
typename ValueType,
typename RewardModelType>
397 std::size_t seed = 0;
398 boost::hash_combine(seed, transitionMatrix.hash());
399 boost::hash_combine(seed, stateLabeling.hash());
400 for (
auto const& rewModel : rewardModels) {
401 boost::hash_combine(seed, rewModel.second.hash());
403 if (choiceLabeling) {
404 boost::hash_combine(seed, choiceLabeling->hash());
406 if (stateValuations) {
407 boost::hash_combine(seed, stateValuations->hash());
410 boost::hash_combine(seed, choiceOrigins.value()->hash());
415template<
typename ValueType,
typename RewardModelType>
417 out <<
"-------------------------------------------------------------- \n";
423template<
typename ValueType,
typename RewardModelType>
426 out <<
"State Labels: \t";
428 out <<
"Choice Labels: \t";
434 out <<
"-------------------------------------------------------------- \n";
437template<
typename ValueType,
typename RewardModelType>
439 if (this->rewardModels.size()) {
440 std::vector<std::string> rewardModelNames;
441 std::for_each(this->rewardModels.cbegin(), this->rewardModels.cend(),
442 [&rewardModelNames](
typename std::pair<std::string, RewardModelType>
const& nameRewardModelPair) {
443 if (nameRewardModelPair.first.empty()) {
444 rewardModelNames.push_back(
"(default)");
446 rewardModelNames.push_back(nameRewardModelPair.first);
449 out <<
"Reward Models: " << boost::join(rewardModelNames,
", ") <<
'\n';
451 out <<
"Reward Models: none\n";
455template<
typename ValueType,
typename RewardModelType>
456void Model<ValueType, RewardModelType>::writeDotToStream(std::ostream& outStream,
size_t maxWidthLabel,
bool includeLabeling,
458 std::vector<ValueType>
const* secondValue, std::vector<uint_fast64_t>
const* stateColoring,
459 std::vector<std::string>
const* colors, std::vector<uint_fast64_t>*,
bool finalizeOutput)
const {
460 outStream <<
"digraph model {\n";
463 for (uint_fast64_t state = 0, highestStateIndex = this->getNumberOfStates() - 1; state <= highestStateIndex; ++state) {
464 if (subsystem ==
nullptr || subsystem->
get(state)) {
465 outStream <<
"\t" << state;
466 if (includeLabeling || firstValue !=
nullptr || secondValue !=
nullptr || stateColoring !=
nullptr || hasStateValuations()) {
470 if (includeLabeling || firstValue !=
nullptr || secondValue !=
nullptr || hasStateValuations()) {
471 outStream <<
"label = \"" << state;
472 if (hasStateValuations()) {
473 std::string stateInfo = getStateValuations().getStateInfo(state);
474 std::vector<std::string> results;
475 boost::split(results, stateInfo, [](
char c) {
return c ==
','; });
481 if (includeLabeling) {
487 outStream << this->additionalDotStateInfo(state);
490 if (firstValue !=
nullptr || secondValue !=
nullptr) {
492 if (firstValue !=
nullptr) {
493 outStream << (*firstValue)[state];
494 if (secondValue !=
nullptr) {
498 if (secondValue !=
nullptr) {
499 outStream << (*secondValue)[state];
506 if (stateColoring !=
nullptr && colors !=
nullptr) {
508 outStream <<
" style = filled, fillcolor = " << (*colors)[(*stateColoring)[state]];
518 if (finalizeOutput) {
523template<
typename ValueType,
typename RewardModelType>
526 "Exporting a large model to json. This might take some time and will result in a very large file.");
527 using JsonValueType = storm::RationalNumber;
531 stateChoicesJson[
"id"] = state;
536 stateChoicesJson[
"lab"] = labels;
538 for (
auto const& rm : rewardModels) {
539 if (rm.second.hasStateRewards()) {
540 auto const& r = rm.second.getStateReward(state);
546 if (!stateRewardsJson.empty()) {
547 stateChoicesJson[
"rew"] = std::move(stateRewardsJson);
555 rateForProbabilityScaling = ctmc->getExitRateVector()[state];
559 if (ma->isMarkovianState(state)) {
573 if (!choiceLabels.empty()) {
574 choiceJson[
"lab"] = choiceLabels;
577 choiceJson[
"id"] = choiceIndex;
579 for (
auto const& rm : rewardModels) {
580 if (rm.second.hasStateActionRewards()) {
581 auto r = rm.second.getStateActionReward(choiceIndex);
587 if (!choiceRewardsJson.empty()) {
588 choiceRewardsJson[
"rew"] = std::move(choiceRewardsJson);
591 for (
auto const& entry : transitionMatrix.getRow(choiceIndex)) {
593 successor[
"id"] = entry.getColumn();
595 successors.push_back(successor);
597 choiceJson[
"succ"] = std::move(successors);
598 choicesJson.push_back(choiceJson);
600 stateChoicesJson[
"c"] = std::move(choicesJson);
601 output.push_back(std::move(stateChoicesJson));
608 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Json export not implemented for this model type.");
611template<
typename ValueType,
typename RewardModelType>
616template<
typename ValueType,
typename RewardModelType>
618 return this->stateLabeling.getLabelsOfState(state);
621template<
typename ValueType,
typename RewardModelType>
624 if (entry.getColumn() != state) {
634template<
typename ValueType,
typename RewardModelType>
639template<
typename ValueType,
typename RewardModelType>
641 return std::is_same<ValueType, storm::RationalFunction>::value;
644template<
typename ValueType,
typename RewardModelType>
649template<
typename ValueType,
typename RewardModelType>
664template<
typename ValueType,
typename RewardModelType>
679template<
typename ValueType,
typename RewardModelType>
684template<
typename ValueType,
typename RewardModelType>
686 return this->rewardModels;
689template<
typename ValueType,
typename RewardModelType>
691 return this->rewardModels;
699 std::set<storm::RationalFunctionVariable> result;
702 result.insert(tmp.begin(), tmp.end());
709 auto const& ctmc = model.template as<storm::models::sparse::Ctmc<storm::RationalFunction>>();
712 auto const& ma = model.template as<storm::models::sparse::MarkovAutomaton<storm::RationalFunction>>();
722 parameters.insert(rewardParameters.begin(), rewardParameters.end());
723 std::set<storm::RationalFunctionVariable> rateParameters =
getRateParameters(model);
724 parameters.insert(rateParameters.begin(), rateParameters.end());
virtual bool isExact() const
Checks whether the model is exact.
virtual bool hasParameters() const
Checks whether the model has parameters.
virtual ModelType getType() const
Return the actual type of the model.
virtual bool isSparseModel() const
Checks whether the model is a sparse model.
std::shared_ptr< ModelType > as()
Casts the model into the model type given by the template parameter.
bool isOfType(storm::models::ModelType const &modelType) const
Checks whether the model is of the given type.
virtual bool supportsUncertainty() const
Does it support uncertainty (e.g., via interval-valued entries).
virtual bool supportsParameters() const
Checks whether the model supports parameters.
This class manages the labeling of the choice space with a number of (atomic) labels.
Base class for all sparse models.
storm::models::sparse::ChoiceLabeling const & getChoiceLabeling() const
Retrieves the labels for the choices of the model.
RewardModelType const & getUniqueRewardModel() const
bool hasRewardModel() const
Retrieves whether the model has at least one reward model.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
virtual std::size_t hash() const
virtual bool hasUncertainty() const
Checks whether the model actually is uncertain, i.e., whether there is a non-singleton transition rel...
Model(Model< ValueType, RewardModelType > const &other)=default
void setInitialStates(storm::storage::BitVector const &states)
Overwrites the initial states of the model.
virtual bool supportsUncertainty() const override
Does it support uncertainty (e.g., via interval-valued entries).
void printModelInformationFooterToStream(std::ostream &out) const
virtual void printModelInformationToStream(std::ostream &out) const override
Prints information about the model to the specified stream.
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
void restrictRewardModels(std::set< std::string > const &keptRewardModels)
Removes all reward models whose name is not in the given set.
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the sets of states labeled with the given label.
bool removeRewardModel(std::string const &rewardModelName)
Removes the reward model with the given name from the model.
void printRewardModelsInformationToStream(std::ostream &out) const
std::set< std::string > getLabelsOfState(storm::storage::sparse::state_type state) const
Retrieves the set of labels attached to the given state.
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.
RewardModelType & rewardModel(std::string const &rewardModelName)
virtual uint_fast64_t getNumberOfChoices() const override
storm::storage::sparse::StateValuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
void addRewardModel(std::string const &rewardModelName, RewardModelType const &rewModel)
Adds a reward model to the model.
std::shared_ptr< storm::storage::sparse::ChoiceOrigins > const & getChoiceOrigins() const
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
bool isSinkState(uint64_t sink) const
bool hasChoiceLabeling() const
Retrieves whether this model has a labeling of the choices.
uint_fast64_t getNumberOfRewardModels() const
Retrieves the number of reward models associated with this model.
virtual bool hasRewardModel(std::string const &rewardModelName) const override
Retrieves whether the model has a reward model with the given name.
storm::models::sparse::StateLabeling const & getStateLabeling() const
virtual void writeJsonToStream(std::ostream &outStream) const
Writes a JSON representation of the model to the given stream.
void printModelInformationHeaderToStream(std::ostream &out) const
std::optional< storm::models::sparse::ChoiceLabeling > const & getOptionalChoiceLabeling() const
Retrieves an optional value that contains the choice labeling if there is one.
CRewardModelType RewardModelType
virtual bool supportsParameters() const override
Checks whether the model supports parameters.
virtual bool hasUniqueRewardModel() const override
virtual std::string additionalDotStateInfo(uint64_t state) const
Return a string that is additonally added to the state information in the dot stream.
std::optional< storm::storage::sparse::StateValuations > const & getOptionalStateValuations() const
Retrieves an optional value that contains the state valuations if there are some.
virtual uint_fast64_t getNumberOfTransitions() const override
Returns the number of (non-zero) transitions of the model.
virtual bool isExact() const override
bool hasChoiceOrigins() const
virtual uint_fast64_t getNumberOfStates() const override
bool hasLabel(std::string const &label) const
Retrieves whether the given label is a valid label in this model.
RewardModelType const & getRewardModel(std::string const &rewardModelName) const
Retrieves the reward model with the given name, if one exists.
virtual std::string const & getUniqueRewardModelName() const override
Retrieves the name of the unique reward model, if there exists exactly one.
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
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.
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.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_ERROR_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
void outputFixedWidth(std::ostream &stream, Container const &output, size_t maxWidth=30)
Output list of strings with linebreaks according to fixed width.
std::set< storm::RationalFunctionVariable > getRateParameters(Model< storm::RationalFunction > const &model)
Get all parameters occurring in rates.
std::set< storm::RationalFunctionVariable > getRewardParameters(Model< storm::RationalFunction > const &model)
Get all parameters occurring in rewards.
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.
std::set< storm::RationalFunctionVariable > getAllParameters(Model< storm::RationalFunction > const &model)
Get all parameters (probability, rewards, and rates) occurring in the model.
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)
bool isConstant(ValueType const &)
bool isZero(ValueType const &a)
std::string to_string(ValueType const &value)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
constexpr bool IsIntervalType
Helper to check if a type is an interval.
std::string dumpJson(storm::json< ValueType > const &j, bool compact)
Dumps the given json object, producing a String.
static const bool IsExact
boost::optional< storm::storage::BitVector > markovianStates
boost::optional< std::vector< storm::storage::PlayerIndex > > statePlayerIndications
boost::optional< storm::storage::SparseMatrix< storm::storage::sparse::state_type > > player1Matrix
boost::optional< std::map< std::string, storm::storage::PlayerIndex > > playerNameToIndexMap
boost::optional< std::vector< ValueType > > exitRates