Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ApplyFiniteSchedulerToPomdp.cpp
Go to the documentation of this file.
4
7
8namespace storm {
9namespace transformer {
11 if (mode == "standard") {
13 } else if (mode == "simple-linear") {
15 } else if (mode == "simple-linear-inverse") {
17 } else {
18 STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Mode " << mode << " not known.");
19 }
20}
21
23 RationalFunctionConstructor(std::shared_ptr<RawPolynomialCache> const& cache) : cache(cache) {}
24
29
30 std::shared_ptr<RawPolynomialCache> cache;
31};
32
33template<typename ValueType>
34std::shared_ptr<RawPolynomialCache> getCache(storm::models::sparse::Pomdp<ValueType> const&) {
35 return std::make_shared<RawPolynomialCache>();
36}
37
38template<>
39std::shared_ptr<RawPolynomialCache> getCache(storm::models::sparse::Pomdp<storm::RationalFunction> const& model) {
40 for (auto const& entry : model.getTransitionMatrix()) {
41 if (!entry.getValue().isConstant()) {
42 return entry.getValue().nominatorAsPolynomial().pCache();
43 }
44 }
45 return std::make_shared<RawPolynomialCache>();
46}
47
48template<typename ValueType>
49std::unordered_map<uint32_t, std::vector<storm::RationalFunction>> ApplyFiniteSchedulerToPomdp<ValueType>::getObservationChoiceWeights(
50 PomdpFscApplicationMode applicationMode) const {
51 std::unordered_map<uint32_t, std::vector<storm::RationalFunction>> res;
52 RationalFunctionConstructor ratFuncConstructor(getCache(pomdp));
53
54 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
55 auto observation = pomdp.getObservation(state);
56 auto it = res.find(observation);
57 if (it == res.end()) {
58 std::vector<storm::RationalFunction> weights;
59 storm::RationalFunction collected = storm::utility::one<storm::RationalFunction>();
60 storm::RationalFunction lastWeight = storm::utility::one<storm::RationalFunction>();
61 for (uint64_t a = 0; a < pomdp.getNumberOfChoices(state) - 1; ++a) {
62 std::string varName = "p" + std::to_string(observation) + "_" + std::to_string(a);
63 storm::RationalFunction var = ratFuncConstructor.translate(storm::createRFVariable(varName));
64 if (applicationMode == PomdpFscApplicationMode::SIMPLE_LINEAR) {
65 weights.push_back(collected * var);
66 collected *= storm::utility::one<storm::RationalFunction>() - var;
67 } else if (applicationMode == PomdpFscApplicationMode::SIMPLE_LINEAR_INVERSE) {
68 weights.push_back(collected * (storm::utility::one<storm::RationalFunction>() - var));
69 collected *= var;
70 } else if (applicationMode == PomdpFscApplicationMode::STANDARD) {
71 weights.push_back(var);
72 }
73 lastWeight -= weights.back();
74 }
75 weights.push_back(lastWeight);
76 res.emplace(observation, weights);
77 }
78 STORM_LOG_ASSERT(it == res.end() || it->second.size() == pomdp.getNumberOfChoices(state),
79 "Number of choices must be equal for every state with same number of actions");
80 }
81 return res;
82}
83
84template<typename ValueType>
85std::shared_ptr<storm::models::sparse::Model<storm::RationalFunction>> ApplyFiniteSchedulerToPomdp<ValueType>::transform(
86 PomdpFscApplicationMode applicationMode) const {
87 STORM_LOG_THROW(pomdp.isCanonic(), storm::exceptions::IllegalArgumentException, "POMDP needs to be canonic");
89
90 uint64_t nrStates = pomdp.getNumberOfStates();
91 std::unordered_map<uint32_t, std::vector<storm::RationalFunction>> observationChoiceWeights = getObservationChoiceWeights(applicationMode);
93
94 for (uint64_t state = 0; state < nrStates; ++state) {
95 auto const& weights = observationChoiceWeights.at(pomdp.getObservation(state));
96 std::map<uint64_t, storm::RationalFunction> weightedTransitions;
97 for (uint64_t action = 0; action < pomdp.getNumberOfChoices(state); ++action) {
98 auto ratSum = storm::utility::zero<storm::RationalFunction>();
99 uint64_t nrEntries = pomdp.getTransitionMatrix().getRow(state, action).getNumberOfEntries();
100 uint64_t currEntry = 1;
101 for (auto const& entry : pomdp.getTransitionMatrix().getRow(state, action)) {
102 auto it = weightedTransitions.find(entry.getColumn());
103 auto entryVal = storm::utility::convertNumber<storm::RationalFunction>(entry.getValue());
104 ratSum += entryVal;
105 if (currEntry == nrEntries && storm::utility::one<storm::RationalFunction>() - ratSum != storm::utility::zero<storm::RationalFunction>()) {
106 // In case there are numeric problems with the conversion, we simply add the lost mass to the last value
107 entryVal += (storm::utility::one<storm::RationalFunction>() - ratSum);
108 }
109 if (it == weightedTransitions.end()) {
110 weightedTransitions[entry.getColumn()] = entryVal * weights[action];
111 } else {
112 it->second += entryVal * weights[action];
113 }
114 ++currEntry;
115 }
116 }
117 for (auto const& entry : weightedTransitions) {
118 smb.addNextValue(state, entry.first, entry.second);
119 }
120 }
121 modelComponents.transitionMatrix = smb.build();
122
123 for (auto const& pomdpRewardModel : pomdp.getRewardModels()) {
124 std::vector<storm::RationalFunction> stateRewards;
125
126 if (pomdpRewardModel.second.hasStateRewards()) {
127 stateRewards = storm::utility::vector::convertNumericVector<storm::RationalFunction>(pomdpRewardModel.second.getStateRewardVector());
128 } else {
129 stateRewards.resize(nrStates, storm::utility::zero<storm::RationalFunction>());
130 }
131 if (pomdpRewardModel.second.hasStateActionRewards()) {
132 std::vector<ValueType> pomdpActionRewards = pomdpRewardModel.second.getStateActionRewardVector();
133 for (uint64_t state = 0; state < nrStates; ++state) {
134 auto& stateReward = stateRewards[state];
135 auto const& weights = observationChoiceWeights.at(pomdp.getObservation(state));
136 uint64_t offset = pomdp.getTransitionMatrix().getRowGroupIndices()[state];
137 for (uint64_t action = 0; action < pomdp.getNumberOfChoices(state); ++action) {
138 if (!storm::utility::isZero(pomdpActionRewards[offset + action])) {
139 stateReward += storm::utility::convertNumber<storm::RationalFunction>(pomdpActionRewards[offset + action]) * weights[action];
140 }
141 }
142 }
143 }
145 modelComponents.rewardModels.emplace(pomdpRewardModel.first, std::move(rewardModel));
146 }
147
148 modelComponents.stateLabeling = pomdp.getStateLabeling();
149 modelComponents.stateValuations = pomdp.getOptionalStateValuations();
150
151 return std::make_shared<storm::models::sparse::Dtmc<storm::RationalFunction>>(modelComponents);
152}
153
155
158} // namespace transformer
159} // namespace storm
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
This class represents a partially observable Markov decision process.
Definition Pomdp.h:15
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
std::shared_ptr< storm::models::sparse::Model< storm::RationalFunction > > transform(PomdpFscApplicationMode applicationMode=PomdpFscApplicationMode::SIMPLE_LINEAR) const
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
std::shared_ptr< RawPolynomialCache > getCache(storm::models::sparse::Pomdp< ValueType > const &)
PomdpFscApplicationMode parsePomdpFscApplicationMode(std::string const &mode)
bool isZero(ValueType const &a)
Definition constants.cpp:41
LabParser.cpp.
Definition cli.cpp:18
RationalFunctionVariable createRFVariable(std::string const &name)
carl::Variable RationalFunctionVariable
carl::RationalFunction< Polynomial, true > RationalFunction
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial
std::optional< storm::storage::sparse::StateValuations > stateValuations
std::unordered_map< std::string, RewardModelType > rewardModels
storm::storage::SparseMatrix< ValueType > transitionMatrix
storm::models::sparse::StateLabeling stateLabeling
storm::RationalFunction translate(storm::RationalFunctionVariable const &var)
RationalFunctionConstructor(std::shared_ptr< RawPolynomialCache > const &cache)