27template<
typename ValueType,
typename TargetValueType>
34 std::vector<TargetValueType> branchProbabilities;
36 for (uint64_t rowIndex = 0; rowIndex < matrix.
getRowCount(); ++rowIndex) {
37 auto const& row = matrix.
getRow(rowIndex);
38 for (
auto const& entry : row) {
39 umb.branchToTarget->push_back(entry.getColumn());
43 auto rowProbs = std::span<TargetValueType>(branchProbabilities.end() - row.getNumberOfEntries(), branchProbabilities.end());
46 std::for_each(rowProbs.begin(), rowProbs.end(), [&rowSum](TargetValueType& entry) { entry /= rowSum; });
50 umb.branchToProbability.template set<TargetValueType>(std::move(branchProbabilities));
54 for (
auto const& labelName : labeling.
getLabels()) {
55 if (labelName ==
"init") {
58 STORM_LOG_ASSERT(
umb.index.aps(),
"Model index must have annotations to store state labels.");
59 auto const name =
umb.index.findAPName(labelName);
60 STORM_LOG_ASSERT(name.has_value(),
"Label '" << labelName <<
"' not found in the model index.");
61 auto& aps =
umb.aps(
true).value();
62 STORM_LOG_ASSERT(!aps.contains(*name),
"Annotation for label '" << labelName <<
"' already exists.");
63 auto& annotation = aps[*name];
64 annotation.states.emplace().values.template set<bool>(labeling.
getStates(labelName));
70 auto& choiceToAction =
umb.choiceActions.emplace().values.emplace();
78 auto actionStrings =
StringsBuilder(
umb.choiceActions->strings.emplace(),
umb.choiceActions->stringMapping.emplace());
80 [[maybe_unused]]
auto const emptyStringIndex = actionStrings.push_back(
"");
81 STORM_LOG_ASSERT(emptyStringIndex == 0,
"Action index for empty action string must be 0.");
88 actionStrings.finalize();
89 return actionStrings.size();
95 auto& choiceToAction =
umb.choiceActions.emplace().values.emplace(labeling.
getNumberOfItems(), 0);
96 auto actionStrings =
StringsBuilder(
umb.choiceActions->strings.emplace(),
umb.choiceActions->stringMapping.emplace());
101 for (
auto const& labelName : labels) {
102 auto const& currentChoices = labeling.
getChoices(labelName);
103 if (choicesWithAtLeastOneLabel.
size() == 0) {
105 choicesWithAtLeastOneLabel = currentChoices;
106 }
else if (choicesWithMultipleLabels.
size() == 0) {
108 choicesWithMultipleLabels = choicesWithAtLeastOneLabel & currentChoices;
109 choicesWithAtLeastOneLabel |= currentChoices;
112 choicesWithMultipleLabels |= choicesWithAtLeastOneLabel & currentChoices;
113 choicesWithAtLeastOneLabel |= currentChoices;
118 if (choicesWithAtLeastOneLabel.
size() == 0 || !choicesWithAtLeastOneLabel.
full()) {
120 [[maybe_unused]]
auto const emptyStringIndex = actionStrings.push_back(
"");
121 STORM_LOG_ASSERT(emptyStringIndex == 0,
"Action index for empty action string must be 0.");
126 auto setChoices = [&choiceToAction, &actionStrings](
storm::storage::BitVector const& choices, std::string_view actionName) {
127 auto choiceIt = choices.begin();
128 auto const choiceItEnd = choices.end();
129 if (choiceIt != choiceItEnd) {
131 auto const actionIndex = actionStrings.findOrPushBack(actionName);
132 for (; choiceIt != choiceItEnd; ++choiceIt) {
133 choiceToAction[*choiceIt] = actionIndex;
137 if (choicesWithMultipleLabels.
empty()) {
138 for (
auto const& labelName : labels) {
139 setChoices(labeling.
getChoices(labelName), labelName);
143 for (
auto const& labelName : labels) {
144 setChoices(labeling.
getChoices(labelName) & choicesWithMultipleLabels, labelName);
150 for (uint64_t choice : choicesWithMultipleLabels) {
153 if (!action.empty()) {
158 choiceToAction[choice] = actionStrings.findOrPushBack(action);
160 return actionStrings.
size();
163template<
typename TargetValueType>
165 using ValueType = std::ranges::range_value_t<
decltype(values)>;
166 if constexpr (std::is_same_v<ValueType, TargetValueType>) {
167 target.template set<TargetValueType>(std::forward<
decltype(values)>(values));
173template<
typename ValueType,
typename TargetValueType>
176 STORM_LOG_ASSERT(
umb.index.rewards(),
"Model index must have rewards to store state labels.");
177 auto const rewardIdentifier =
umb.index.findRewardName(rewardModelName);
178 STORM_LOG_ASSERT(rewardIdentifier.has_value(),
"Reward '" << rewardModelName <<
"' not found in the model index.");
179 auto& umbRewards =
umb.rewards(
true).value();
180 STORM_LOG_ASSERT(!umbRewards.contains(*rewardIdentifier),
"Reward '" << *rewardIdentifier <<
"' already exists in the umb model.");
181 auto& rewardAnnotation = umbRewards[*rewardIdentifier];
189 std::vector<TargetValueType> branchRewards;
192 "The number of rows in the transition matrix and the reward model do not match.");
193 for (uint64_t rowIndex = 0; rowIndex < transitionMatrix.
getRowCount(); ++rowIndex) {
194 auto const& transitionRow = transitionMatrix.
getRow(rowIndex);
196 auto rewIt = rewardRow.begin();
198 for (
auto const& entry : transitionRow) {
199 while (rewIt != rewardRow.end() && rewIt->getColumn() < entry.getColumn()) {
202 if (rewIt == rewardRow.end() || rewIt->getColumn() > entry.getColumn()) {
205 STORM_LOG_ASSERT(rewIt->getColumn() == entry.getColumn(),
"Unexpected column in reward model.");
210 rewardAnnotation.branches.emplace().values.template set<TargetValueType>(std::move(branchRewards));
214template<
typename ValueType,
typename TargetValueType>
216 STORM_LOG_ASSERT(playerNames.empty() && stateToPlayerIndices.empty(),
"Expected initially empty player names and indices.");
221 for (
auto const& [name, index] : origPlayerNamesToIndex) {
222 playerNames[index] = name;
223 unnamedIndices.
set(index,
false);
225 auto freshPlayerName = [&origPlayerNamesToIndex](uint64_t i) {
226 std::string name =
"unnamed_player" + std::to_string(i);
227 while (origPlayerNamesToIndex.contains(name)) {
232 for (uint64_t unnamedIndex : unnamedIndices) {
233 playerNames[unnamedIndex] = freshPlayerName(unnamedIndex);
239 bool hasInvalidIndices =
false;
242 stateToPlayerIndices.push_back(invalPlayerIndex);
243 hasInvalidIndices =
true;
246 stateToPlayerIndices.push_back(index);
249 if (hasInvalidIndices) {
250 playerNames.push_back(freshPlayerName(invalPlayerIndex));
254template<
typename ValueType>
258 switch (options.valueType) {
259 case OptionType::Default:
260 if constexpr (std::is_same_v<ValueType, double>) {
261 return ExportType::Double;
262 }
else if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
263 return ExportType::Rational;
264 }
else if constexpr (std::is_same_v<ValueType, storm::Interval>) {
265 return ExportType::DoubleInterval;
267 static_assert(std::is_same_v<ValueType, storm::RationalInterval>,
"Unhandled value type");
268 return ExportType::RationalInterval;
270 case OptionType::Double:
271 return ExportType::Double;
272 case OptionType::Rational:
273 return ExportType::Rational;
274 case OptionType::DoubleInterval:
275 return ExportType::DoubleInterval;
276 case OptionType::RationalInterval:
277 return ExportType::RationalInterval;
279 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Unexpected value type.");
282template<
typename ValueType>
287 index.
fileData->setCreationDateToNow();
301 ts.time = Stochastic;
309 case MarkovAutomaton:
310 ts.time = UrgentStochastic;
318 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Unexpected model type.");
326 ts.numBranchActions = 0;
330 ts.branchProbabilityType = {exportType,
defaultBitSize(exportType)};
332 ts.exitRateType = ts.branchProbabilityType;
339 if (hasRewards || hasAps) {
345 auto& rewards = index.
rewards(
true).value();
346 for (
auto const& [rewardModelName, rewardModel] : model.
getRewardModels()) {
348 STORM_LOG_THROW(!rewards.contains(identifier), storm::exceptions::WrongFormatException,
"Reward id '" << identifier <<
"' already exists.");
349 auto& rewardIndex = rewards[identifier];
350 if (!rewardModelName.empty()) {
351 rewardIndex.alias = rewardModelName;
353 if (rewardModel.hasNegativeRewards()) {
354 if (!rewardModel.hasPositiveRewards()) {
355 rewardIndex.upper = 0;
358 rewardIndex.lower = 0;
361 if (rewardModel.hasStateRewards()) {
362 rewardIndex.appliesTo.push_back(States);
364 if (rewardModel.hasStateActionRewards()) {
365 rewardIndex.appliesTo.push_back(Choices);
367 if (rewardModel.hasTransitionRewards()) {
368 rewardIndex.appliesTo.push_back(Branches);
376 auto& aps = index.
aps(
true).value();
378 if (label ==
"init") {
382 STORM_LOG_THROW(!aps.contains(identifier), storm::exceptions::WrongFormatException,
"AP with identifier '" << identifier <<
"' already exists.");
383 auto& apIndex = aps[identifier];
384 apIndex.alias = label;
393 for (uint64_t classIndex = 0; classIndex < valuations.numClasses(); ++classIndex) {
394 descr.
classes.push_back(valuations.getClassDescription(classIndex));
396 if (valuations.hasStrings()) {
406 auto pomdp = model.template as<storm::models::sparse::Pomdp<ValueType>>();
407 if (
pomdp->hasObservationValuations()) {
411 index.
valuations->observations = createDescription(
pomdp->getObservationValuations().getStorage());
416template<
typename ValueType,
typename TargetValueType>
421 auto pomdp = model.template as<storm::models::sparse::Pomdp<ValueType>>();
422 if (!
pomdp->isCanonic()) {
425 auto newOptions = options;
442 "Choice origins and choice labeling are both present but only choice origins will be used as actions for UMB export.");
456 auto pomdp = model.template as<storm::models::sparse::Pomdp<ValueType>>();
457 if (
pomdp->hasObservationValuations()) {
464 bool normalize = model.
isOfType(Ctmc);
466 STORM_LOG_WARN(
"Translating from non-exact to exact model representation. This may lead to rounding errors.");
478 auto const& ctmc = *model.template as<storm::models::sparse::Ctmc<ValueType>>();
480 }
else if (model.
isOfType(MarkovAutomaton)) {
481 auto const& ma = *model.template as<storm::models::sparse::MarkovAutomaton<ValueType>>();
485 auto const&
pomdp = *model.template as<storm::models::sparse::Pomdp<ValueType>>();
490 auto const& smg = *model.template as<storm::models::sparse::Smg<ValueType>>();
494 "Exporting SMG to UMB with zero or one players. The model will be recognized as MDP or DTMC on import.");
497 "Unexpected model type for UMB export: " << model.
getType() <<
".");
503template<
typename ValueType>
507 switch (options.valueType) {
524 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Unexpected value type.");
storm::models::sparse::Dtmc< double > Dtmc
storm::models::sparse::Mdp< double > Mdp
virtual ModelType getType() const
Return the actual type of the model.
bool isOfType(storm::models::ModelType const &modelType) const
Checks whether the model is of the given type.
virtual bool isPartiallyObservable() const
This class manages the labeling of the choice space with a number of (atomic) labels.
storm::storage::BitVector const & getChoices(std::string const &label) const
Returns the labeling of choices associated with the given label.
std::set< std::string > getLabelsOfChoice(uint64_t choice) const
Retrieves the set of labels attached to the given choice.
std::set< std::string > getLabels() const
Retrieves the set of labels contained in this labeling.
bool containsLabel(std::string const &label) const
Checks whether a label is registered within this labeling.
std::size_t getNumberOfItems() const
Returns the number of items managed by this object.
std::size_t getNumberOfLabels() const
Returns the number of labels managed by this object.
Base class for all sparse models.
storm::models::sparse::ChoiceLabeling const & getChoiceLabeling() const
Retrieves the labels for the choices of the model.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
storm::storage::sparse::Valuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
virtual uint_fast64_t getNumberOfChoices() const override
Returns the number of choices ine the model.
std::shared_ptr< storm::storage::sparse::ChoiceOrigins > const & getChoiceOrigins() const
Retrieves the origins of the choices of the model.
bool hasChoiceLabeling() const
Retrieves whether this model has a labeling of the choices.
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
Returns the state labeling associated with this model.
virtual uint_fast64_t getNumberOfTransitions() const override
Returns the number of (non-zero) transitions of the model.
bool hasChoiceOrigins() const
Retrieves whether this model was build with choice origins.
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
This class represents a stochastic multiplayer game.
std::vector< storm::storage::PlayerIndex > const & getStatePlayerIndications() const
std::map< std::string, storm::storage::PlayerIndex > const & getPlayerNamesToIndex() const
uint64_t getNumberOfPlayers() const
storm::storage::SparseMatrix< ValueType > const & getTransitionRewardMatrix() const
Retrieves the transition rewards of the reward model.
bool hasTransitionRewards() const
Retrieves whether the reward model has transition rewards.
std::vector< ValueType > const & getStateActionRewardVector() const
Retrieves the state-action rewards of the reward model.
std::vector< ValueType > const & getStateRewardVector() const
Retrieves the state rewards of the reward model.
bool hasStateRewards() const
Retrieves whether the reward model has state rewards.
bool hasStateActionRewards() const
Retrieves whether the reward model has state-action rewards.
This class manages the labeling of the state space with a number of (atomic) labels.
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the labeling of states associated with the given label.
A bit vector that is internally represented as a vector of 64-bit values.
void complement()
Negates all bits in the bit vector.
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.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
index_type getEntryCount() const
Returns the number of entries in the matrix.
std::vector< index_type > const & getRowIndices() const
Returns the entry indices within the given row.
bool hasTrivialRowGrouping() const
Retrieves whether the matrix has a trivial row grouping.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
This class represents the origin of the choices of a model in terms of the input model specification ...
virtual uint_fast64_t getNumberOfIdentifiers() const =0
uint_fast64_t getIdentifier(uint_fast64_t choiceIndex) const
static uint_fast64_t getIdentifierForChoicesWithNoOrigin()
uint_fast64_t getNumberOfChoices() const
std::string const & getIdentifierInfo(uint_fast64_t identifier) const
ValuationsStorage const & getStorage() const
Stores valuations of variables for a set of entities (e.g.
storm::umb::UmbModel::Valuation getRawUmbData() const
Exports a snapshot of the raw UMB model valuation data (packed bytes, optional class mapping,...
Represents a model in the UMB format.
TO1< bool > stateIsMarkovian
bool validate(std::ostream &errors) const
Validates the given UMB model and writes potential errors to the given output stream.
TO1< bool > stateIsInitial
TO1< AnyValueType > stateToExitRate
TO1< uint32_t > stateToPlayer
std::optional< Observations > stateObservations
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
PlayerIndex const INVALID_PLAYER_INDEX
void rewardToUmb(std::string const &rewardModelName, storm::models::sparse::StandardRewardModel< ValueType > const &rewardModel, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::umb::UmbModel &umb)
storm::umb::Type getExportType(ExportOptions const &options)
void setIndexInformation(storm::models::sparse::Model< ValueType > const &model, storm::umb::ModelIndex &index, ExportOptions const &options)
uint64_t choiceLabelingToUmb(storm::models::sparse::ChoiceLabeling const &labeling, storm::umb::UmbModel &umb)
void setGenericVector(storm::umb::GenericVector &target, std::ranges::input_range auto &&values)
uint64_t choiceOriginsToUmb(storm::storage::sparse::ChoiceOrigins const &choiceOrigins, storm::umb::UmbModel &umb)
void playerIndicesToUmb(storm::models::sparse::Smg< ValueType > const &smg, auto &playerNames, auto &stateToPlayerIndices)
void transitionMatrixToUmb(storm::storage::SparseMatrix< ValueType > const &matrix, storm::umb::UmbModel &umb, bool const normalize)
void stateLabelingToUmb(storm::models::sparse::StateLabeling const &labeling, storm::umb::UmbModel &umb)
void sparseModelToUmb(storm::models::sparse::Model< ValueType > const &model, UmbModel &umbModel, ExportOptions const &options)
Import and export of umb files.
storm::umb::UmbModel sparseModelToUmb(storm::models::sparse::Model< ValueType > const &model, ExportOptions const &options)
template storm::umb::UmbModel sparseModelToUmb< storm::RationalInterval >(storm::models::sparse::Model< storm::RationalInterval > const &model, ExportOptions const &options)
uint64_t defaultBitSize(Type const type)
Returns the default size (in bits) of a type, if available.
template storm::umb::UmbModel sparseModelToUmb< double >(storm::models::sparse::Model< double > const &model, ExportOptions const &options)
template storm::umb::UmbModel sparseModelToUmb< storm::Interval >(storm::models::sparse::Model< storm::Interval > const &model, ExportOptions const &options)
template storm::umb::UmbModel sparseModelToUmb< storm::RationalNumber >(storm::models::sparse::Model< storm::RationalNumber > const &model, ExportOptions const &options)
std::vector< TargetType > convertNumericVector(std::vector< SourceType > const &oldVector)
Converts the given vector to the given ValueType Assumes that both, TargetType and SourceType are num...
bool isOne(ValueType const &a)
TargetType convertNumber(SourceType const &number)
carl::Interval< storm::RationalNumber > RationalInterval
static const bool IsExact
Describes all valuation classes for a set of entities (e.g.
std::vector< ValuationClassDescription > classes
std::optional< uint64_t > numStrings
bool allowChoiceLabelingAsActions
Whether export of choice origins is enabled.
bool allowChoiceOriginsAsActions
Whether export of choice origins is enabled.
ValueType
The type that is used for all kinds of values.
bool canonicizePomdp
Whether to canonicize POMDPs before export.
static std::string getValidIdentifierFromAlias(std::string const &alias)
Takes an alias (which can be an arbitrary string) and converts it to a valid identifier in [0-9a-z_-]...
static auto constexpr InvalidNumber
uint64_t numChoiceActions
std::optional< storm::SerializedEnum< ObservationsApplyToDeclaration > > observationsApplyTo
std::optional< std::vector< std::string > > playerNames
storm::OptionalRef< AnnotationMap > rewards(bool createIfMissing=false)
struct storm::umb::ModelIndex::TransitionSystem transitionSystem
std::optional< std::map< std::string, AnnotationMap > > annotations
std::optional< Valuations > valuations
storm::OptionalRef< AnnotationMap > aps(bool createIfMissing=false)
std::optional< FileData > fileData
std::optional< Values > observations
std::optional< Values > states