26template<
typename ValueType,
typename TargetValueType>
33 std::vector<TargetValueType> branchProbabilities;
35 for (uint64_t rowIndex = 0; rowIndex < matrix.
getRowCount(); ++rowIndex) {
36 auto const& row = matrix.
getRow(rowIndex);
37 for (
auto const& entry : row) {
38 umb.branchToTarget->push_back(entry.getColumn());
42 auto rowProbs = std::span<TargetValueType>(branchProbabilities.end() - row.getNumberOfEntries(), branchProbabilities.end());
45 std::for_each(rowProbs.begin(), rowProbs.end(), [&rowSum](TargetValueType& entry) { entry /= rowSum; });
49 umb.branchToProbability.template set<TargetValueType>(std::move(branchProbabilities));
53 for (
auto const& labelName : labeling.
getLabels()) {
54 if (labelName ==
"init") {
57 STORM_LOG_ASSERT(
umb.index.aps(),
"Model index must have annotations to store state labels.");
58 auto const name =
umb.index.findAPName(labelName);
59 STORM_LOG_ASSERT(name.has_value(),
"Label '" << labelName <<
"' not found in the model index.");
60 auto& aps =
umb.aps(
true).value();
61 STORM_LOG_ASSERT(!aps.contains(*name),
"Annotation for label '" << labelName <<
"' already exists.");
62 auto& annotation = aps[*name];
63 annotation.states.emplace().values.template set<bool>(labeling.
getStates(labelName));
69 auto& choiceToAction =
umb.choiceActions.emplace().values.emplace();
77 auto actionStrings =
StringsBuilder(
umb.choiceActions->strings.emplace(),
umb.choiceActions->stringMapping.emplace());
79 auto const emptyStringIndex = actionStrings.push_back(
"");
80 STORM_LOG_ASSERT(emptyStringIndex == 0,
"Action index for empty action string must be 0.");
87 actionStrings.finalize();
88 return actionStrings.size();
94 auto& choiceToAction =
umb.choiceActions.emplace().values.emplace(labeling.
getNumberOfItems(), 0);
95 auto actionStrings =
StringsBuilder(
umb.choiceActions->strings.emplace(),
umb.choiceActions->stringMapping.emplace());
100 for (
auto const& labelName : labels) {
101 auto const& currentChoices = labeling.
getChoices(labelName);
102 if (choicesWithAtLeastOneLabel.
size() == 0) {
104 choicesWithAtLeastOneLabel = currentChoices;
105 }
else if (choicesWithMultipleLabels.
size() == 0) {
107 choicesWithMultipleLabels = choicesWithAtLeastOneLabel & currentChoices;
108 choicesWithAtLeastOneLabel |= currentChoices;
111 choicesWithMultipleLabels |= choicesWithAtLeastOneLabel & currentChoices;
112 choicesWithAtLeastOneLabel |= currentChoices;
117 if (!choicesWithAtLeastOneLabel.
full()) {
119 auto const emptyStringIndex = actionStrings.push_back(
"");
120 STORM_LOG_ASSERT(emptyStringIndex == 0,
"Action index for empty action string must be 0.");
125 auto setChoices = [&choiceToAction, &actionStrings](
storm::storage::BitVector const& choices, std::string_view actionName) {
126 auto choiceIt = choices.begin();
127 auto const choiceItEnd = choices.end();
128 if (choiceIt != choiceItEnd) {
130 auto const actionIndex = actionStrings.findOrPushBack(actionName);
131 for (; choiceIt != choiceItEnd; ++choiceIt) {
132 choiceToAction[*choiceIt] = actionIndex;
136 if (choicesWithMultipleLabels.
empty()) {
137 for (
auto const& labelName : labels) {
138 setChoices(labeling.
getChoices(labelName), labelName);
142 for (
auto const& labelName : labels) {
143 setChoices(labeling.
getChoices(labelName) & choicesWithMultipleLabels, labelName);
149 for (
auto const& choice : choicesWithMultipleLabels) {
152 if (!action.empty()) {
157 choiceToAction[choice] = actionStrings.findOrPushBack(action);
159 return actionStrings.
size();
162template<
typename TargetValueType>
164 using ValueType = std::ranges::range_value_t<
decltype(values)>;
165 if constexpr (std::is_same_v<ValueType, TargetValueType>) {
166 target.template set<TargetValueType>(std::forward<
decltype(values)>(values));
172template<
typename ValueType,
typename TargetValueType>
175 STORM_LOG_ASSERT(
umb.index.rewards(),
"Model index must have rewards to store state labels.");
176 auto const rewardIdentifier =
umb.index.findRewardName(rewardModelName);
177 STORM_LOG_ASSERT(rewardIdentifier.has_value(),
"Reward '" << rewardModelName <<
"' not found in the model index.");
178 auto& umbRewards =
umb.rewards(
true).value();
179 STORM_LOG_ASSERT(!umbRewards.contains(*rewardIdentifier),
"Reward '" << *rewardIdentifier <<
"' already exists in the umb model.");
180 auto& rewardAnnotation = umbRewards[*rewardIdentifier];
188 std::vector<TargetValueType> branchRewards;
191 "The number of rows in the transition matrix and the reward model do not match.");
192 for (uint64_t rowIndex = 0; rowIndex < transitionMatrix.
getRowCount(); ++rowIndex) {
193 auto const& transitionRow = transitionMatrix.
getRow(rowIndex);
195 auto rewIt = rewardRow.begin();
197 for (
auto const& entry : transitionRow) {
198 while (rewIt != rewardRow.end() && rewIt->getColumn() < entry.getColumn()) {
201 if (rewIt == rewardRow.end() || rewIt->getColumn() > entry.getColumn()) {
204 STORM_LOG_ASSERT(rewIt->getColumn() == entry.getColumn(),
"Unexpected column in reward model.");
209 rewardAnnotation.branches.emplace().values.template set<TargetValueType>(std::move(branchRewards));
213template<
typename ValueType,
typename TargetValueType>
215 STORM_LOG_ASSERT(playerNames.empty() && stateToPlayerIndices.empty(),
"Expected initially empty player names and indices.");
220 for (
auto const& [name, index] : origPlayerNamesToIndex) {
221 playerNames[index] = name;
222 unnamedIndices.
set(index,
false);
224 auto freshPlayerName = [&origPlayerNamesToIndex](uint64_t i) {
225 std::string name =
"unnamed_player" + std::to_string(i);
226 while (origPlayerNamesToIndex.contains(name)) {
231 for (
auto const unnamedIndex : unnamedIndices) {
232 playerNames[unnamedIndex] = freshPlayerName(unnamedIndex);
238 bool hasInvalidIndices =
false;
241 stateToPlayerIndices.push_back(invalPlayerIndex);
242 hasInvalidIndices =
true;
245 stateToPlayerIndices.push_back(index);
248 if (hasInvalidIndices) {
249 playerNames.push_back(freshPlayerName(invalPlayerIndex));
253template<
typename ValueType>
257 switch (options.valueType) {
258 case OptionType::Default:
259 if constexpr (std::is_same_v<ValueType, double>) {
260 return ExportType::Double;
261 }
else if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
262 return ExportType::Rational;
263 }
else if constexpr (std::is_same_v<ValueType, storm::Interval>) {
264 return ExportType::DoubleInterval;
266 static_assert(std::is_same_v<ValueType, storm::RationalInterval>,
"Unhandled value type");
267 return ExportType::RationalInterval;
269 case OptionType::Double:
270 return ExportType::Double;
271 case OptionType::Rational:
272 return ExportType::Rational;
273 case OptionType::DoubleInterval:
274 return ExportType::DoubleInterval;
275 case OptionType::RationalInterval:
276 return ExportType::RationalInterval;
278 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Unexpected value type.");
281template<
typename ValueType>
286 index.
fileData->setCreationDateToNow();
300 ts.time = Stochastic;
308 case MarkovAutomaton:
309 ts.time = UrgentStochastic;
317 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Unexpected model type.");
325 ts.numBranchActions = 0;
329 ts.branchProbabilityType = {exportType,
defaultBitSize(exportType)};
331 ts.exitRateType = ts.branchProbabilityType;
338 if (hasRewards || hasAps) {
344 auto& rewards = index.
rewards(
true).value();
345 for (
auto const& [rewardModelName, rewardModel] : model.
getRewardModels()) {
347 STORM_LOG_THROW(!rewards.contains(identifier), storm::exceptions::WrongFormatException,
"Reward id '" << identifier <<
"' already exists.");
348 auto& rewardIndex = rewards[identifier];
349 if (!rewardModelName.empty()) {
350 rewardIndex.alias = rewardModelName;
352 if (rewardModel.hasNegativeRewards()) {
353 if (!rewardModel.hasPositiveRewards()) {
354 rewardIndex.upper = 0;
357 rewardIndex.lower = 0;
360 if (rewardModel.hasStateRewards()) {
361 rewardIndex.appliesTo.push_back(States);
363 if (rewardModel.hasStateActionRewards()) {
364 rewardIndex.appliesTo.push_back(Choices);
366 if (rewardModel.hasTransitionRewards()) {
367 rewardIndex.appliesTo.push_back(Branches);
375 auto& aps = index.
aps(
true).value();
377 if (label ==
"init") {
381 STORM_LOG_THROW(!aps.contains(identifier), storm::exceptions::WrongFormatException,
"AP with identifier '" << identifier <<
"' already exists.");
382 auto& apIndex = aps[identifier];
383 apIndex.alias = label;
390template<
typename ValueType,
typename TargetValueType>
395 auto pomdp = model.template as<storm::models::sparse::Pomdp<ValueType>>();
396 if (!
pomdp->isCanonic()) {
399 auto newOptions = options;
416 "Choice origins and choice labeling are both present but only choice origins will be used as actions for UMB export.");
426 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"State valuations are not yet supported for UMB export.");
431 bool normalize = model.
isOfType(Ctmc);
433 STORM_LOG_WARN(
"Translating from non-exact to exact model representation. This may lead to rounding errors.");
445 auto const& ctmc = *model.template as<storm::models::sparse::Ctmc<ValueType>>();
447 }
else if (model.
isOfType(MarkovAutomaton)) {
448 auto const& ma = *model.template as<storm::models::sparse::MarkovAutomaton<ValueType>>();
452 auto const&
pomdp = *model.template as<storm::models::sparse::Pomdp<ValueType>>();
457 auto const& smg = *model.template as<storm::models::sparse::Smg<ValueType>>();
461 "Exporting SMG to UMB with zero or one players. The model will be recognized as MDP or DTMC on import.");
464 "Unexpected model type for UMB export: " << model.
getType());
470template<
typename ValueType>
474 switch (options.valueType) {
491 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.
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
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)
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
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
storm::OptionalRef< AnnotationMap > aps(bool createIfMissing=false)
std::optional< FileData > fileData