Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
storm-pomdp.cpp
Go to the documentation of this file.
1#include <optional>
2#include <type_traits>
3
11
32#include "storm/api/storm.h"
44#include "storm/utility/graph.h"
45
46namespace storm {
47namespace pomdp {
48namespace cli {
49
51template<typename ValueType>
53 storm::logic::Formula const& formula) {
55 bool preprocessingPerformed = false;
56 if (pomdpSettings.isSelfloopReductionSet()) {
58 if (selfLoopEliminator.preservesFormula(formula)) {
59 STORM_PRINT_AND_LOG("Eliminating self-loop choices ...");
60 uint64_t oldChoiceCount = pomdp->getNumberOfChoices();
61 pomdp = selfLoopEliminator.transform();
62 STORM_PRINT_AND_LOG(oldChoiceCount - pomdp->getNumberOfChoices() << " choices eliminated through self-loop elimination.\n");
63 preprocessingPerformed = true;
64 } else {
65 STORM_PRINT_AND_LOG("Not eliminating self-loop choices as it does not preserve the formula.\n");
66 }
67 }
68 if (pomdpSettings.isQualitativeReductionSet() && formulaInfo.isNonNestedReachabilityProbability() && !formulaInfo.isBounded()) {
70 STORM_PRINT_AND_LOG("Computing states with probability 0 ...");
71 storm::storage::BitVector prob0States = qualitativeAnalysis.analyseProb0(formula.asProbabilityOperatorFormula());
72 STORM_PRINT_AND_LOG(" done. " << prob0States.getNumberOfSetBits() << " states found.\n");
73 STORM_PRINT_AND_LOG("Computing states with probability 1 ...");
74 storm::storage::BitVector prob1States = qualitativeAnalysis.analyseProb1(formula.asProbabilityOperatorFormula());
75 STORM_PRINT_AND_LOG(" done. " << prob1States.getNumberOfSetBits() << " states found.\n");
77 pomdp = kpt.transform(*pomdp, prob0States, prob1States);
78 // Update formulaInfo to changes from Preprocessing
79 formulaInfo.updateTargetStates(*pomdp, std::move(prob1States));
80 formulaInfo.updateSinkStates(*pomdp, std::move(prob0States));
81 preprocessingPerformed = true;
82 }
83 return preprocessingPerformed;
84}
85
86template<typename ValueType>
87void printResult(std::optional<ValueType> const& lowerBound, std::optional<ValueType> const& upperBound) {
88 if (lowerBound.has_value() && upperBound.has_value()) {
89 if (*lowerBound == *upperBound) {
90 if (storm::utility::isInfinity(*lowerBound)) {
92 } else {
93 STORM_PRINT_AND_LOG(*lowerBound);
94 }
95 } else if (storm::utility::isInfinity(ValueType(-*lowerBound))) {
96 if (storm::utility::isInfinity(*upperBound)) {
97 STORM_PRINT_AND_LOG("[-inf, inf] (width=inf)");
98 }
99 } else {
100 STORM_PRINT_AND_LOG("[" << *lowerBound << ", " << *upperBound << "] (width=" << ValueType(*upperBound - *lowerBound) << ")");
101 }
102 } else if (lowerBound.has_value()) {
103 STORM_PRINT_AND_LOG("≥ " << *lowerBound);
104 } else if (upperBound.has_value()) {
105 STORM_PRINT_AND_LOG("≤ " << *upperBound);
106 }
108 STORM_PRINT_AND_LOG(" (approx. ");
109 std::optional<double> roundedLowerBound = std::nullopt;
110 std::optional<double> roundedUpperBound = std::nullopt;
111 if (lowerBound.has_value()) {
112 roundedLowerBound = storm::utility::convertNumber<double>(*lowerBound);
113 }
114 if (upperBound.has_value()) {
115 roundedUpperBound = storm::utility::convertNumber<double>(*upperBound);
116 }
117 printResult(roundedLowerBound, roundedUpperBound);
119 }
120}
121
122template<typename Statistics>
123void printBeliefExplorationStatistics(Statistics const& statistics) {
124 STORM_PRINT_AND_LOG("Belief exploration " << (statistics.completedExploration ? "completed" : "stopped early") << ": " << statistics.discoveredBeliefs
125 << " beliefs discovered, " << statistics.exploredBeliefs << " beliefs explored.\n");
126 STORM_PRINT_AND_LOG("Constructed belief MDP: " << statistics.beliefMdpStates << " states, " << statistics.beliefMdpChoices << " choices, "
127 << statistics.beliefMdpTransitions << " transitions.\n");
128 if (statistics.processedMdpStates && statistics.processedMdpChoices && statistics.processedMdpTransitions) {
129 STORM_PRINT_AND_LOG("Processed belief MDP: " << *statistics.processedMdpStates << " states, " << *statistics.processedMdpChoices << " choices, "
130 << *statistics.processedMdpTransitions << " transitions.\n");
131 }
132 STORM_PRINT_AND_LOG("Time for exploring beliefs: " << statistics.explorationTimeMilliseconds << "ms.\n");
133 STORM_PRINT_AND_LOG("Time for building the belief MDP: " << statistics.beliefMdpBuildTimeMilliseconds << "ms.\n");
134 STORM_PRINT_AND_LOG("Time for analyzing the belief MDP: " << statistics.beliefMdpAnalysisTimeMilliseconds << "ms.\n");
135}
136
140
141 options.onlyDeterministicStrategies = qualSettings.isOnlyDeterministicSet();
142 uint64_t loglevel = 0;
143 // TODO a big ugly, but we have our own loglevels (for technical reasons)
144 if (storm::utility::getLogLevel() == l3pp::LogLevel::INFO) {
145 loglevel = 1;
146 } else if (storm::utility::getLogLevel() == l3pp::LogLevel::DEBUG) {
147 loglevel = 2;
148 } else if (storm::utility::getLogLevel() == l3pp::LogLevel::TRACE) {
149 loglevel = 3;
150 }
151 options.setDebugLevel(loglevel);
152 options.validateEveryStep = qualSettings.validateIntermediateSteps();
153 options.validateResult = qualSettings.validateFinalResult();
154
155 options.pathVariableType = storm::pomdp::pathVariableTypeFromString(qualSettings.getLookaheadType());
156
157 if (qualSettings.isExportSATCallsSet()) {
158 options.setExportSATCalls(qualSettings.getExportSATCallsPath());
159 }
160
161 return options;
162}
163
164template<typename ValueType>
166 storm::pomdp::analysis::FormulaInformation const& formulaInfo, storm::logic::Formula const& formula) {
169 std::stringstream sstr;
170 origpomdp->printModelInformationToStream(sstr);
171 STORM_LOG_INFO(sstr.str());
172 STORM_LOG_THROW(formulaInfo.isNonNestedReachabilityProbability() && !formulaInfo.isBounded(), storm::exceptions::NotSupportedException,
173 "Qualitative memoryless scheduler search is not implemented for this property type.");
174 STORM_LOG_TRACE("Run qualitative preprocessing...");
177 // After preprocessing, this might be done cheaper.
178 storm::storage::BitVector surelyNotAlmostSurelyReachTarget = qualitativeAnalysis.analyseProbSmaller1(formula.asProbabilityOperatorFormula());
179 pomdp.getTransitionMatrix().makeRowGroupsAbsorbing(surelyNotAlmostSurelyReachTarget);
180 storm::storage::BitVector targetStates = qualitativeAnalysis.analyseProb1(formula.asProbabilityOperatorFormula());
181 bool computedSomething = false;
182 if (qualSettings.isMemlessSearchSet()) {
183 computedSomething = true;
184 std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory = std::make_shared<storm::utility::solver::SmtSolverFactory>();
185 uint64_t lookahead = qualSettings.getLookahead();
186 if (lookahead == 0) {
187 lookahead = pomdp.getNumberOfStates();
188 }
189 if (qualSettings.getMemlessSearchMethod() == "one-shot") {
190 storm::pomdp::OneShotPolicySearch<ValueType> memlessSearch(env, pomdp, targetStates, surelyNotAlmostSurelyReachTarget, smtSolverFactory);
191 if (qualSettings.isWinningRegionSet()) {
192 STORM_LOG_ERROR("Computing winning regions is not supported by the one-shot method.");
193 } else {
194 bool result = memlessSearch.analyzeForInitialStates(lookahead);
195 if (result) {
196 STORM_PRINT_AND_LOG("From initial state, one can almost-surely reach the target.\n");
197 } else {
198 STORM_PRINT_AND_LOG("From initial state, one may not almost-surely reach the target .\n");
199 }
200 }
201 } else if (qualSettings.getMemlessSearchMethod() == "iterative") {
203 storm::pomdp::IterativePolicySearch<ValueType> search(env, pomdp, targetStates, surelyNotAlmostSurelyReachTarget, smtSolverFactory, options);
204 if (qualSettings.isWinningRegionSet()) {
205 search.computeWinningRegion(lookahead);
206 } else {
207 bool result = search.analyzeForInitialStates(lookahead);
208 if (result) {
209 STORM_PRINT_AND_LOG("From initial state, one can almost-surely reach the target.");
210 } else {
211 // TODO consider adding check for end components to improve this message.
212 STORM_PRINT_AND_LOG("From initial state, one may not almost-surely reach the target.");
213 }
214 }
215
216 if (qualSettings.isPrintWinningRegionSet()) {
217 search.getLastWinningRegion().print();
218 std::cout << '\n';
219 }
220 if (qualSettings.isExportWinningRegionSet()) {
221 std::size_t hash = pomdp.hash();
222 search.getLastWinningRegion().storeToFile(qualSettings.exportWinningRegionPath(), "model hash: " + std::to_string(hash));
223 }
224
225 search.finalizeStatistics();
226 if (pomdp.getInitialStates().getNumberOfSetBits() == 1) {
227 uint64_t initialState = pomdp.getInitialStates().getNextSetIndex(0);
228 uint64_t initialObservation = pomdp.getObservation(initialState);
229 // TODO this is inefficient.
230 uint64_t offset = 0;
231 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
232 if (state == initialState) {
233 break;
234 }
235 if (pomdp.getObservation(state) == initialObservation) {
236 ++offset;
237 }
238 }
239
240 if (search.getLastWinningRegion().isWinning(initialObservation, offset)) {
241 STORM_PRINT_AND_LOG("Initial state is safe!\n");
242 } else {
243 STORM_PRINT_AND_LOG("Initial state may not be safe.\n");
244 }
245 } else {
246 STORM_LOG_WARN("Output for multiple initial states is incomplete");
247 }
248
249 if (coreSettings.isShowStatisticsSet()) {
250 STORM_PRINT_AND_LOG("#STATS Number of belief support states: " << search.getLastWinningRegion().beliefSupportStates() << '\n');
251 if (qualSettings.computeExpensiveStats()) {
252 auto wbss = search.getLastWinningRegion().computeNrWinningBeliefs();
253 STORM_PRINT_AND_LOG("#STATS Number of winning belief support states: [" << wbss.first << "," << wbss.second << "]");
254 }
255 search.getStatistics().print();
256 }
257
258 } else {
259 STORM_LOG_ERROR("This method is not implemented.");
260 }
261 }
262 if (qualSettings.isComputeOnBeliefSupportSet()) {
263 computedSomething = true;
265 janicreator.generate(targetStates, surelyNotAlmostSurelyReachTarget);
266 bool initialOnly = !qualSettings.isWinningRegionSet();
267 janicreator.verifySymbolic(env, initialOnly);
268 STORM_PRINT_AND_LOG("Initial state is safe: " << janicreator.isInitialWinning() << "\n");
269 }
270 STORM_LOG_THROW(computedSomething, storm::exceptions::InvalidSettingsException, "Nothing to be done, did you forget to set a method?");
271}
272
273template<typename ValueType, typename BeliefType, typename BeliefMDPType>
275 storm::pomdp::analysis::FormulaInformation const& formulaInfo, storm::logic::Formula const& formula) {
278 STORM_LOG_THROW(!formulaInfo.isBounded() || !belExplSettings.isUseClippingSet(), storm::exceptions::NotSupportedException,
279 "Grid clipping is not supported for reward-bounded POMDP properties.");
280
282 // We hard-code this to FIFO for now to mimic the legacy behaviour
284 if (belExplSettings.getExplorationTimeLimit() != 0) {
285 revisedOptions.maxExplorationTime = belExplSettings.getExplorationTimeLimit();
286 }
287 revisedOptions.cutZeroGap = belExplSettings.isCutZeroGapSet();
288
289 std::shared_ptr<storm::models::sparse::Pomdp<ValueType>> preprocessedPomdpPtr = pomdp;
290
291 std::optional<std::string> rewardModelName;
292 std::set<uint32_t> targetObservations;
293 if (formulaInfo.isNonNestedReachabilityProbability() || formulaInfo.isNonNestedExpectedRewardFormula()) {
294 if (formulaInfo.getTargetStates().observationClosed) {
295 targetObservations = formulaInfo.getTargetStates().observations;
296 } else {
298 std::tie(preprocessedPomdpPtr, targetObservations) = obsCloser.transform(formulaInfo.getTargetStates().states);
299 }
300 if (formulaInfo.isNonNestedReachabilityProbability()) {
301 if (!formulaInfo.getSinkStates().empty()) {
303 components.stateLabeling = preprocessedPomdpPtr->getStateLabeling();
304 components.rewardModels = preprocessedPomdpPtr->getRewardModels();
305 auto matrix = preprocessedPomdpPtr->getTransitionMatrix();
306 matrix.makeRowGroupsAbsorbing(formulaInfo.getSinkStates().states, true);
307 STORM_LOG_ASSERT(matrix.isProbabilistic(storm::utility::zero<ValueType>()), "Resulting transition matrix is not a probability matrix.");
308 STORM_LOG_ASSERT(matrix.hasOnlyPositiveEntries(), "Resulting transition matrix has non-positive entries.");
309 components.transitionMatrix = matrix;
310 components.observabilityClasses = preprocessedPomdpPtr->getObservations();
311 if (preprocessedPomdpPtr->hasChoiceLabeling()) {
312 components.choiceLabeling = preprocessedPomdpPtr->getChoiceLabeling();
313 }
314 if (preprocessedPomdpPtr->hasObservationValuations()) {
315 components.observationValuations = preprocessedPomdpPtr->getObservationValuations();
316 }
317 preprocessedPomdpPtr = std::make_shared<storm::models::sparse::Pomdp<ValueType>>(std::move(components), true);
318 auto reachableFromSinkStates =
319 storm::utility::graph::getReachableStates(preprocessedPomdpPtr->getTransitionMatrix(), formulaInfo.getSinkStates().states,
320 formulaInfo.getSinkStates().states, ~formulaInfo.getSinkStates().states);
321 reachableFromSinkStates &= ~formulaInfo.getSinkStates().states;
322 STORM_LOG_THROW(reachableFromSinkStates.empty(), storm::exceptions::NotSupportedException,
323 "There are sink states that can reach non-sink states. This is currently not supported");
324 }
325 } else {
326 // Expected reward formula!
327 rewardModelName = formulaInfo.getRewardModelName();
328 }
329 } else {
330 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Unsupported formula '" << formula << "'.");
331 }
332 std::optional<storm::storage::BitVector> optionalTargetStates;
333 optionalTargetStates = formulaInfo.getTargetStates().states;
334 if (storm::pomdp::detectFiniteBeliefMdp(*preprocessedPomdpPtr, optionalTargetStates)) {
335 STORM_LOG_INFO("Detected that the belief MDP is finite.");
336 }
337
339
340 if (!formulaInfo.isBounded()) {
341 // Precompute initial bounds used for cut-offs and clipping
342 if (belExplSettings.isInexactPreprocessingSet()) {
343 STORM_LOG_WARN("Using inexact preprocessing for belief exploration can lead to inaccurate results.");
344 std::shared_ptr<storm::models::sparse::Pomdp<double>> preprocessedPomdpDouble;
345 if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
346 preprocessedPomdpDouble = storm::transformer::sparseRationalModelToDouble(
348 ->template as<storm::models::sparse::Pomdp<double>>();
349 } else {
350 STORM_LOG_WARN("Inexact preprocessing option has no effect for floating-point models.");
351 preprocessedPomdpDouble = preprocessedPomdpPtr;
352 }
353 auto inExactPreProcessingMC =
355 beliefExplorationBounds.preprocessingBounds = inExactPreProcessingMC.getValueBounds(env, formula).template toValueType<ValueType>();
356 if (belExplSettings.isUseClippingSet() && rewardModelName) {
357 beliefExplorationBounds.extremeBounds = inExactPreProcessingMC.getExtremeValueBound(env, formula).template toValueType<ValueType>();
358 }
359 } else {
361 beliefExplorationBounds.preprocessingBounds = preProcessingMC.getValueBounds(env, formula);
362 if (belExplSettings.isUseClippingSet() && rewardModelName) {
363 beliefExplorationBounds.extremeBounds = preProcessingMC.getExtremeValueBound(env, formula);
364 }
365 }
366 } else {
367 // We only consider bounded probability formulae, so we can use 0-1 bounds
369 zeroOneValueBound.lower.push_back(std::vector<ValueType>(preprocessedPomdpPtr->getNumberOfStates(), storm::utility::zero<ValueType>()));
370 zeroOneValueBound.upper.push_back(std::vector<ValueType>(preprocessedPomdpPtr->getNumberOfStates(), storm::utility::one<ValueType>()));
371
372 beliefExplorationBounds.preprocessingBounds = zeroOneValueBound;
373 }
374
375 uint64_t initialPomdpState = preprocessedPomdpPtr->getInitialStates().getNextSetIndex(0);
376 using ExtendedBeliefMDPType = storm::utility::ExtendedValueType<BeliefMDPType>;
377 std::optional<ExtendedBeliefMDPType> lowerBound =
378 storm::utility::fromSentinel(beliefExplorationBounds.preprocessingBounds->template getHighestLowerBound<BeliefMDPType>(initialPomdpState));
379 std::optional<ExtendedBeliefMDPType> upperBound =
380 storm::utility::fromSentinel(beliefExplorationBounds.preprocessingBounds->template getSmallestUpperBound<BeliefMDPType>(initialPomdpState));
381 STORM_LOG_INFO("Initial value bounds are [" << *lowerBound << ", " << *upperBound << "]");
382
383 auto updateLowerBound = [&lowerBound](ExtendedBeliefMDPType const& value) {
384 if (!lowerBound || value > *lowerBound) {
385 lowerBound = value;
386 }
387 };
388 auto updateUpperBound = [&upperBound](ExtendedBeliefMDPType const& value) {
389 if (!upperBound || value < *upperBound) {
390 upperBound = value;
391 }
392 };
393
395 if (rewardModelName) {
397 propertyInfo.rewardModelName = rewardModelName;
398 } else if (formulaInfo.isBounded()) {
400 // Collect reward bounds from bounded formula
401 auto boundedFormula = formula.asProbabilityOperatorFormula().getSubformula().asBoundedUntilFormula();
402 for (uint64_t i = 0; i < boundedFormula.getDimension(); ++i) {
403 const auto& tbRef = boundedFormula.getTimeBoundReference(i);
404 if (tbRef.isRewardBound()) {
405 propertyInfo.rewardBounds.push_back({.rewardModelName = tbRef.getOptionalRewardModelName().get_value_or(""),
406 .lowerBound = boundedFormula.getLowerBoundAsOptionalTimeBound(i),
407 .upperBound = boundedFormula.getUpperBoundAsOptionalTimeBound(i)});
408 }
409 }
410 } else {
412 }
413 propertyInfo.dir = formulaInfo.getOptimizationDirection();
414 propertyInfo.targetObservations = targetObservations;
415
416 storm::pomdp::beliefs::BeliefBasedModelChecker<storm::models::sparse::Pomdp<ValueType>, BeliefType, BeliefMDPType> checker(*preprocessedPomdpPtr);
417 ExtendedBeliefMDPType overResultValue;
418 ExtendedBeliefMDPType underResultValue;
419 bool isOverApproximation{false};
420 bool isUnderApproximation{false};
421 bool completedExploration{false};
422 if (pomdpSettings.isBeliefExplorationDiscretizeSet()) {
423 isOverApproximation = true;
424 STORM_PRINT_AND_LOG("Computing an over-approximation via belief MDP discretization...\n");
425 STORM_LOG_WARN_COND(belExplSettings.getSizeThresholdInit() == 0,
426 "The size threshold is ignored for discretization, which requires complete exploration.");
427 STORM_LOG_WARN_COND(belExplSettings.getExplorationTimeLimit() == 0,
428 "The exploration time threshold is ignored for discretization, which requires complete exploration.");
429 revisedOptions.maxExplorationSize.reset();
430 revisedOptions.maxExplorationTime.reset();
431
433 std::vector<std::string> relevantRewardModelNames;
434 for (auto const& rewardBound : propertyInfo.rewardBounds) {
435 relevantRewardModelNames.push_back(rewardBound.rewardModelName);
436 }
437 auto checkResult =
438 checker.checkRewardAwareDiscretize(env, propertyInfo, revisedOptions, belExplSettings.getResolutionInit(),
439 belExplSettings.isDynamicTriangulationModeSet(), beliefExplorationBounds, relevantRewardModelNames);
440 overResultValue = checkResult.value;
441 printBeliefExplorationStatistics(checkResult.statistics);
442 } else {
443 auto checkResult = checker.checkDiscretize(env, propertyInfo, revisedOptions, belExplSettings.getResolutionInit(),
444 belExplSettings.isDynamicTriangulationModeSet(), beliefExplorationBounds);
445 overResultValue = checkResult.value;
446 printBeliefExplorationStatistics(checkResult.statistics);
447 }
448 }
449
450 if (pomdpSettings.isBeliefExplorationUnfoldSet()) {
451 STORM_PRINT_AND_LOG("Computing an under-approximation via belief MDP unfolding...\n");
452 if (belExplSettings.getExplorationTimeLimit() != 0) {
453 revisedOptions.maxExplorationTime = belExplSettings.getExplorationTimeLimit();
454 }
455 if (belExplSettings.getSizeThresholdInit() == 0) {
456 revisedOptions.maxExplorationSize = preprocessedPomdpPtr->getNumberOfStates() * preprocessedPomdpPtr->getMaxNrStatesWithSameObservation();
457 STORM_PRINT_AND_LOG("Heuristically selected an under-approximation MDP size threshold of " << revisedOptions.maxExplorationSize.value() << ".\n");
458 } else {
459 revisedOptions.maxExplorationSize = belExplSettings.getSizeThresholdInit();
460 }
461 if (belExplSettings.isUseClippingSet()) {
462 revisedOptions.useClipping = true;
463 revisedOptions.clippingResolutions = std::vector<uint64_t>(preprocessedPomdpPtr->getNrObservations(), belExplSettings.getClippingGridResolution());
464 }
465 isUnderApproximation = true;
468 std::vector<std::string> relevantRewardModelNames;
469 for (auto const& rewardBound : propertyInfo.rewardBounds) {
470 relevantRewardModelNames.push_back(rewardBound.rewardModelName);
471 }
472 return checker.checkRewardAwareUnfold(env, propertyInfo, revisedOptions, beliefExplorationBounds, relevantRewardModelNames);
473 }
474 return checker.checkUnfold(env, propertyInfo, revisedOptions, beliefExplorationBounds);
475 }();
476 underResultValue = checkResult.value;
477 completedExploration = checkResult.completedExploration;
478 printBeliefExplorationStatistics(checkResult.statistics);
479 isOverApproximation = (completedExploration && !belExplSettings.isUseClippingSet()) || isOverApproximation;
480 }
481
482 if (completedExploration && !belExplSettings.isUseClippingSet()) {
483 updateLowerBound(underResultValue);
484 updateUpperBound(underResultValue);
485 } else {
486 if (isOverApproximation) {
487 if (storm::solver::maximize(propertyInfo.dir)) {
488 updateUpperBound(overResultValue);
489 if (!isUnderApproximation) {
490 lowerBound.reset();
491 }
492 } else {
493 updateLowerBound(overResultValue);
494 if (!isUnderApproximation) {
495 upperBound.reset();
496 }
497 }
498 }
499 if (isUnderApproximation) {
500 if (storm::solver::maximize(propertyInfo.dir)) {
501 updateLowerBound(underResultValue);
502 if (!isOverApproximation) {
503 upperBound.reset();
504 }
505 } else {
506 updateUpperBound(underResultValue);
507 if (!isOverApproximation) {
508 lowerBound.reset();
509 }
510 }
511 }
512 }
513
515 STORM_PRINT_AND_LOG("\nResult till abort: ");
516 } else {
517 STORM_PRINT_AND_LOG("\nResult: ");
518 }
519 printResult(lowerBound, upperBound);
521 return true;
522}
523
524template<typename ValueType, typename BeliefType = ValueType>
526 storm::pomdp::analysis::FormulaInformation const& formulaInfo, storm::logic::Formula const& formula) {
528 bool analysisPerformed = false;
529 if (pomdpSettings.isBeliefExplorationSet()) {
531 if (beliefExplorationSettings.isBeliefMDPNumberTypeDouble()) {
533 } else if (beliefExplorationSettings.isBeliefMDPNumberTypeRational()) {
535 } else if (beliefExplorationSettings.isBeliefMDPNumberTypeMatch()) {
536 STORM_LOG_ASSERT(beliefExplorationSettings.isBeliefMDPNumberTypeMatch(),
537 "Expected belief MDP number type to be set to match the POMDP, but it is not.");
539 }
540 analysisPerformed = true;
541 }
542 if (pomdpSettings.isQualitativeAnalysisSet()) {
543 performQualitativeAnalysis(env, pomdp, formulaInfo, formula);
544 analysisPerformed = true;
545 }
546 if (pomdpSettings.isCheckFullyObservableSet()) {
547 STORM_PRINT_AND_LOG("Analyzing the formula on the fully observable MDP ... ");
550 if (resultPtr) {
551 auto result = resultPtr->template asExplicitQuantitativeCheckResult<ValueType>();
554 STORM_PRINT_AND_LOG("\nResult till abort: ");
555 } else {
556 STORM_PRINT_AND_LOG("\nResult: ");
557 }
558 printResult(std::optional{result.getMin()}, std::optional{result.getMax()});
560 } else {
561 STORM_PRINT_AND_LOG("\nResult: Not available.\n");
562 }
563 analysisPerformed = true;
564 }
565 return analysisPerformed;
566}
567
568template<typename ValueType>
573 bool transformationPerformed = false;
574 bool memoryUnfolded = false;
575 if (pomdpSettings.getMemoryBound() > 1) {
576 STORM_PRINT_AND_LOG("Computing the unfolding for memory bound " << pomdpSettings.getMemoryBound() << " and memory pattern '"
577 << storm::storage::toString(pomdpSettings.getMemoryPattern()) << "' ...");
578 storm::storage::PomdpMemory memory = storm::storage::PomdpMemoryBuilder().build(pomdpSettings.getMemoryPattern(), pomdpSettings.getMemoryBound());
579 std::cout << memory.toString() << '\n';
581 pomdp = memoryUnfolder.transform();
582 STORM_PRINT_AND_LOG(" done.\n");
583 pomdp->printModelInformationToStream(std::cout);
584 transformationPerformed = true;
585 memoryUnfolded = true;
586 }
587
588 // From now on the POMDP is considered memoryless
589
590 if (transformSettings.isMecReductionSet()) {
591 STORM_PRINT_AND_LOG("Eliminating mec choices ...");
592 // Note: Elimination of mec choices only preserves memoryless schedulers.
593 uint64_t oldChoiceCount = pomdp->getNumberOfChoices();
595 pomdp = mecChoiceEliminator.transform(formula);
596 STORM_PRINT_AND_LOG(" done.\n");
597 STORM_PRINT_AND_LOG(oldChoiceCount - pomdp->getNumberOfChoices() << " choices eliminated through MEC choice elimination.\n");
598 pomdp->printModelInformationToStream(std::cout);
599 transformationPerformed = true;
600 }
601
602 if (transformSettings.isTransformBinarySet() || transformSettings.isTransformSimpleSet()) {
603 if (transformSettings.isTransformSimpleSet()) {
604 STORM_PRINT_AND_LOG("Transforming the POMDP to a simple POMDP.");
606 } else {
607 STORM_PRINT_AND_LOG("Transforming the POMDP to a binary POMDP.");
609 }
610 pomdp->printModelInformationToStream(std::cout);
611 STORM_PRINT_AND_LOG(" done.\n");
612 transformationPerformed = true;
613 }
614
615 if (pomdpSettings.isExportToParametricSet()) {
616 STORM_PRINT_AND_LOG("Transforming memoryless POMDP to pMC...");
618 std::string transformMode = transformSettings.getFscApplicationTypeString();
619 auto pmc = toPMCTransformer.transform(storm::transformer::parsePomdpFscApplicationMode(transformMode));
620 STORM_PRINT_AND_LOG(" done.\n");
621 if (transformSettings.allowPostSimplifications()) {
622 STORM_PRINT_AND_LOG("Simplifying pMC...");
624 {formula.asSharedPointer()})
625 ->template as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
626 STORM_PRINT_AND_LOG(" done.\n");
627 pmc->printModelInformationToStream(std::cout);
628 }
629 STORM_PRINT_AND_LOG("Exporting pMC...");
630 storm::analysis::ConstraintCollector constraints(*pmc);
631 auto const& parameterSet = constraints.getVariables();
632 std::vector<storm::RationalFunctionVariable> parameters(parameterSet.begin(), parameterSet.end());
633 std::vector<std::string> parameterNames;
634 for (auto const& parameter : parameters) {
635 parameterNames.push_back(parameter.name());
636 }
637 storm::api::exportSparseModelAsDrn(pmc, pomdpSettings.getExportToParametricFilename(), parameterNames,
638 !ioSettings.isExplicitExportPlaceholdersDisabled());
639 STORM_PRINT_AND_LOG(" done.\n");
640 transformationPerformed = true;
641 }
642 if (transformationPerformed && !memoryUnfolded) {
643 STORM_PRINT_AND_LOG("Implicitly assumed restriction to memoryless schedulers for at least one transformation.\n");
644 }
645 return transformationPerformed;
646}
647
648template<typename ValueType>
651
652 if (!pomdpSettings.isNoCanonicSet()) {
654 pomdp = makeCanonic.transform();
655 }
656
657 if (pomdpSettings.isAnalyzeUniqueObservationsSet()) {
658 STORM_PRINT_AND_LOG("Analyzing states with unique observation ...\n");
660 std::cout << uniqueAnalysis.analyse() << '\n';
661 }
662}
663
664template<typename ValueType>
666 std::shared_ptr<storm::logic::Formula const> formula) {
667 if (formula->asOperatorFormula().getSubformula().isBoundedUntilFormula()) {
668 // TODO: allow for more general reward-bounded until properties than reachability
669
670 auto const& boundedUntilFormula = formula->asOperatorFormula().getSubformula().asBoundedUntilFormula();
671 for (uint64_t i = 0; i < boundedUntilFormula.getDimension(); ++i) {
672 STORM_LOG_THROW(boundedUntilFormula.getLeftSubformula(i).isTrueFormula(), storm::exceptions::NotSupportedException,
673 "Reward-bounded until properties for POMDPs currently require 'true' as the left-hand side, i.e., they must be reward-bounded "
674 "reachability properties.");
675 }
677 // Process bounded until formulas
678 // If level widths are given, unfold the levels and make sure that the level rewards (and only those) are made observable
679 // If explicit unfolding is requested, unfold all reward bounds (if levels were unfolded before, this means a second round of unfolding)
680 // If reward observability is set and no level widths are given, make all rewards occurring in the formula observable. This also happens if no
681 // unfolding was requested.
682 storm::utility::Stopwatch boundedUntilProcessingWatch(true);
683 auto const levelWidths = pomdpSettings.getLevelWidthForBoundedReachability();
684 if (!levelWidths.empty()) {
685 STORM_PRINT_AND_LOG("Perform unfolding for observation levels.\n");
686 // Unfold the levels (includes dimensions with level-width 0)
688 options.levelWidths = levelWidths;
689 auto const unfoldingResult = transformer::RewardBoundUnfolder<ValueType>::transform(*pomdp, *formula, options);
690 pomdp = unfoldingResult.model->template as<storm::models::sparse::Pomdp<ValueType>>();
691 formula = unfoldingResult.formula;
692 // make sure the levels are observable
693 std::set<std::string> levelRewardModels;
694 formula->gatherReferencedRewardModels(levelRewardModels);
696 }
697 std::set<std::string> rewardModelsToObserve;
698 if (pomdpSettings.isRewardObservableSet() && levelWidths.empty()) {
699 formula->gatherReferencedRewardModels(rewardModelsToObserve); // keep rewards to make them observable later
700 }
701 if (pomdpSettings.isBoundedToUnboundedReachabilityTransformationSet() && formula->asOperatorFormula().getSubformula().isBoundedUntilFormula()) {
702 STORM_PRINT_AND_LOG("Perform explicit unfolding of reward bounds.\n");
704 options.preservedRewardModels = rewardModelsToObserve;
705 auto const unfoldingResult = transformer::RewardBoundUnfolder<ValueType>::transform(*pomdp, *formula, options);
706 pomdp = unfoldingResult.model->template as<storm::models::sparse::Pomdp<ValueType>>();
707 formula = unfoldingResult.formula;
708 }
709 if (pomdpSettings.isRewardObservableSet() && levelWidths.empty()) {
710 STORM_PRINT_AND_LOG("Extend observation function to become reward aware.\n");
712 }
713 STORM_LOG_THROW(!levelWidths.empty() || pomdpSettings.isRewardObservableSet() || pomdpSettings.isBoundedToUnboundedReachabilityTransformationSet(),
714 storm::exceptions::InvalidSettingsException,
715 "No handling of bounded until formulas specified. Consider setting --unfold-reward-bound and/or --reward-aware.");
716 STORM_PRINT_AND_LOG("bounded reachability processing done. POMDP Information:\n");
717 pomdp->printModelInformationToStream(std::cout);
718 STORM_PRINT_AND_LOG("Transformed formula: " << *formula << "\n");
719 boundedUntilProcessingWatch.stop();
720 STORM_PRINT_AND_LOG("Time for pre-processing: " << boundedUntilProcessingWatch << ".\n");
721 }
722 auto formulaInfo = storm::pomdp::analysis::getFormulaInformation(*pomdp, *formula);
723 STORM_LOG_THROW(!formulaInfo.isUnsupported(), storm::exceptions::InvalidPropertyException,
724 "The formula '" << *formula << "' is not supported by storm-pomdp.");
725
727 // Note that formulaInfo contains state-based information which potentially needs to be updated during preprocessing
728 if (performPreprocessing(pomdp, formulaInfo, *formula)) {
729 sw.stop();
730 STORM_PRINT_AND_LOG("Time for graph-based POMDP (pre-)processing: " << sw << ".\n");
731 pomdp->printModelInformationToStream(std::cout);
732 }
733
734 sw.restart();
735 if (performTransformation(pomdp, *formula)) {
736 sw.stop();
737 STORM_PRINT_AND_LOG("Time for POMDP transformation(s): " << sw << ".\n");
738 }
739
740 sw.restart();
741 if (performAnalysis(env, pomdp, formulaInfo, *formula)) {
742 sw.stop();
743 STORM_PRINT_AND_LOG("Time for POMDP analysis: " << sw << ".\n");
744 }
745}
746
747template<typename ValueType>
749 std::shared_ptr<storm::logic::Formula const> const& formula) {
750 STORM_LOG_ASSERT(pomdp, "No POMDP given or input POMDP is of unexpected type.");
752
753 if (formula) {
754 processFormula(env, std::move(pomdp), formula);
755 } else {
756 STORM_LOG_WARN("Nothing to be done. Did you forget to specify a formula?");
757 }
758}
759
761 auto symbolicInput = storm::cli::parseSymbolicInput();
763 std::tie(symbolicInput, mpi) = storm::cli::preprocessSymbolicInput(symbolicInput);
766 storm::exceptions::UnexpectedException, "Unexpected ValueType for model building.");
767
768 auto model = storm::cli::buildPreprocessExportModel(symbolicInput, mpi);
769 if (!model) {
770 STORM_PRINT_AND_LOG("No input model given.\n");
771 return;
772 }
773 STORM_LOG_THROW(model->getType() == storm::models::ModelType::Pomdp && model->isSparseModel(), storm::exceptions::WrongFormatException,
774 "Expected a POMDP in sparse representation.");
775
776 std::shared_ptr<storm::logic::Formula const> formula;
777 if (!symbolicInput.properties.empty()) {
778 formula = symbolicInput.properties.front().getRawFormula();
779 STORM_PRINT_AND_LOG("Analyzing property '" << *formula << "'\n");
780 STORM_LOG_WARN_COND(symbolicInput.properties.size() == 1,
781 "There is currently no support for multiple properties. All other properties will be ignored.");
782 }
783
784 if (model->isExact()) {
786 } else {
787 processPomdpFormula(mpi.env, model->template as<storm::models::sparse::Pomdp<double>>(), formula);
788 }
789}
790
791} // namespace cli
792} // namespace pomdp
793} // namespace storm
794
802int main(const int argc, const char** argv) {
803 try {
805 } catch (storm::exceptions::BaseException const& exception) {
806 STORM_LOG_ERROR("An exception caused Storm-pomdp to terminate. The message of the exception is: " << exception.what());
807 return 1;
808 } catch (std::exception const& exception) {
809 STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-pomdp to terminate. The message of this exception is: " << exception.what());
810 return 2;
811 }
812}
Class to collect constraints on parametric Markov chains.
std::set< storm::RationalFunctionVariable > const & getVariables() const
Returns the set of variables in the model.
storm::storage::BitVector analyseProb0(storm::logic::ProbabilityOperatorFormula const &formula) const
storm::storage::BitVector analyseProbSmaller1(storm::logic::ProbabilityOperatorFormula const &formula) const
storm::storage::BitVector analyseProb1(storm::logic::ProbabilityOperatorFormula const &formula) const
This class represents the base class of all exception classes.
virtual const char * what() const noexcept override
Retrieves the message associated with this exception.
BoundedUntilFormula & asBoundedUntilFormula()
Definition Formula.cpp:363
ProbabilityOperatorFormula & asProbabilityOperatorFormula()
Definition Formula.cpp:506
std::shared_ptr< Formula const > asSharedPointer()
Definition Formula.cpp:601
Formula const & getSubformula() const
A qualitative check result over the states of a sparse model.
This class represents a discrete-time Markov chain.
Definition Dtmc.h:16
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:16
This class represents a partially observable Markov decision process.
Definition Pomdp.h:13
WinningRegion const & getLastWinningRegion() const
void setExportSATCalls(std::string const &path)
MemlessSearchPathVariables pathVariableType
bool analyzeForInitialStates(uint64_t k)
Check if you can find a memoryless policy from the initial states.
std::pair< storm::RationalNumber, storm::RationalNumber > computeNrWinningBeliefs() const
storm::RationalNumber beliefSupportStates() const
bool isWinning(uint64_t observation, uint64_t offset) const
void storeToFile(std::string const &path, std::string const &preamble="", bool append=false) const
void updateSinkStates(PomdpType const &pomdp, storm::storage::BitVector &&newSinkStates)
storm::solver::OptimizationDirection const & getOptimizationDirection() const
void updateTargetStates(PomdpType const &pomdp, storm::storage::BitVector &&newTargetStates)
Builds and checks a finite belief MDP approximation of a POMDP.
BeliefBasedModelCheckerResult< BeliefMdpValueType > checkRewardAwareDiscretize(storm::Environment const &env, PropertyInformation const &propertyInformation, storm::pomdp::beliefs::BeliefBasedModelCheckerOptions< BeliefMdpValueType > const &options, uint64_t resolution, bool useDynamic, storage::BeliefExplorationBounds< typename PomdpModelType::ValueType > const &valueBounds, std::vector< std::string > const &relevantRewardModelNames)
Combines reward-aware exploration with Freudenthal triangulation discretization.
BeliefBasedModelCheckerResult< BeliefMdpValueType > checkDiscretize(storm::Environment const &env, PropertyInformation const &propertyInformation, storm::pomdp::beliefs::BeliefBasedModelCheckerOptions< BeliefMdpValueType > const &options, uint64_t resolution, bool useDynamic, storage::BeliefExplorationBounds< PomdpValueType > const &valueBounds)
Explores the belief space and discretises beliefs using the Freudenthal triangualtion approximation.
BeliefBasedModelCheckerResult< BeliefMdpValueType > checkUnfold(storm::Environment const &env, PropertyInformation const &propertyInformation, BeliefBasedModelCheckerOptions< BeliefMdpValueType > const &options, storage::BeliefExplorationBounds< PomdpValueType > const &valueBounds)
Explores the belief MDP by unfolding the belief space.
BeliefBasedModelCheckerResult< BeliefMdpValueType > checkRewardAwareUnfold(storm::Environment const &env, PropertyInformation const &propertyInformation, storm::pomdp::beliefs::BeliefBasedModelCheckerOptions< BeliefMdpValueType > const &options, storage::BeliefExplorationBounds< typename PomdpModelType::ValueType > const &valueBounds, std::vector< std::string > const &relevantRewardModelNames)
Explores a reward-aware belief MDP, splitting beliefs before successor generation by their reward vec...
void generate(storm::storage::BitVector const &targetStates, storm::storage::BitVector const &badStates)
void verifySymbolic(storm::Environment const &env, bool onlyInitial=true)
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transform(storm::models::sparse::Pomdp< ValueType > const &pomdp, storm::storage::BitVector &prob0States, storm::storage::BitVector &prob1States)
static ReturnType transform(storm::models::sparse::Model< ValueType > const &model, storm::logic::Formula const &formula, UnfoldingOptions const &options={})
Unfolds reward-bounded dimensions into the model state space and returns an equivalent formula.
static std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transformRewardAware(storm::models::sparse::Pomdp< ValueType > const &pomdp, std::set< std::string > const &observableRewardModels, bool dropUnreachableStates=true)
Makes rewards observable by extending observations with the state and state-action reward values of t...
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
PomdpMemory build(PomdpMemoryPattern pattern, uint64_t numStates) const
std::string toString() const
std::shared_ptr< storm::models::sparse::Model< storm::RationalFunction > > transform(PomdpFscApplicationMode applicationMode=PomdpFscApplicationMode::SIMPLE_LINEAR) const
PomdpTransformationResult< ValueType > transform(storm::models::sparse::Pomdp< ValueType > const &pomdp, bool transformSimple, bool keepStateValuations=false) const
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transform() const
bool preservesFormula(storm::logic::Formula const &formula) const
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transform(storm::logic::Formula const &formula) const
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transform() const
std::pair< std::shared_ptr< storm::models::sparse::Pomdp< ValueType > >, std::set< uint32_t > > transform(storm::storage::BitVector const &stateSet) const
Ensures that the given set of states is observation closed, potentially, adding new observation(s) A ...
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transform(bool dropUnreachableStates=true) const
A class that provides convenience operations to display run times.
Definition Stopwatch.h:13
void restart()
Reset the stopwatch and immediately start it.
Definition Stopwatch.cpp:59
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_INFO(message)
Definition logging.h:34
#define STORM_LOG_WARN(message)
Definition logging.h:35
#define STORM_LOG_TRACE(message)
Definition logging.h:22
#define STORM_LOG_ERROR(message)
Definition logging.h:36
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:54
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > createTask(std::shared_ptr< const storm::logic::Formula > const &formula, bool onlyInitialStatesRelevant=false)
void exportSparseModelAsDrn(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::string const &filename, std::vector< std::string > const &parameterNames={}, bool allowPlaceholders=true)
Definition export.h:30
std::shared_ptr< storm::models::sparse::Model< ValueType > > performBisimulationMinimization(std::shared_ptr< storm::models::sparse::Model< ValueType > > const &model, std::vector< std::shared_ptr< storm::logic::Formula const > > const &formulas={}, storm::bisimulation::Options const &options={})
std::unique_ptr< storm::modelchecker::CheckResult > verifyWithSparseEngine(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Dtmc< ValueType > > const &dtmc, storm::modelchecker::CheckTask< storm::logic::Formula, ValueType > const &task, bool preferEliminationChecker=false)
std::shared_ptr< storm::models::ModelBase > buildPreprocessExportModel(SymbolicInput const &input, ModelProcessingInformation const &mpi)
SymbolicInput parseSymbolicInput()
int process(std::string const &name, std::string const &executableName, std::function< void(std::string const &, std::string const &)> initSettingsFunc, std::function< void(void)> processOptionsFunc, const int argc, const char **argv)
Processes the options and returns the exit code.
Definition cli.cpp:96
std::pair< SymbolicInput, ModelProcessingInformation > preprocessSymbolicInput(SymbolicInput const &input)
FormulaInformation getFormulaInformation(PomdpType const &pomdp, storm::logic::ProbabilityOperatorFormula const &formula)
bool performPreprocessing(std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > &pomdp, storm::pomdp::analysis::FormulaInformation &formulaInfo, storm::logic::Formula const &formula)
Perform preprocessings based on the graph structure (if requested or necessary). Return true,...
void processPomdp(std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > &pomdp)
void processPomdpFormula(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > &&pomdp, std::shared_ptr< storm::logic::Formula const > const &formula)
bool performTransformation(std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > &pomdp, storm::logic::Formula const &formula)
MemlessSearchOptions fillMemlessSearchOptionsFromSettings()
bool performAnalysis(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > const &pomdp, storm::pomdp::analysis::FormulaInformation const &formulaInfo, storm::logic::Formula const &formula)
void performQualitativeAnalysis(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > const &origpomdp, storm::pomdp::analysis::FormulaInformation const &formulaInfo, storm::logic::Formula const &formula)
bool performBeliefExploration(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > const &pomdp, storm::pomdp::analysis::FormulaInformation const &formulaInfo, storm::logic::Formula const &formula)
void printResult(std::optional< ValueType > const &lowerBound, std::optional< ValueType > const &upperBound)
void processFormula(storm::Environment const &env, std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > &&pomdp, std::shared_ptr< storm::logic::Formula const > formula)
void printBeliefExplorationStatistics(Statistics const &statistics)
MemlessSearchPathVariables pathVariableTypeFromString(std::string const &in)
bool detectFiniteBeliefMdp(storm::models::sparse::Pomdp< ValueType > const &pomdp, std::optional< storm::storage::BitVector > const &targetStates)
This method tries to detect that the beliefmdp is finite.
void initializePomdpSettings(std::string const &name, std::string const &executableName)
Initialize the settings manager.
SettingsType const & getModule()
Get module.
bool constexpr maximize(OptimizationDirection d)
std::string toString(PomdpMemoryPattern const &pattern)
std::shared_ptr< storm::models::sparse::Model< double > > sparseRationalModelToDouble(std::shared_ptr< storm::models::sparse::Model< storm::RationalNumber > > const &inputModel, double precision)
PomdpFscApplicationMode parsePomdpFscApplicationMode(std::string const &mode)
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
Definition graph.cpp:42
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
ExtendedValueType< ValueType > fromSentinel(ValueType &&value)
Recognises the value that storm::utility::infinity still yields for the value types that have no infi...
ValueType zero()
Definition constants.cpp:26
std::conditional_t< storm::NumberTraits< ValueType >::HasInfinity, ValueType, ExtendedNumber< ValueType > > ExtendedValueType
The type to use for values that may be infinite.
ValueType one()
Definition constants.cpp:21
bool isInfinity(ValueType const &a)
TargetType convertNumber(SourceType const &number)
l3pp::LogLevel getLogLevel()
Gets the global log level.
#define STORM_PRINT_AND_LOG(message)
Definition print.h:20
int main(const int argc, const char **argv)
Entry point for the pomdp backend.
static const bool IsExact
bool cutZeroGap
Cut non-target beliefs only when their preprocessing lower and upper bounds have exactly zero gap.
storm::utility::ExtendedValueType< BeliefMdpValueType > value
Property data consumed by the belief MDP construction.
std::set< BeliefObservationType > targetObservations
Struct for storing precomputed values bounding the actual values on the POMDP.
std::optional< ExtremePOMDPValueBound< POMDPValueType > > extremeBounds
std::optional< PreprocessingPomdpValueBounds< POMDPValueType > > preprocessingBounds
Struct for storing precomputed values bounding the actual values on the POMDP.
std::vector< std::vector< POMDPValueType > > lower
std::vector< std::vector< POMDPValueType > > upper
std::vector< uint64_t > levelWidths
Allows to define a levelWidth for each dimension.
std::set< std::string > preservedRewardModels
The reward models that will be preserved in the unfolding.
std::unordered_map< std::string, RewardModelType > rewardModels
storm::storage::SparseMatrix< ValueType > transitionMatrix
std::optional< storm::storage::sparse::Valuations > observationValuations
std::optional< storm::models::sparse::ChoiceLabeling > choiceLabeling
storm::models::sparse::StateLabeling stateLabeling
std::optional< std::vector< uint32_t > > observabilityClasses