135 auto rewardModels = pomdp.getRewardModels();
136 std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> newRewardModels;
137 for (
auto& rewardModelNameAndModel : rewardModels) {
138 newRewardModels.emplace(rewardModelNameAndModel.first, rewardModelNameAndModel.second.permuteActions(permutation));
141 newRewardModels,
false, boost::none);
147 return std::make_shared<storm::models::sparse::Pomdp<ValueType>>(modelcomponents,
true);
170 std::map<uint32_t, std::vector<detail::ActionIdentifier>> observationActionIdentifiers;
171 std::map<uint32_t, uint64_t> actionIdentifierDefinition;
172 auto const& choiceLabeling = pomdp.getChoiceLabeling();
175 std::vector<uint64_t> permutation;
176 uint64_t nrObservations = pomdp.getNrObservations();
179 uint64_t freshChoiceOriginId = 0;
181 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
182 uint64_t rowIndexFrom = pomdp.getTransitionMatrix().getRowGroupIndices()[state];
183 uint64_t rowIndexTo = pomdp.getTransitionMatrix().getRowGroupIndices()[state + 1];
185 uint64_t observation = pomdp.getObservation(state);
186 if (rowIndexFrom + 1 == rowIndexTo) {
187 permutation.push_back(rowIndexFrom);
188 if (moreActionObservations.
get(observation)) {
191 std::string actionval =
"";
192 if (pomdp.hasChoiceLabeling()) {
193 auto labelsOfChoice = pomdp.getChoiceLabeling().getLabelsOfChoice(rowIndexFrom);
194 if (labelsOfChoice.empty()) {
195 actionval =
"[[no-label]]";
197 actionval = *pomdp.getChoiceLabeling().getLabelsOfChoice(rowIndexFrom).begin();
201 "Observation " << getObservationInformation(observation) <<
" sometimes provides multiple actions, but in state "
202 << getStateInformation(state) <<
" provides only one action " << actionval <<
".");
204 oneActionObservations.
set(observation);
209 if (oneActionObservations.
get(observation)) {
216 "Observation " << getObservationInformation(observation) <<
" sometimes provides one action, but in state "
217 << getStateInformation(state) <<
" provides " << rowIndexTo - rowIndexFrom <<
" actions.");
219 moreActionObservations.
set(observation);
222 std::map<detail::ActionIdentifier, uint64_t> actionIdentifiers;
223 std::set<uint64_t> actionLabels;
224 for (uint64_t actionIndex = rowIndexFrom; actionIndex < rowIndexTo; ++actionIndex) {
227 std::set<std::string> labels = choiceLabeling.getLabelsOfChoice(actionIndex);
228 STORM_LOG_ASSERT(labels.size() <= 1,
"We expect choice labels to be single sets");
230 uint64_t labelId = -1;
231 if (labels.size() == 1) {
233 STORM_LOG_THROW(actionLabels.count(labelId) == 0, storm::exceptions::AmbiguousModelException,
234 "Multiple actions with label '" << *labels.begin() <<
"' exist in state id " << state <<
".");
235 actionLabels.emplace(labelId);
242 if (pomdp.hasChoiceOrigins()) {
243 ai.
choiceOriginId = pomdp.getChoiceOrigins()->getIdentifier(actionIndex);
247 STORM_LOG_ASSERT(actionIdentifiers.count(ai) == 0,
"Action with this identifier already exists for this state");
248 actionIdentifiers.emplace(ai, actionIndex);
250 STORM_LOG_ASSERT(actionIdentifiers.size() == rowIndexTo - rowIndexFrom,
"Number of action identifiers should match number of actions");
252 if (observationActionIdentifiers.count(observation) == 0) {
255 std::vector<detail::ActionIdentifier> ais;
256 for (
auto const& als : actionIdentifiers) {
257 ais.push_back(als.first);
260 observationActionIdentifiers.emplace(observation, ais);
261 actionIdentifierDefinition.emplace(observation, state);
263 auto referenceStart = observationActionIdentifiers[observation].begin();
264 auto referenceEnd = observationActionIdentifiers[observation].end();
265 STORM_LOG_ASSERT(observationActionIdentifiers[observation].size() == pomdp.getNumberOfChoices(actionIdentifierDefinition[observation]),
266 "Number of actions recorded for state does not coincide with number of actions.");
267 if (observationActionIdentifiers[observation].size() != actionIdentifiers.size()) {
269 "Number of actions in state '" << getStateInformation(state) <<
"' (nr actions:" << actionIdentifiers.size() <<
") and state '"
270 << getStateInformation(actionIdentifierDefinition[observation])
271 <<
"' (actions: " << observationActionIdentifiers[observation].size()
272 <<
" ), both having observation " << getObservationInformation(observation) <<
" do not match.");
274 if (!
detail::compatibleWith(referenceStart, referenceEnd, actionIdentifiers.begin(), actionIdentifiers.end())) {
275 std::cout <<
"Observation " << getObservationInformation(observation) <<
": \n";
277 std::cout <<
" according to state " << actionIdentifierDefinition[observation] <<
".\n";
279 std::cout <<
" according to state " << state <<
".\n";
280 std::cout <<
"(Actions are given as [id (label), originId])\n";
282 for (
auto const& ai : actionIdentifiers) {
283 if (labelStorage.
getLabel(ai.first.choiceLabelId) ==
"") {
284 for (
auto const& ai2 : observationActionIdentifiers[observation]) {
286 "Actions with empty label are only considered the same action if they originate from the same command.");
292 "Actions identifiers do not align between states \n\t"
293 << getStateInformation(state) <<
"\nand\n\t" << getStateInformation(actionIdentifierDefinition[observation])
294 <<
"\nboth having observation " << getObservationInformation(observation) <<
". See output above for more information.");
298 for (
auto const& al : actionIdentifiers) {
299 permutation.push_back(al.second);