3#include <boost/algorithm/string/join.hpp>
4#include <boost/algorithm/string/split.hpp>
27template<
typename ValueType,
typename RewardModelType>
30 transitionMatrix(other.transitionMatrix),
31 stateLabeling(other.stateLabeling),
32 rewardModels(other.rewardModels),
33 choiceLabeling(other.choiceLabeling),
34 stateValuations(other.stateValuations),
35 choiceOrigins(other.choiceOrigins),
36 stochasticTolerance(other.stochasticTolerance ?
std::make_unique<
ValueType>(*other.stochasticTolerance) : nullptr) {
40template<
typename ValueType,
typename RewardModelType>
44 transitionMatrix = other.transitionMatrix;
45 stateLabeling = other.stateLabeling;
46 rewardModels = other.rewardModels;
47 choiceLabeling = other.choiceLabeling;
48 stateValuations = other.stateValuations;
49 choiceOrigins = other.choiceOrigins;
50 stochasticTolerance = other.stochasticTolerance ? std::make_unique<ValueType>(*other.stochasticTolerance) :
nullptr;
55template<
typename ValueType,
typename RewardModelType>
58 transitionMatrix(components.transitionMatrix),
59 stateLabeling(components.stateLabeling),
60 rewardModels(components.rewardModels),
61 choiceLabeling(components.choiceLabeling),
62 stateValuations(components.stateValuations),
63 choiceOrigins(components.choiceOrigins) {
66 assertValidityOfComponents(components);
69template<
typename ValueType,
typename RewardModelType>
72 transitionMatrix(
std::move(components.transitionMatrix)),
73 stateLabeling(
std::move(components.stateLabeling)),
74 rewardModels(
std::move(components.rewardModels)),
75 choiceLabeling(
std::move(components.choiceLabeling)),
76 stateValuations(
std::move(components.stateValuations)),
77 choiceOrigins(
std::move(components.choiceOrigins)) {
78 stochasticTolerance = std::make_unique<ValueType>(components.stochasticTolerance.value_or(
80 assertValidityOfComponents(components);
83template<
typename ValueType,
typename RewardModelType>
84void Model<ValueType, RewardModelType>::assertValidityOfComponents(
93 "Invalid column count of transition matrix.");
95 [[maybe_unused]] std::string reasonNotProbabilistic;
97 "The matrix is not probabilistic. " << reasonNotProbabilistic);
99 STORM_LOG_THROW(this->getStateLabeling().getNumberOfItems() == stateCount, storm::exceptions::IllegalArgumentException,
100 "Invalid item count (" << this->getStateLabeling().getNumberOfItems() <<
") of state labeling (states: " << stateCount <<
").");
101 for (
auto const& rewardModel : this->getRewardModels()) {
103 storm::exceptions::IllegalArgumentException,
104 "Invalid size (" <<
rewardModel.second.getStateRewardVector().size() <<
") of state reward vector (states:" << stateCount <<
").");
106 !
rewardModel.second.hasStateActionRewards() ||
rewardModel.second.getStateActionRewardVector().size() == choiceCount,
107 storm::exceptions::IllegalArgumentException,
108 "Invalid size (" <<
rewardModel.second.getStateActionRewardVector().size() <<
") of state action reward vector (expected:" << choiceCount <<
").");
110 !
rewardModel.second.hasTransitionRewards() ||
rewardModel.second.getTransitionRewardMatrix().isSubmatrixOf(this->getTransitionMatrix()),
111 "The transition reward matrix is not a submatrix of the transition matrix, i.e. there are rewards for transitions that do not exist.");
114 !this->hasChoiceLabeling() || this->getChoiceLabeling().getNumberOfItems() == choiceCount, storm::exceptions::IllegalArgumentException,
115 "Invalid choice count of choice labeling (choices: " << choiceCount <<
" vs. labeling:" << this->getChoiceLabeling().getNumberOfItems() <<
").");
118 "Invalid state count for state valuations (states: " << stateCount <<
" vs. valuations:" << this->
getStateValuations().getNumberOfEntities() <<
").");
126 "Can not create deterministic model: Transition matrix has non-trivial row grouping.");
128 "Can not create deterministic model: Number of rows of transition matrix does not match state count.");
130 "Can not create deterministic model: Number of columns of transition matrix does not match state count.");
134 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getRowGroupCount(), storm::exceptions::IllegalArgumentException,
135 "Can not create nondeterministic model: Number of row groups ("
136 << this->getTransitionMatrix().getRowGroupCount() <<
") of transition matrix does not match state count (" << stateCount <<
").");
137 STORM_LOG_THROW(stateCount == this->getTransitionMatrix().getColumnCount(), storm::exceptions::IllegalArgumentException,
138 "Can not create nondeterministic model: Number of columns of transition matrix does not match state count.");
142 "No player 1 matrix given for stochastic game.");
144 "Can not create stochastic game: There is a row in the p1 matrix with not exactly one entry.");
146 "Can not create stochastic game: Number of row groups of p1 matrix does not match state count.");
148 storm::exceptions::IllegalArgumentException,
149 "Can not create stochastic game: Number of row groups of p2 matrix does not match column count of p1 matrix.");
151 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Invalid model type.");
157 "Can not create continuous time model: no rates are given.");
159 "Size of exit rate vector does not match state count.");
161 "Can not create Markov Automaton: no Markovian states given.");
164 "Rates specified for discrete-time model. The rates will be ignored.");
167 "Markovian states given for a model that is not a Markov automaton (will be ignored).");
172 "Can not create stochastic multiplayer game: Missing player indications.");
176 "Size of state player indications (" << components.
statePlayerIndications->size() <<
") of SMG does not match state count (" << stateCount <<
").");
179 "statePlayerIndications given for a model that is not a stochastic multiplayer game (will be ignored).");
181 "playerNameToIndexMap given for a model that is not a stochastic multiplayer game (will be ignored).");
185template<
typename ValueType,
typename RewardModelType>
190template<
typename ValueType,
typename RewardModelType>
195template<
typename ValueType,
typename RewardModelType>
200template<
typename ValueType,
typename RewardModelType>
205template<
typename ValueType,
typename RewardModelType>
210template<
typename ValueType,
typename RewardModelType>
215template<
typename ValueType,
typename RewardModelType>
217 return stateLabeling.getStates(label);
220template<
typename ValueType,
typename RewardModelType>
222 return stateLabeling.containsLabel(label);
225template<
typename ValueType,
typename RewardModelType>
227 return transitionMatrix;
230template<
typename ValueType,
typename RewardModelType>
232 return transitionMatrix;
235template<
typename ValueType,
typename RewardModelType>
237 return this->rewardModels.find(rewardModelName) != this->rewardModels.
end();
240template<
typename ValueType,
typename RewardModelType>
243 return this->rewardModels.find(rewardModelName)->second;
246template<
typename ValueType,
typename RewardModelType>
248 auto it = this->rewardModels.find(rewardModelName);
249 if (it == this->rewardModels.end()) {
250 if (rewardModelName.empty()) {
255 "Unable to refer to default reward model, because there is no default model or it is not unique.");
258 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"The requested reward model '" << rewardModelName <<
"' does not exist.");
264template<
typename ValueType,
typename RewardModelType>
266 auto it = this->rewardModels.find(rewardModelName);
267 if (it == this->rewardModels.end()) {
268 if (rewardModelName.empty()) {
273 "Unable to refer to default reward model, because there is no default model or it is not unique.");
276 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"The requested reward model '" << rewardModelName <<
"' does not exist.");
282template<
typename ValueType,
typename RewardModelType>
286 "A reward model with the given name '" << rewardModelName <<
"' already exists.");
288 STORM_LOG_ASSERT(newRewardModel.isCompatible(this->getNumberOfStates(), this->getTransitionMatrix().getRowCount()),
"New reward model is not compatible.");
289 this->rewardModels.emplace(rewardModelName, newRewardModel);
292template<
typename ValueType,
typename RewardModelType>
294 auto it = this->rewardModels.find(rewardModelName);
295 bool res = (it != this->rewardModels.end());
297 this->rewardModels.erase(it->first);
302template<
typename ValueType,
typename RewardModelType>
304 std::set<std::string> removedRewardModels;
306 if (keptRewardModels.find(rewModel.first) == keptRewardModels.end()) {
307 removedRewardModels.insert(rewModel.first);
310 for (
auto const& rewModelName : removedRewardModels) {
315template<
typename ValueType,
typename RewardModelType>
320template<
typename ValueType,
typename RewardModelType>
323 return this->rewardModels.begin()->first;
326template<
typename ValueType,
typename RewardModelType>
328 return !this->rewardModels.empty();
331template<
typename ValueType,
typename RewardModelType>
334 return this->rewardModels.cbegin()->second;
337template<
typename ValueType,
typename RewardModelType>
340 return this->rewardModels.begin()->second;
343template<
typename ValueType,
typename RewardModelType>
345 return this->rewardModels.size();
347template<
typename ValueType,
typename RewardModelType>
349 return stateLabeling;
352template<
typename ValueType,
typename RewardModelType>
354 return stateLabeling;
357template<
typename ValueType,
typename RewardModelType>
359 return static_cast<bool>(choiceLabeling);
362template<
typename ValueType,
typename RewardModelType>
364 return choiceLabeling.value();
367template<
typename ValueType,
typename RewardModelType>
369 return choiceLabeling;
372template<
typename ValueType,
typename RewardModelType>
374 return choiceLabeling;
377template<
typename ValueType,
typename RewardModelType>
379 return static_cast<bool>(stateValuations);
382template<
typename ValueType,
typename RewardModelType>
384 return stateValuations.value();
387template<
typename ValueType,
typename RewardModelType>
389 return stateValuations;
392template<
typename ValueType,
typename RewardModelType>
394 return stateValuations;
397template<
typename ValueType,
typename RewardModelType>
399 return static_cast<bool>(choiceOrigins);
402template<
typename ValueType,
typename RewardModelType>
404 return choiceOrigins.value();
407template<
typename ValueType,
typename RewardModelType>
409 return choiceOrigins;
412template<
typename ValueType,
typename RewardModelType>
414 return choiceOrigins;
417template<
typename ValueType,
typename RewardModelType>
423template<
typename ValueType,
typename RewardModelType>
425 std::size_t seed = 0;
426 boost::hash_combine(seed, transitionMatrix.hash());
427 boost::hash_combine(seed, stateLabeling.hash());
428 for (
auto const& rewModel : rewardModels) {
429 boost::hash_combine(seed, rewModel.second.hash());
431 if (choiceLabeling) {
432 boost::hash_combine(seed, choiceLabeling->hash());
434 if (stateValuations) {
435 boost::hash_combine(seed, stateValuations->hash());
438 boost::hash_combine(seed, choiceOrigins.value()->hash());
443template<
typename ValueType,
typename RewardModelType>
445 out <<
"-------------------------------------------------------------- \n";
451template<
typename ValueType,
typename RewardModelType>
454 out <<
"State Labels: \t";
456 out <<
"Choice Labels: \t";
462 out <<
"-------------------------------------------------------------- \n";
465template<
typename ValueType,
typename RewardModelType>
467 if (this->rewardModels.size()) {
468 std::vector<std::string> rewardModelNames;
469 std::for_each(this->rewardModels.cbegin(), this->rewardModels.cend(),
470 [&rewardModelNames](
typename std::pair<std::string, RewardModelType>
const& nameRewardModelPair) {
471 if (nameRewardModelPair.first.empty()) {
472 rewardModelNames.push_back(
"(default)");
474 rewardModelNames.push_back(nameRewardModelPair.first);
477 out <<
"Reward Models: " << boost::join(rewardModelNames,
", ") <<
'\n';
479 out <<
"Reward Models: none\n";
483template<
typename ValueType,
typename RewardModelType>
484void Model<ValueType, RewardModelType>::writeDotToStream(std::ostream& outStream,
size_t maxWidthLabel,
bool includeLabeling,
486 std::vector<ValueType>
const* secondValue, std::vector<uint_fast64_t>
const* stateColoring,
487 std::vector<std::string>
const* colors, std::vector<uint_fast64_t>*,
bool finalizeOutput)
const {
488 outStream <<
"digraph model {\n";
491 for (uint_fast64_t state = 0, highestStateIndex = this->getNumberOfStates() - 1; state <= highestStateIndex; ++state) {
492 if (subsystem ==
nullptr || subsystem->
get(state)) {
493 outStream <<
"\t" << state;
494 if (includeLabeling || firstValue !=
nullptr || secondValue !=
nullptr || stateColoring !=
nullptr || hasStateValuations()) {
498 if (includeLabeling || firstValue !=
nullptr || secondValue !=
nullptr || hasStateValuations()) {
499 outStream <<
"label = \"" << state;
500 if (hasStateValuations()) {
501 std::string stateInfo = getStateValuations().toString(state);
502 std::vector<std::string> results;
503 boost::split(results, stateInfo, [](
char c) {
return c ==
','; });
509 if (includeLabeling) {
515 outStream << this->additionalDotStateInfo(state);
518 if (firstValue !=
nullptr || secondValue !=
nullptr) {
520 if (firstValue !=
nullptr) {
521 outStream << (*firstValue)[state];
522 if (secondValue !=
nullptr) {
526 if (secondValue !=
nullptr) {
527 outStream << (*secondValue)[state];
534 if (stateColoring !=
nullptr && colors !=
nullptr) {
536 outStream <<
" style = filled, fillcolor = " << (*colors)[(*stateColoring)[state]];
546 if (finalizeOutput) {
551template<
typename ValueType,
typename RewardModelType>
554 "Exporting a large model to json. This might take some time and will result in a very large file.");
555 using JsonValueType = storm::RationalNumber;
559 stateChoicesJson[
"id"] = state;
564 stateChoicesJson[
"lab"] = labels;
566 for (
auto const& rm : rewardModels) {
567 if (rm.second.hasStateRewards()) {
568 auto const& r = rm.second.getStateReward(state);
574 if (!stateRewardsJson.empty()) {
575 stateChoicesJson[
"rew"] = std::move(stateRewardsJson);
583 rateForProbabilityScaling = ctmc->getExitRateVector()[state];
587 if (ma->isMarkovianState(state)) {
601 if (!choiceLabels.empty()) {
602 choiceJson[
"lab"] = choiceLabels;
605 choiceJson[
"id"] = choiceIndex;
607 for (
auto const& rm : rewardModels) {
608 if (rm.second.hasStateActionRewards()) {
609 auto r = rm.second.getStateActionReward(choiceIndex);
615 if (!choiceRewardsJson.empty()) {
616 choiceJson[
"rew"] = std::move(choiceRewardsJson);
619 for (
auto const& entry : transitionMatrix.getRow(choiceIndex)) {
621 successor[
"id"] = entry.getColumn();
623 successors.push_back(successor);
625 choiceJson[
"succ"] = std::move(successors);
626 choicesJson.push_back(choiceJson);
628 stateChoicesJson[
"c"] = std::move(choicesJson);
629 output.push_back(std::move(stateChoicesJson));
636 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Json export not implemented for this model type.");
639template<
typename ValueType,
typename RewardModelType>
644template<
typename ValueType,
typename RewardModelType>
646 return this->stateLabeling.getLabelsOfState(state);
649template<
typename ValueType,
typename RewardModelType>
652 if (entry.getColumn() != state) {
662template<
typename ValueType,
typename RewardModelType>
667template<
typename ValueType,
typename RewardModelType>
669 return std::is_same<ValueType, storm::RationalFunction>::value;
672template<
typename ValueType,
typename RewardModelType>
677template<
typename ValueType,
typename RewardModelType>
692template<
typename ValueType,
typename RewardModelType>
707template<
typename ValueType,
typename RewardModelType>
712template<
typename ValueType,
typename RewardModelType>
714 return *this->stochasticTolerance;
717template<
typename ValueType,
typename RewardModelType>
719 *this->stochasticTolerance = tolerance;
722template<
typename ValueType,
typename RewardModelType>
724 return this->rewardModels;
727template<
typename ValueType,
typename RewardModelType>
729 return this->rewardModels;
737 std::set<storm::RationalFunctionVariable> result;
740 result.insert(tmp.begin(), tmp.end());
747 auto const& ctmc = model.template as<storm::models::sparse::Ctmc<storm::RationalFunction>>();
750 auto const& ma = model.template as<storm::models::sparse::MarkovAutomaton<storm::RationalFunction>>();
760 parameters.insert(rewardParameters.begin(), rewardParameters.end());
761 std::set<storm::RationalFunctionVariable> rateParameters =
getRateParameters(model);
762 parameters.insert(rateParameters.begin(), rateParameters.end());
static constexpr double DefaultModelTolerance
The default tolerance up to which probabilities and rates are considered equal.
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
Retrieves the unique reward model, if there exists exactly one.
std::optional< storm::storage::sparse::Valuations > const & getOptionalStateValuations() const
Retrieves an optional value that contains the state valuations if there are some.
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...
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).
Model & operator=(Model< ValueType, RewardModelType > const &other)
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
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
Prints information about the reward models to the specified stream.
std::set< std::string > getLabelsOfState(storm::storage::sparse::state_type state) const
Retrieves the set of labels attached to the given state.
storm::storage::sparse::Valuations const & getStateValuations() const
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
void addRewardModel(std::string const &rewardModelName, RewardModelType const &rewModel)
Adds a reward model to the model.
ValueType const & getStochasticTolerance() const
Retrieves the tolerance up to which the model components are considered valid.
std::shared_ptr< storm::storage::sparse::ChoiceOrigins > const & getChoiceOrigins() const
void setStochasticTolerance(ValueType const &tolerance)
Sets the tolerance up to which the model components are considered valid.
Model(Model< ValueType, RewardModelType > const &other)
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
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
virtual void writeJsonToStream(std::ostream &outStream) const
Writes a JSON representation of the model to the given stream.
void printModelInformationHeaderToStream(std::ostream &out) const
Prints the information header (number of states and transitions) of the model to the specified stream...
std::optional< storm::models::sparse::ChoiceLabeling > const & getOptionalChoiceLabeling() const
Retrieves an optional value that contains the choice labeling if there is one.
StandardRewardModel< ValueType > RewardModelType
virtual bool supportsParameters() const override
Checks whether the model supports parameters.
virtual bool hasUniqueRewardModel() const override
Retrieves whether the model has a unique reward model.
virtual std::string additionalDotStateInfo(uint64_t state) const
Return a string that is additonally added to the state information in the dot stream.
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.
Provides access to valuations of variables for a set of entities (e.g.
#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)
TargetType convertNumber(SourceType const &number)
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
std::optional< ValueType > stochasticTolerance