28 STORM_LOG_ASSERT(i + 1 < csr->size(),
"CSR index out of bounds: " << (i + 1) <<
" >= " << csr->size());
29 return std::ranges::iota_view(csr.value()[i], csr.value()[i + 1]);
32 return std::ranges::iota_view(i, i + 1);
36template<
typename ValueType>
44template<
typename ValueType>
48 bool const hasRowGroups = tsIndex.
numPlayers >= 1;
51 hasRowGroups ? tsIndex.numStates : 0u);
52 builder.setAccumulationMode(accumulationMode);
53 for (uint64_t stateIndex{0}; stateIndex < tsIndex.numStates; ++stateIndex) {
56 builder.newRowGroup(*choices.begin());
58 for (
auto const choiceIndex : choices) {
59 STORM_LOG_ASSERT(choiceIndex < tsIndex.numChoices,
"Choice index out of bounds.");
62 STORM_LOG_ASSERT(branchTarget < tsIndex.numStates,
"Branch target index out of bounds: " << branchTarget <<
" >= " << tsIndex.numStates);
63 builder.addNextValue(choiceIndex, branchTarget, branchValues[branchIndex]);
67 return builder.build(tsIndex.numChoices, tsIndex.numStates, hasRowGroups ? tsIndex.numStates : 0u);
70template<
typename ValueType>
74 [&umbModel, accumulationMode](
auto&& input) {
return createBranchMatrix<ValueType>(umbModel, input, accumulationMode); }, branchValues, sourceType);
77template<
typename ValueType>
81 std::ranges::views::transform([&defaultValue](
auto) -> ValueType {
return defaultValue; });
86 STORM_LOG_THROW(umbBitVector.size() >= size, storm::exceptions::WrongFormatException,
87 "Bit vector has unexpected size: " << umbBitVector.size() <<
" < " << size <<
".");
94 STORM_LOG_THROW(umbBitVector.has_value(), storm::exceptions::WrongFormatException,
"BitVector is not given but expected.");
104 if (umbModel.
index.
aps().has_value()) {
106 for (
auto const& [apName, apIndex] : aps.value()) {
107 STORM_LOG_THROW(umbModel.
aps().has_value() && umbModel.
aps()->contains(apName), storm::exceptions::WrongFormatException,
108 "Atomic proposition '" << apName <<
"' mentioned in index but no files were found.");
110 "Atomic proposition '" << apName <<
"' must be of boolean type.");
111 STORM_LOG_THROW(apIndex.appliesTo.size() == 1 && apIndex.appliesToStates(), storm::exceptions::WrongFormatException,
112 "Atomic proposition '" << apName <<
"' must apply only to states.");
113 auto const& ap = umbModel.
aps()->at(apName);
114 auto labelName = apIndex.alias.value_or(apName);
115 STORM_LOG_THROW(ap.states.has_value(), storm::exceptions::WrongFormatException,
"Atomic proposition '" << apName <<
"' has no states values.");
116 auto labeledStates =
createBitVector(ap.states->values.template get<bool>(), numStates);
119 "Label '" << labelName <<
"' is declared multiple times with different labellings.");
120 STORM_LOG_WARN(
"Ignoring additional declaration of label '" << labelName <<
"' as it is already defined with the same labelling.");
122 stateLabelling.
addLabel(labelName, std::move(labeledStates));
130 return stateLabelling;
140 bool const hasActionStrings = !actionStrings.empty();
141 STORM_LOG_THROW(!hasActionStrings || actionStrings.size() == numActions, storm::exceptions::WrongFormatException,
142 "Number of action strings does not match number of actions.");
145 uint64_t
const emptyActionIndex = hasActionStrings ? std::ranges::find(actionStrings,
"") - actionStrings.begin() : numActions;
148 auto const& choiceToChoiceAction = umbModel.
choiceActions->values.value();
150 for (uint64_t choiceIndex = 0; choiceIndex < numChoices; ++choiceIndex) {
151 auto const actionIndex = choiceToChoiceAction[choiceIndex];
152 STORM_LOG_ASSERT(actionIndex < numActions,
"Choice to action mapping out of bounds.");
153 if (hasActionStrings && actionIndex == emptyActionIndex) {
156 actionToLabels[actionIndex].set(choiceIndex);
160 if (hasActionStrings) {
161 for (uint64_t actionIndex = 0; actionIndex < numActions; ++actionIndex) {
162 if (actionIndex == emptyActionIndex) {
165 choiceLabeling.
addLabel(std::string(actionStrings[actionIndex]), std::move(actionToLabels[actionIndex]));
169 for (uint64_t actionIndex = 0; actionIndex < numActions; ++actionIndex) {
170 choiceLabeling.
addLabel(
"a" + std::to_string(actionIndex), std::move(actionToLabels[actionIndex]));
173 return choiceLabeling;
176template<
typename ValueType>
179 std::unordered_map<std::string, RewardModel> rewardModels;
182 for (
auto const& [rewName, rewIndex] : rewards.value()) {
184 "Reward " << rewName <<
"' mentioned in index but no files were found.");
185 auto const& rew = umbModel.
rewards()->at(rewName);
186 auto usedRewName = rewIndex.alias.value_or(rewName);
187 STORM_LOG_THROW(!rewardModels.contains(usedRewName), storm::exceptions::WrongFormatException,
188 "Reward '" << usedRewName <<
"' already exists in reward models.");
190 "Reward type for reward '" << rewName <<
"' must be numeric.");
191 std::optional<std::vector<ValueType>> stateRewards, stateActionRewards;
192 std::optional<storm::storage::SparseMatrix<ValueType>> transitionRewards;
193 if (rewIndex.appliesToStates() && rew.states.has_value()) {
196 if (rewIndex.appliesToChoices() && rew.choices.has_value()) {
199 if (rewIndex.appliesToBranches() && rew.branches.has_value()) {
203 }
catch (storm::exceptions::InvalidArgumentException
const& e) {
205 "Branch rewards of reward '"
207 <<
"' can not be imported, possibly due to multiple branches with the same source choice and the same target "
208 "state but distinct rewards, which is not supported. ("
212 STORM_LOG_THROW(!rewIndex.appliesToObservations(), storm::exceptions::NotSupportedException,
213 "Observation rewards are not supported for reward '" << rewName <<
"'.");
214 STORM_LOG_THROW(!rewIndex.appliesToPlayers(), storm::exceptions::NotSupportedException,
215 "Player rewards are not supported for reward '" << rewName <<
"'.");
216 rewardModels.emplace(std::move(usedRewName), RewardModel(std::move(stateRewards), std::move(stateActionRewards), std::move(transitionRewards)));
222template<
typename ValueType>
231 uint64_t numNormalized{0};
233 auto updateNormStats = [&numNormalized, &maxDiff](
auto const& rowSum) {
239 for (uint64_t rowIndex = 0; rowIndex < result.getRowCount(); ++rowIndex) {
240 auto const rowSum = result.getRowSum(rowIndex);
243 updateNormStats(rowSum.lower());
244 for (
auto& entry : result.getRow(rowIndex)) {
245 entry.setValue({entry.getValue().lower() / rowSum.lower(), entry.getValue().upper()});
248 updateNormStats(rowSum.upper());
249 for (
auto& entry : result.getRow(rowIndex)) {
250 entry.setValue({entry.getValue().lower(), entry.getValue().upper() / rowSum.upper()});
255 updateNormStats(rowSum);
256 for (
auto& entry : result.getRow(rowIndex)) {
257 entry.setValue(entry.getValue() / rowSum);
263 "Branch probabilities are given in an imprecise type but an exact model was requested. Probabilities for "
264 << numNormalized <<
" choices were normalized to ensure they sum up to 1. Maximum diff to 1 was " << maxDiff <<
".");
273template<
typename ValueType>
280 "Branch probability type must be given in the UMB model index.");
287 "Choice actions mentioned in the index but no files given.");
293 "State valuations mentioned in the index but no files given.");
296 STORM_LOG_ASSERT(svIndex.numStrings.has_value() == svData.stringMapping.has_value() && svIndex.numStrings.has_value() == svData.strings.has_value(),
297 "String mapping and strings must be given iff there are #strings mentioned in index.");
299 svData.stringMapping.value_or(std::vector<uint64_t>()), svData.strings.value_or(std::vector<char>()),
300 svData.valuationToClass);
309 if (modelType == Ctmc || modelType == MarkovAutomaton) {
311 "Exit rates are required for CTMC and Markov automaton models but not present in the UMB model.");
313 if (modelType == MarkovAutomaton) {
321 }
else if (modelType == Pomdp) {
323 storm::exceptions::NotSupportedException,
"Only state observations are currently supported for POMDP models.");
325 "Only deterministic state observations are currently supported for POMDP models.");
327 "State observations are required for POMDP models but not present in the UMB model.");
332 storm::exceptions::WrongFormatException,
"Observation valuations mentioned in the index but no files given.");
335 STORM_LOG_ASSERT(ovIndex.numStrings.has_value() == ovData.stringMapping.has_value() && ovIndex.numStrings.has_value() == ovData.strings.has_value(),
336 "String mapping and strings must be given iff there are #strings mentioned in index.");
338 ovData.stringMapping.value_or(std::vector<uint64_t>()), ovData.strings.value_or(std::vector<char>()),
339 ovData.valuationToClass);
344 }
else if (modelType == Smg) {
355 "Number of player names does not match number of players in the UMB model index.");
357 for (uint64_t i = 0; i < names.size(); ++i) {
363 "Unexpected model type for UMB import: " << modelType <<
".");
375 STORM_LOG_THROW(ts.branchProbabilityType.has_value(), storm::exceptions::NotSupportedException,
"Models without branch values are not supported.");
379 switch (ts.numPlayers) {
383 return ts.numObservations == 0 ?
Mdp : Pomdp;
385 STORM_LOG_THROW(ts.numObservations == 0, storm::exceptions::NotSupportedException,
386 "Multiplayer partially observable models are not supported.");
390 STORM_LOG_THROW(ts.numPlayers == 0, storm::exceptions::NotSupportedException,
"Stochastic time models with multiple players are not supported.");
392 case UrgentStochastic:
393 STORM_LOG_THROW(ts.numPlayers == 1, storm::exceptions::NotSupportedException,
394 "Urgent stochastic time models with multiple or no players are not supported.");
395 return MarkovAutomaton;
397 STORM_LOG_THROW(
false, storm::exceptions::UnexpectedException,
"Unexpected transition system time type" << ts.time <<
".");
400template<
typename ValueType>
403 "Models without branch values are not supported.");
408 bool const haveInterval = haveDoubleInterval || haveRationalInterval;
413 STORM_LOG_ASSERT(useDefault || useDouble || useRational,
"Unexpected value type option: " <<
static_cast<int>(options.valueType) <<
".");
416 if constexpr (std::is_same_v<ValueType, double>) {
417 return useDouble || (useDefault && haveDouble);
418 }
else if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
419 return useRational || (useDefault && haveRational);
424 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
425 return useDouble || (useDefault && haveDoubleInterval);
426 }
else if constexpr (std::is_same_v<ValueType, storm::RationalInterval>) {
427 return useRational || (useDefault && haveRationalInterval);
434template<
typename ValueType>
450 "Could not derive a supported value type for the UMB model with branch probabilities of type "
storm::models::sparse::Dtmc< double > Dtmc
storm::models::sparse::Mdp< double > Mdp
This class manages the labeling of the choice space with a number of (atomic) labels.
void addLabel(std::string const &label)
Adds a new label to the labelings.
bool containsLabel(std::string const &label) const
Checks whether a label is registered within this labeling.
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 resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
A class that can be used to build a sparse matrix by adding value by value.
AccumulationMode
Specifies how values that are added for the same row and column are combined.
A class that holds a possibly non-square matrix in the compressed row storage format.
Stores valuations of variables for a set of entities (e.g.
Represents a model in the UMB format.
TO1< bool > stateIsMarkovian
void validateOrThrow() const
Validates the UmbModel.
storm::OptionalRef< Annotation > rewards(bool createIfMissing=false)
TO1< AnyValueType > branchToProbability
std::optional< ActionLabels > choiceActions
TO1< bool > stateIsInitial
TO1< AnyValueType > stateToExitRate
TO1< uint32_t > stateToPlayer
TO1< uint64_t > branchToTarget
std::optional< Observations > stateObservations
storm::OptionalRef< Annotation > aps(bool createIfMissing=false)
static auto applyDecodedVector(auto &&func, storm::umb::GenericVector const &input, storm::umb::SizedType const &sourceType)
returns func(<decoded_input>) where <decoded_input> is a range that (if necessary) decodes and conver...
static std::vector< ValueType > createDecodedVector(storm::umb::GenericVector const &input, storm::umb::SizedType const &sourceType)
#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)
std::shared_ptr< storm::models::sparse::Model< ValueType > > constructSparseModel(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
auto csrRange(auto &&csr, uint64_t i)
storm::models::sparse::StateLabeling constructStateLabeling(storm::umb::UmbModel const &umbModel)
auto constructRewardModels(storm::umb::UmbModel const &umbModel)
typename storm::storage::SparseMatrixBuilder< ValueType >::AccumulationMode AccumulationMode
storm::storage::SparseMatrix< ValueType > constructTransitionMatrix(storm::umb::UmbModel const &umbModel)
storm::storage::BitVector createBitVector(storm::umb::VectorType< bool > const &umbBitVector, uint64_t size)
storm::models::sparse::ChoiceLabeling constructChoiceLabeling(storm::umb::UmbModel const &umbModel)
storm::storage::SparseMatrix< ValueType > createBranchMatrix(storm::umb::UmbModel const &umbModel, std::ranges::input_range auto &&branchValues, AccumulationMode< ValueType > accumulationMode)
Creates a matrix with one row per choice and one column per state, where the entry at (choice,...
Import and export of umb files.
std::optional< VectorType< T > > OptionalVectorType
template std::shared_ptr< storm::models::sparse::Model< storm::RationalNumber > > sparseModelFromUmb< storm::RationalNumber >(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
bool isNumericType(Type const type)
template std::shared_ptr< storm::models::sparse::Model< storm::Interval > > sparseModelFromUmb< storm::Interval >(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
std::conditional_t< std::is_same_v< T, bool >, storm::storage::BitVector, std::vector< T > > VectorType
bool deriveValueType(storm::umb::ModelIndex const &index, ImportOptions const &options)
Returns true iff the given umb model with the given options should have ValueType as its ValueType.
bool isBooleanType(Type const type)
std::shared_ptr< storm::models::sparse::Model< ValueType > > sparseModelFromUmb(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
Constructs a sparse model from the given UMB model.
template std::shared_ptr< storm::models::sparse::Model< storm::RationalInterval > > sparseModelFromUmb< storm::RationalInterval >(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
auto stringVectorView(SEQ< char >::value_type const &strings, CSR::value_type const &stringMapping)
template std::shared_ptr< storm::models::sparse::Model< double > > sparseModelFromUmb< double >(storm::umb::UmbModel const &umbModel, ImportOptions const &options)
storm::models::ModelType deriveModelType(storm::umb::ModelIndex const &index)
Derives the model type from the given UMB model index.
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > buildModelFromComponents(storm::models::ModelType modelType, storm::storage::sparse::ModelComponents< ValueType, RewardModelType > &&components)
bool isOne(ValueType const &a)
ValueType abs(ValueType const &number)
carl::Interval< double > Interval
Interval type.
constexpr bool IsIntervalType
Helper to check if a type is an interval.
typename detail::IntervalMetaProgrammingHelper< ValueType >::BaseType IntervalBaseType
Helper to access the type in which interval boundaries are stored.
static const bool IsExact
boost::optional< storm::storage::BitVector > markovianStates
boost::optional< std::vector< storm::storage::PlayerIndex > > statePlayerIndications
std::optional< storm::storage::sparse::Valuations > observationValuations
std::optional< storm::models::sparse::ChoiceLabeling > choiceLabeling
boost::optional< std::map< std::string, storm::storage::PlayerIndex > > playerNameToIndexMap
std::optional< storm::storage::sparse::Valuations > stateValuations
std::optional< std::vector< uint32_t > > observabilityClasses
boost::optional< std::vector< ValueType > > exitRates
bool buildChoiceLabeling
Controls building of choice labelings.
bool buildObservationValuations
Controls building of observation valuations.
bool buildStateValuations
Controls building of state valuations.
uint64_t numChoiceActions
std::optional< SizedType > exitRateType
std::optional< SizedType > branchProbabilityType
std::optional< storm::SerializedEnum< ObservationsApplyToDeclaration > > observationsApplyTo
std::optional< std::vector< std::string > > playerNames
std::optional< SizedType > observationProbabilityType
storm::OptionalRef< AnnotationMap > rewards(bool createIfMissing=false)
struct storm::umb::ModelIndex::TransitionSystem transitionSystem
std::optional< Valuations > valuations
storm::OptionalRef< AnnotationMap > aps(bool createIfMissing=false)
std::optional< Values > observations
std::optional< Values > states