From 83d4b5000cd96ea378dedfd60a28047f03948a4a Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:33:30 +0100 Subject: [PATCH 01/27] Add ValueType to ExplicitQualitativeCheckResult --- src/storm-cli-utilities/model-handling.h | 20 +-- .../api/counterexamples.cpp | 2 +- .../MILPMinimalLabelSetGenerator.h | 6 +- .../SMTMinimalLabelSetGenerator.h | 6 +- .../modelchecker/DFTModelChecker.cpp | 2 +- src/storm-pars-cli/sampling.h | 2 +- src/storm-pars-cli/solutionFunctions.h | 2 +- ...rseDerivativeInstantiationModelChecker.cpp | 8 +- .../SparseDtmcInstantiationModelChecker.cpp | 2 +- .../SparseMdpInstantiationModelChecker.cpp | 2 +- ...SparseDtmcParameterLiftingModelChecker.cpp | 10 +- .../SparseMdpParameterLiftingModelChecker.cpp | 10 +- .../SparseParameterLiftingModelChecker.cpp | 15 +-- ...tingSparseParameterLiftingModelChecker.cpp | 10 +- .../region/monotonicity/OrderExtender.cpp | 6 +- .../SparseParametricDtmcSimplifier.cpp | 10 +- .../SparseParametricMdpSimplifier.cpp | 10 +- .../analysis/PermissiveSchedulers.cpp | 10 +- src/storm-pomdp-cli/storm-pomdp.cpp | 2 +- .../analysis/FormulaInformation.cpp | 2 +- .../analysis/QualitativeAnalysisOnGraphs.cpp | 2 +- .../GlobalPomdpMecChoiceEliminator.cpp | 2 +- src/storm/api/export.h | 3 +- .../modelchecker/AbstractModelChecker.cpp | 2 +- .../csl/SparseCtmcCslModelChecker.cpp | 26 ++-- .../SparseMarkovAutomatonCslModelChecker.cpp | 22 ++-- .../SparseCbAchievabilityQuery.cpp | 2 +- ...eterministicSchedsAchievabilityChecker.cpp | 4 +- .../DeterministicSchedsObjectiveHelper.cpp | 2 +- .../pcaa/SparsePcaaAchievabilityQuery.cpp | 3 +- .../pcaa/SparsePcaaQuantitativeQuery.cpp | 3 +- .../SparseMultiObjectivePreprocessor.cpp | 30 ++--- .../prctl/HybridMdpPrctlModelChecker.cpp | 2 +- .../prctl/SparseDtmcPrctlModelChecker.cpp | 30 ++--- .../prctl/SparseMdpPrctlModelChecker.cpp | 28 ++--- .../helper/rewardbounded/ProductModel.cpp | 10 +- .../SparsePropositionalModelChecker.cpp | 6 +- .../SparseDtmcEliminationModelChecker.cpp | 22 ++-- .../modelchecker/results/CheckResult.cpp | 22 +++- src/storm/modelchecker/results/CheckResult.h | 8 +- .../ExplicitParetoCurveCheckResult.cpp | 4 +- .../ExplicitQualitativeCheckResult.cpp | 117 +++++++++++++----- .../results/ExplicitQualitativeCheckResult.h | 6 + .../ExplicitQuantitativeCheckResult.cpp | 12 +- .../results/ExplicitQuantitativeCheckResult.h | 3 +- .../results/LexicographicCheckResult.cpp | 4 +- .../BisimulationDecomposition.cpp | 4 +- src/storm/transformer/MemoryIncorporation.cpp | 3 +- .../monotonicity/MonotonicityCheckerTest.cpp | 10 +- .../region/monotonicity/OrderExtenderTest.cpp | 10 +- .../analysis/MilpPermissiveSchedulerTest.cpp | 4 +- .../analysis/SmtPermissiveSchedulerTest.cpp | 4 +- .../csl/CtmcCslModelCheckerTest.cpp | 2 +- .../csl/LraCtmcCslModelCheckerTest.cpp | 2 +- .../MarkovAutomatonCslModelCheckerTest.cpp | 2 +- ...ultiObjectiveSchedRestModelCheckerTest.cpp | 10 +- ...arseMaCbMultiObjectiveModelCheckerTest.cpp | 4 +- ...seMaPcaaMultiObjectiveModelCheckerTest.cpp | 6 +- ...rseMdpCbMultiObjectiveModelCheckerTest.cpp | 8 +- ...eMdpPcaaMultiObjectiveModelCheckerTest.cpp | 8 +- .../prctl/dtmc/DtmcPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/MdpPrctlModelCheckerTest.cpp | 2 +- .../prctl/mdp/QuantileQueryTest.cpp | 2 +- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 4 +- 64 files changed, 343 insertions(+), 256 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 8dcd741e1b..6f7eaee4b2 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -903,14 +903,14 @@ inline void printCounterexample(std::shared_ptr - requires(!std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { +requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, + SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template - requires(std::derived_from>) -inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { +requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, + SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -966,8 +966,8 @@ inline void generateCounterexamples(std::shared_ptr const& sparseMode } template - requires(!storm::IsIntervalType) -void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { +requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, + storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1034,9 +1034,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template - requires(!storm::IsIntervalType) -void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { +requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, + storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; @@ -1302,7 +1302,7 @@ void verifyModel(std::shared_ptr> const& std::unique_ptr filter; if (filterForInitialStates) { - filter = std::make_unique(sparseModel->getInitialStates()); + filter = std::make_unique>(sparseModel->getInitialStates()); } else if (!states->isTrueFormula()) { // No need to apply filter if it is the formula 'true' filter = storm::api::verifyWithSparseEngine(mpi.env, sparseModel, storm::api::createTask(states, false)); } diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index 6738bf2239..af0104a901 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -45,7 +45,7 @@ std::shared_ptr computeKShortestPathCoun storm::logic::EventuallyFormula const& eventuallyFormula = subformula.asEventuallyFormula(); std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); // Check if counterexample is even possible storm::storage::BitVector phiStates(model->getNumberOfStates(), true); diff --git a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h index cdd057d069..e14a490411 100644 --- a/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1023,8 +1023,8 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); phiStates = leftQualitativeResult.getTruthValuesVector(); psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -1033,7 +1033,7 @@ class MILPMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); phiStates = storm::storage::BitVector(mdp.getNumberOfStates(), true); psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h index 4cf453c738..5a837289ae 100644 --- a/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h +++ b/src/storm-counterexamples/counterexamples/SMTMinimalLabelSetGenerator.h @@ -2157,8 +2157,8 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr leftResult = modelchecker.check(env, untilFormula.getLeftSubformula()); std::unique_ptr rightResult = modelchecker.check(env, untilFormula.getRightSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->asExplicitQualitativeCheckResult(); - storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& leftQualitativeResult = leftResult->template asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& rightQualitativeResult = rightResult->template asExplicitQualitativeCheckResult(); result.phiStates = leftQualitativeResult.getTruthValuesVector(); result.psiStates = rightQualitativeResult.getTruthValuesVector(); @@ -2167,7 +2167,7 @@ class SMTMinimalLabelSetGenerator { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->template asExplicitQualitativeCheckResult(); result.phiStates = storm::storage::BitVector(model.getNumberOfStates(), true); result.psiStates = subQualitativeResult.getTruthValuesVector(); diff --git a/src/storm-dft/modelchecker/DFTModelChecker.cpp b/src/storm-dft/modelchecker/DFTModelChecker.cpp index 6dbbc1f31a..e56ed46673 100644 --- a/src/storm-dft/modelchecker/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/DFTModelChecker.cpp @@ -461,7 +461,7 @@ std::vector DFTModelChecker::checkModel(std::shared_ptr(model, storm::api::createTask(property, true))); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); ValueType resultValue = result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second; results.push_back(resultValue); } else { diff --git a/src/storm-pars-cli/sampling.h b/src/storm-pars-cli/sampling.h index 622f806415..b163dabe3f 100644 --- a/src/storm-pars-cli/sampling.h +++ b/src/storm-pars-cli/sampling.h @@ -115,7 +115,7 @@ void verifyPropertiesAtSamplePoints(ModelType const& model, cli::SymbolicInput c valuationWatch.stop(); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model.getInitialStates())); } printInitialStatesResult(result, &valuationWatch, &valuation); diff --git a/src/storm-pars-cli/solutionFunctions.h b/src/storm-pars-cli/solutionFunctions.h index 294c50c56b..8c74e278ff 100644 --- a/src/storm-pars-cli/solutionFunctions.h +++ b/src/storm-pars-cli/solutionFunctions.h @@ -31,7 +31,7 @@ void computeSolutionFunctionsWithSparseEngine(std::shared_ptr result = storm::api::verifyWithSparseEngine(model, storm::api::createTask(formula, true)); if (result) { - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); } return result; }, diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index 5bf5ec4f12..ce1ae41f60 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); diff --git a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp index 6b7387b67c..6551db7209 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseDtmcInstantiationModelChecker.cpp @@ -181,7 +181,7 @@ std::unique_ptr SparseDtmcInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp index dc75828481..d866cc858b 100644 --- a/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp +++ b/src/storm-pars/modelchecker/instantiation/SparseMdpInstantiationModelChecker.cpp @@ -220,7 +220,7 @@ std::unique_ptr SparseMdpInstantiationModelChecker0 steps std::unique_ptr subFormulaResult = modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula()); - maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + maybeStates = maybeStates & ~(subFormulaResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); hint.setMaybeStates(std::move(maybeStates)); hint.setComputeOnlyMaybeStates(true); } else { diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 11ada9bdd9..150f271501 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -151,9 +151,9 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -193,9 +193,9 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -265,7 +265,7 @@ void SparseDtmcParameterLiftingModelCheckerasExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index 9e9c2f366f..ff81f266b4 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -110,9 +110,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -153,9 +153,9 @@ void SparseMdpParameterLiftingModelChecker::speci propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -204,7 +204,7 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp index 69964a1cff..0cb3c6a252 100644 --- a/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseParameterLiftingModelChecker.cpp @@ -101,15 +101,16 @@ RegionResult SparseParameterLiftingModelChecker:: (result == RegionResult::Unknown || result == RegionResult::ExistsIllDefined || result == RegionResult::CenterIllDefined)) { auto const center = region.region.getCenterPoint(); if (getInstantiationChecker(false).isWellDefined(center)) { - result = getInstantiationChecker(false).check(env, center)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] + result = getInstantiationChecker(false).check(env, center)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] ? RegionResult::CenterSat : RegionResult::CenterViolated; } else { auto const lowerCorner = region.region.getLowerBoundaries(); if (getInstantiationChecker(false).isWellDefined(lowerCorner)) { - result = getInstantiationChecker(false).check(env, lowerCorner)->asExplicitQualitativeCheckResult()[getUniqueInitialState()] - ? RegionResult::ExistsSat - : RegionResult::ExistsViolated; + result = + getInstantiationChecker(false).check(env, lowerCorner)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()] + ? RegionResult::ExistsSat + : RegionResult::ExistsViolated; } else { result = RegionResult::CenterIllDefined; } @@ -143,7 +144,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto const valuation = getOptimalValuationForMonotonicity(region.region, globalMonotonicity->getMonotonicityResult(), dirToCheck); STORM_LOG_ASSERT(valuation.size() == region.region.getVariables().size(), "Not all parameters seem to be monotonic."); auto& checker = existsSat ? getInstantiationCheckerSAT(false) : getInstantiationCheckerVIO(false); - bool const monCheckResult = checker.check(env, valuation)->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const monCheckResult = checker.check(env, valuation)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if (existsSat == monCheckResult) { result = existsSat ? RegionResult::AllSat : RegionResult::AllViolated; STORM_LOG_INFO("Region " << region.region << " is " << result << ", discovered with instantiation checker on " << valuation @@ -165,7 +166,7 @@ RegionResult SparseParameterLiftingModelChecker:: // Try to prove AllSat or AllViolated through parameterLifting auto const checkResult = this->check(env, region, dirToCheck); if (checkResult) { - bool const value = checkResult->asExplicitQualitativeCheckResult()[getUniqueInitialState()]; + bool const value = checkResult->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]; if ((dirToCheck == dirForSat) == value) { result = (dirToCheck == dirForSat) ? RegionResult::AllSat : RegionResult::AllViolated; } else if (sampleVerticesOfRegion) { @@ -196,7 +197,7 @@ RegionResult SparseParameterLiftingModelChecker:: auto vertices = region.getVerticesOfRegion(region.getVariables()); auto vertexIt = vertices.begin(); while (vertexIt != vertices.end() && !(hasSatPoint && hasViolatedPoint)) { - if (getInstantiationChecker(false).check(env, *vertexIt)->asExplicitQualitativeCheckResult()[getUniqueInitialState()]) { + if (getInstantiationChecker(false).check(env, *vertexIt)->template asExplicitQualitativeCheckResult()[getUniqueInitialState()]) { hasSatPoint = true; } else { hasViolatedPoint = true; diff --git a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp index 05fa65ef00..184b549475 100644 --- a/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/ValidatingSparseParameterLiftingModelChecker.cpp @@ -91,8 +91,9 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; + bool preciseResult = + preciseChecker.check(env, region, parameterOptDir) + ->template asExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; bool preciseResultAgrees = preciseResult == (currentResult == RegionResult::AllSat); if (!preciseResultAgrees) { @@ -103,8 +104,9 @@ RegionResult ValidatingSparseParameterLiftingModelCheckerasExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; + preciseResult = + preciseChecker.check(env, region, parameterOptDir) + ->template asExplicitQualitativeCheckResult()[*preciseChecker.getConsideredParametricModel().getInitialStates().begin()]; if (preciseResult && parameterOptDir == preciseChecker.getCurrentCheckTask().getOptimizationDirection()) { currentResult = RegionResult::AllSat; } else if (!preciseResult && parameterOptDir == storm::solver::invert(preciseChecker.getCurrentCheckTask().getOptimizationDirection())) { diff --git a/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp b/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp index 90cabf4968..a57d2d9ead 100644 --- a/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp +++ b/src/storm-pars/modelchecker/region/monotonicity/OrderExtender.cpp @@ -102,16 +102,16 @@ std::shared_ptr OrderExtender::getBottomTopOrder assert(formula->isProbabilityOperatorFormula()); if (formula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { phiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } else { assert(formula->asProbabilityOperatorFormula().getSubformula().isEventuallyFormula()); phiStates = storage::BitVector(numberOfStates, true); psiStates = propositionalChecker.check(formula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); } // Get the maybeStates diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index 7258cbb5b2..ea66d7728e 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -30,9 +30,9 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -97,10 +97,10 @@ bool SparseParametricDtmcSimplifier::simplifyForBoundedUntilPro return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = storm::utility::graph::performProbGreater0(this->originalModel.getBackwardTransitions(), phiStates, psiStates, true, upperStepBound); @@ -152,7 +152,7 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 375690682f..4026d9dcfb 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -35,9 +35,9 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti return false; } storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -121,10 +121,10 @@ bool SparseParametricMdpSimplifier::simplifyForBoundedUntilProb return false; } storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getLeftSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asBoundedUntilFormula().getRightSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector()); storm::storage::BitVector probGreater0States = minimizing ? storm::utility::graph::performProbGreater0A(this->originalModel.getTransitionMatrix(), @@ -182,7 +182,7 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa return false; } storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm-permissive/analysis/PermissiveSchedulers.cpp b/src/storm-permissive/analysis/PermissiveSchedulers.cpp index 5ce205bc4d..a73a11c45f 100644 --- a/src/storm-permissive/analysis/PermissiveSchedulers.cpp +++ b/src/storm-permissive/analysis/PermissiveSchedulers.cpp @@ -20,8 +20,9 @@ boost::optional> computePermissiveSchedulerViaMILP storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); @@ -49,8 +50,9 @@ boost::optional> computePermissiveSchedulerViaSMT( storm::modelchecker::SparsePropositionalModelChecker> propMC(mdp); STORM_LOG_ASSERT(safeProp.getSubformula().isEventuallyFormula(), "No eventually formula."); auto backwardTransitions = mdp.getBackwardTransitions(); - storm::storage::BitVector goalstates = - propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); goalstates = storm::utility::graph::performProb1A(mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); diff --git a/src/storm-pomdp-cli/storm-pomdp.cpp b/src/storm-pomdp-cli/storm-pomdp.cpp index 45805c4cc7..45f5595dcb 100644 --- a/src/storm-pomdp-cli/storm-pomdp.cpp +++ b/src/storm-pomdp-cli/storm-pomdp.cpp @@ -273,7 +273,7 @@ bool performAnalysis(std::shared_ptr> co storm::api::createTask(formula.asSharedPointer(), true)); if (resultPtr) { auto result = resultPtr->template asExplicitQuantitativeCheckResult(); - result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); + result.filter(storm::modelchecker::ExplicitQualitativeCheckResult(pomdp->getInitialStates())); if (storm::utility::resources::isTerminate()) { STORM_PRINT_AND_LOG("\nResult till abort: "); } else { diff --git a/src/storm-pomdp/analysis/FormulaInformation.cpp b/src/storm-pomdp/analysis/FormulaInformation.cpp index 3b7ad31bbf..62aaee7078 100644 --- a/src/storm-pomdp/analysis/FormulaInformation.cpp +++ b/src/storm-pomdp/analysis/FormulaInformation.cpp @@ -114,7 +114,7 @@ template storm::storage::BitVector getStates(storm::logic::Formula const& propositionalFormula, bool formulaInverted, PomdpType const& pomdp) { storm::modelchecker::SparsePropositionalModelChecker mc(pomdp); auto checkResult = mc.check(propositionalFormula); - storm::storage::BitVector resultBitVector(checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector resultBitVector(checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector()); if (formulaInverted) { resultBitVector.complement(); } diff --git a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp index 3f0f71845c..5a9a6fcea5 100644 --- a/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp +++ b/src/storm-pomdp/analysis/QualitativeAnalysisOnGraphs.cpp @@ -202,7 +202,7 @@ storm::storage::BitVector QualitativeAnalysisOnGraphs::checkPropositi storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class QualitativeAnalysisOnGraphs; diff --git a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp index a357cc5917..a8f1f388a6 100644 --- a/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp +++ b/src/storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.cpp @@ -234,7 +234,7 @@ storm::storage::BitVector GlobalPomdpMecChoiceEliminator::checkPropos storm::modelchecker::SparsePropositionalModelChecker> mc(pomdp); STORM_LOG_THROW(mc.canHandle(propositionalFormula), storm::exceptions::InvalidPropertyException, "Propositional model checker can not handle formula " << propositionalFormula); - return mc.check(propositionalFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return mc.check(propositionalFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template class GlobalPomdpMecChoiceEliminator; diff --git a/src/storm/api/export.h b/src/storm/api/export.h index c24ea4ce33..baff690a6b 100644 --- a/src/storm/api/export.h +++ b/src/storm/api/export.h @@ -115,7 +115,8 @@ inline void exportCheckResultToJson(std::shared_ptrisExplicitQualitativeCheckResult()) { - auto j = checkResult->asExplicitQualitativeCheckResult().toJson(model->getOptionalStateValuations(), model->getStateLabeling()); + auto j = checkResult->template asExplicitQualitativeCheckResult().template toJson(model->getOptionalStateValuations(), + model->getStateLabeling()); stream << storm::dumpJson(j); } else { STORM_LOG_THROW(checkResult->isExplicitQuantitativeCheckResult(), storm::exceptions::NotSupportedException, diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index f81331c3d2..6b42c5be6c 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -150,7 +150,7 @@ std::unique_ptr AbstractModelChecker::computeStateFormul std::unique_ptr resultPointer = this->check(env, checkTask.getFormula()); if (resultPointer->isExplicitQualitativeCheckResult()) { STORM_LOG_ASSERT(ModelType::Representation == storm::models::ModelRepresentation::Sparse, "Unexpected model type."); - return std::make_unique>(resultPointer->asExplicitQualitativeCheckResult()); + return std::make_unique>(resultPointer->template asExplicitQualitativeCheckResult()); } else { STORM_LOG_ASSERT(resultPointer->isSymbolicQualitativeCheckResult(), "Unexpected result type."); STORM_LOG_ASSERT(ModelType::Representation != storm::models::ModelRepresentation::Sparse, "Unexpected model type."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 8a5e847156..b36579b09c 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -57,8 +57,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); @@ -86,7 +86,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -97,7 +97,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), probabilisticTransitions, probabilisticTransitions.transpose(), @@ -111,8 +111,8 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), @@ -130,7 +130,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -148,7 +148,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -196,7 +196,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -220,7 +220,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto probabilisticTransitions = this->getModel().computeProbabilityMatrix(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(probabilisticTransitions, this->getModel().getExitRateVector()); @@ -246,7 +246,7 @@ std::unique_ptr SparseCtmcCslModelChecker::com Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -269,8 +269,8 @@ std::vector SparseCtmcCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities( env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 203cbce8f1..f5aa67bc85 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -72,10 +72,10 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on MAs are not supported."); @@ -103,7 +103,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -116,7 +116,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -135,8 +135,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), @@ -157,7 +157,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -183,7 +183,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -205,7 +205,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards( @@ -247,7 +247,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper( this->getModel().getTransitionMatrix(), this->getModel().getMarkovianStates(), this->getModel().getExitRates()); @@ -291,7 +291,7 @@ std::unique_ptr SparseMarkovAutomatonCslModelCheckergetModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityTimes( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), diff --git a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp index 225b7b12f5..4bfd4de17f 100644 --- a/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/constraintbased/SparseCbAchievabilityQuery.cpp @@ -34,7 +34,7 @@ template std::unique_ptr SparseCbAchievabilityQuery::check(Environment const& env) { bool result = this->checkAchievability(); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp index cedca9edfe..75bdfe5c8b 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsAchievabilityChecker.cpp @@ -63,13 +63,13 @@ std::unique_ptr DeterministicSchedsAchievabilityCheckercheck(env, thresholdPolytope, eps); bool const isAchievable = achievingPoint.has_value(); + using ValueType = typename SparseModelType::ValueType; if (isAchievable) { STORM_LOG_INFO( "Found achievable point: " << storm::utility::vector::toString(achievingPoint->first) << " ( approx. " << storm::utility::vector::toString(storm::utility::vector::convertNumericVector(achievingPoint->first)) << " )."); if (optimizingObjectiveIndex.has_value()) { - using ValueType = typename SparseModelType::ValueType; // Average between obtained lower- and upper bounds auto result = storm::utility::convertNumber(achievingPoint->first[*optimizingObjectiveIndex] + achievingPoint->second); @@ -80,7 +80,7 @@ std::unique_ptr DeterministicSchedsAchievabilityChecker>(originalModelInitialState, result); } } - return std::make_unique(originalModelInitialState, isAchievable); + return std::make_unique>(originalModelInitialState, isAchievable); } template class DeterministicSchedsAchievabilityChecker, storm::RationalNumber>; diff --git a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp index 0346b41e4f..c1d03129b9 100644 --- a/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp +++ b/src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.cpp @@ -39,7 +39,7 @@ storm::storage::BitVector evaluatePropositionalFormula(ModelType const& model, s auto checkResult = mc.check(formula); STORM_LOG_THROW(checkResult && checkResult->isExplicitQualitativeCheckResult(), storm::exceptions::UnexpectedException, "Unexpected type of check result for subformula " << formula << "."); - return checkResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return checkResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp index 9271fe33e6..562f4dbfc5 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaAchievabilityQuery.cpp @@ -51,7 +51,8 @@ std::unique_ptr SparsePcaaAchievabilityQuerycheckAchievability(env); - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), result)); } template diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp index c13762c22e..e4e613f69a 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuantitativeQuery.cpp @@ -91,7 +91,8 @@ std::unique_ptr SparsePcaaQuantitativeQuery(new ExplicitQuantitativeCheckResult( this->originalModel.getInitialStates().getNextSetIndex(0), resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); + return std::unique_ptr( + new ExplicitQualitativeCheckResult(this->originalModel.getInitialStates().getNextSetIndex(0), false)); } } diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 6eabbd6bda..1a51f2cafc 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -139,9 +139,9 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->asExplicitQualitativeCheckResult().getTruthValuesVector(); + mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +151,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +161,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +181,7 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,13 +210,13 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); } } else if (opFormula->isLongRunAverageOperatorFormula()) { - auto lraStates = mc.check(pathFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lraStates = mc.check(pathFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Compute Sat(Forall F (Forall G not "lraStates")) auto forallGloballyNotLraStates = storm::utility::graph::performProb0A(backwardTransitions, ~lraStates, lraStates); absorbingStatesForSubformula = storm::utility::graph::performProb1A(model->getTransitionMatrix(), model->getNondeterministicChoiceIndices(), @@ -432,7 +432,7 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +445,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +455,7 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +542,7 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index 344766e323..81815a9d85 100644 --- a/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -176,7 +176,7 @@ std::unique_ptr HybridMdpPrctlModelChecker::checkMultiOb // Convert the explicit result if (explicitResult->isExplicitQualitativeCheckResult()) { - if (explicitResult->asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { + if (explicitResult->template asExplicitQualitativeCheckResult()[*sparseModel->getInitialStates().begin()]) { return std::unique_ptr(new storm::modelchecker::SymbolicQualitativeCheckResult( this->getModel().getReachableStates(), this->getModel().getInitialStates(), this->getModel().getManager().getBddOne())); } else { diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 1686bbe010..431039c622 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -92,8 +92,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -109,7 +109,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -121,8 +121,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -135,7 +135,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet()); @@ -151,7 +151,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -168,7 +168,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -236,7 +236,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -249,7 +249,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.getHint()); @@ -290,7 +290,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); @@ -320,8 +320,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -340,8 +340,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index e532228189..8d19c3dea6 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -139,8 +139,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to have discrete upper time bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -158,7 +158,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); @@ -172,8 +172,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), @@ -192,7 +192,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet()); @@ -215,7 +215,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -245,7 +245,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -276,8 +276,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); if constexpr (std::is_same_v) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { @@ -363,7 +363,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -383,7 +383,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), checkTask.isProduceSchedulersSet(), @@ -446,7 +446,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseNondeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskNondeterministic(helper, checkTask, this->getModel()); @@ -499,7 +499,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto ret = lexicographic::check(env, this->getModel(), checkTask, formulaChecker); std::unique_ptr result(new LexicographicCheckResult(ret.values, *this->getModel().getInitialStates().begin())); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 7bb836cc88..02b9e2f177 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -133,8 +133,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector()); + (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +155,7 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +426,9 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index 094a2332cf..8fa08b56c7 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -35,9 +35,9 @@ std::unique_ptr SparsePropositionalModelChecker::c Environment const& env, CheckTask const& checkTask) { storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates()))); } } @@ -47,7 +47,7 @@ std::unique_ptr SparsePropositionalModelChecker::c storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); - return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } template diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 43296a4d13..506f03b3ff 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -55,7 +55,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker const& checkTask) { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -112,7 +112,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -177,7 +177,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(initialStates)); + checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); } return checkResult; } @@ -350,8 +350,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Start by determining the states that have a non-zero probability of reaching the target states within the // time bound. @@ -444,7 +444,7 @@ std::unique_ptr SparseDtmcEliminationModelCheckerfilter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); + checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); } return checkResult; } @@ -457,8 +457,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); @@ -538,7 +538,7 @@ std::unique_ptr SparseDtmcEliminationModelChecker subResultPointer = this->check(eventuallyFormula.getSubformula()); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); @@ -650,8 +650,8 @@ std::unique_ptr SparseDtmcEliminationModelChecker leftResultPointer = this->check(conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - storm::storage::BitVector phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - storm::storage::BitVector psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 8549ce26d0..c43c2cf441 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -82,12 +82,14 @@ bool CheckResult::isHybridQuantitativeCheckResult() const { return false; } -ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult() { + return dynamic_cast&>(*this); } -ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { - return dynamic_cast(*this); +template +ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const { + return dynamic_cast const&>(*this); } template @@ -188,6 +190,8 @@ template QuantitativeCheckResult const& CheckResult::asQuantitativeCheck template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; template LexicographicCheckResult& CheckResult::asLexicographicCheckResult(); @@ -221,6 +225,8 @@ template QuantitativeCheckResult const& CheckResult::asQu template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; template QuantitativeCheckResult& CheckResult::asQuantitativeCheckResult(); template QuantitativeCheckResult const& CheckResult::asQuantitativeCheckResult() const; @@ -228,6 +234,9 @@ template QuantitativeCheckResult const& CheckResult::as template ExplicitQuantitativeCheckResult& CheckResult::asExplicitQuantitativeCheckResult(); template ExplicitQuantitativeCheckResult const& CheckResult::asExplicitQuantitativeCheckResult() const; +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + template ExplicitParetoCurveCheckResult& CheckResult::asExplicitParetoCurveCheckResult(); template ExplicitParetoCurveCheckResult const& CheckResult::asExplicitParetoCurveCheckResult() const; @@ -235,5 +244,10 @@ template LexicographicCheckResult& CheckResult::asLexicog template LexicographicCheckResult const& CheckResult::asLexicographicCheckResult() const; #endif + +// Instantiation for storm::Interval (carl::Interval) +template ExplicitQualitativeCheckResult& CheckResult::asExplicitQualitativeCheckResult(); +template ExplicitQualitativeCheckResult const& CheckResult::asExplicitQualitativeCheckResult() const; + } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/CheckResult.h b/src/storm/modelchecker/results/CheckResult.h index f46e1abcf9..c8ba918329 100644 --- a/src/storm/modelchecker/results/CheckResult.h +++ b/src/storm/modelchecker/results/CheckResult.h @@ -13,6 +13,7 @@ namespace modelchecker { class QualitativeCheckResult; template class QuantitativeCheckResult; +template class ExplicitQualitativeCheckResult; template @@ -77,8 +78,11 @@ class CheckResult { template QuantitativeCheckResult const& asQuantitativeCheckResult() const; - ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; + template + ExplicitQualitativeCheckResult& asExplicitQualitativeCheckResult(); + + template + ExplicitQualitativeCheckResult const& asExplicitQualitativeCheckResult() const; template ExplicitQuantitativeCheckResult& asExplicitQuantitativeCheckResult(); diff --git a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp index a9d59197a5..ac58ec1fc2 100644 --- a/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitParetoCurveCheckResult.cpp @@ -56,8 +56,8 @@ void ExplicitParetoCurveCheckResult::filter(QualitativeCheckResult co STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index f608a3065b..9404a7c355 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,53 +3,67 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/adapters/JsonAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm/utility/macros.h" namespace storm { namespace modelchecker { -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { + +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult() : truthValues(map_type()) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type const& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(map_type&& map) : truthValues(map) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value) : truthValues(map_type()) { boost::get(truthValues)[state] = value; } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm::storage::BitVector&& truthValues) : truthValues(std::move(truthValues)) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { // Intentionally left empty. } -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) : truthValues(std::move(truthValues)) { +template +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) + : truthValues(std::move(truthValues)) { // Intentionally left empty. } -std::unique_ptr ExplicitQualitativeCheckResult::clone() const { - return std::make_unique(this->truthValues); +template +std::unique_ptr ExplicitQualitativeCheckResult::clone() const { + return std::make_unique>(this->truthValues); } -void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, bool logicalAnd) { +template +void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitativeCheckResult& first, QualitativeCheckResult const& second, + bool logicalAnd) { STORM_LOG_THROW(second.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); STORM_LOG_THROW(first.isResultForAllStates() == second.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot perform logical 'and' on check results of incompatible type."); - ExplicitQualitativeCheckResult const& secondCheckResult = static_cast(second); + ExplicitQualitativeCheckResult const& secondCheckResult = static_cast const&>(second); if (first.isResultForAllStates()) { if (logicalAnd) { boost::get(first.truthValues) &= boost::get(secondCheckResult.truthValues); @@ -78,17 +92,20 @@ void ExplicitQualitativeCheckResult::performLogicalOperation(ExplicitQualitative } } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator&=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, true); return *this; } -QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { +template +QualitativeCheckResult& ExplicitQualitativeCheckResult::operator|=(QualitativeCheckResult const& other) { performLogicalOperation(*this, other, false); return *this; } -bool ExplicitQualitativeCheckResult::existsTrue() const { +template +bool ExplicitQualitativeCheckResult::existsTrue() const { if (this->isResultForAllStates()) { return !boost::get(truthValues).empty(); } else { @@ -100,7 +117,9 @@ bool ExplicitQualitativeCheckResult::existsTrue() const { return false; } } -bool ExplicitQualitativeCheckResult::forallTrue() const { + +template +bool ExplicitQualitativeCheckResult::forallTrue() const { if (this->isResultForAllStates()) { return boost::get(truthValues).full(); } else { @@ -113,7 +132,8 @@ bool ExplicitQualitativeCheckResult::forallTrue() const { } } -uint64_t ExplicitQualitativeCheckResult::count() const { +template +uint64_t ExplicitQualitativeCheckResult::count() const { if (this->isResultForAllStates()) { return boost::get(truthValues).getNumberOfSetBits(); } else { @@ -127,7 +147,8 @@ uint64_t ExplicitQualitativeCheckResult::count() const { } } -bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { +template +bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_type state) const { if (this->isResultForAllStates()) { return boost::get(truthValues).get(state); } else { @@ -138,15 +159,18 @@ bool ExplicitQualitativeCheckResult::operator[](storm::storage::sparse::state_ty } } -ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { +template +typename ExplicitQualitativeCheckResult::vector_type const& ExplicitQualitativeCheckResult::getTruthValuesVector() const { return boost::get(truthValues); } -ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { +template +typename ExplicitQualitativeCheckResult::map_type const& ExplicitQualitativeCheckResult::getTruthValuesMap() const { return boost::get(truthValues); } -void ExplicitQualitativeCheckResult::complement() { +template +void ExplicitQualitativeCheckResult::complement() { if (this->isResultForAllStates()) { boost::get(truthValues).complement(); } else { @@ -156,19 +180,23 @@ void ExplicitQualitativeCheckResult::complement() { } } -bool ExplicitQualitativeCheckResult::isExplicit() const { +template +bool ExplicitQualitativeCheckResult::isExplicit() const { return true; } -bool ExplicitQualitativeCheckResult::isResultForAllStates() const { +template +bool ExplicitQualitativeCheckResult::isResultForAllStates() const { return truthValues.which() == 0; } -bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { +template +bool ExplicitQualitativeCheckResult::isExplicitQualitativeCheckResult() const { return true; } -std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { +template +std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) const { if (this->isResultForAllStates()) { vector_type const& vector = boost::get(truthValues); bool allTrue = vector.full(); @@ -211,11 +239,12 @@ std::ostream& ExplicitQualitativeCheckResult::writeToStream(std::ostream& out) c return out; } -void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { +template +void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult const& filter) { STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { @@ -259,9 +288,10 @@ void insertJsonEntry(storm::json& json, uint64_t const& id, bo json.push_back(std::move(entry)); } +template template -storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, - std::optional const& stateLabels) const { +storm::json ExplicitQualitativeCheckResult::toJson(std::optional const& stateValuations, + std::optional const& stateLabels) const { storm::json result; if (this->isResultForAllStates()) { vector_type const& valuesAsVector = boost::get(truthValues); @@ -277,10 +307,33 @@ storm::json ExplicitQualitativeCheckResult::toJson(std::option return result; } -template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, - std::optional const&) const; -template storm::json ExplicitQualitativeCheckResult::toJson( +// Explicit template instantiations +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; + +#ifdef STORM_HAVE_CARL +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( + std::optional const&, std::optional const&) const; + +template class ExplicitQualitativeCheckResult; +template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, + std::optional const&) const; +template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; +#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 8e13acbef7..9e67d1b277 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -9,12 +9,15 @@ #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" #include "storm/storage/BitVector.h" +#include "storm/storage/Scheduler.h" #include "storm/storage/sparse/StateType.h" #include "storm/storage/sparse/StateValuations.h" namespace storm { namespace modelchecker { + +template class ExplicitQualitativeCheckResult : public QualitativeCheckResult { public: typedef storm::storage::BitVector vector_type; @@ -69,6 +72,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { // The values of the quantitative check result. boost::variant truthValues; + + // An optional scheduler that accompanies the values. + boost::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 3464ee9381..278ef000b4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -61,7 +61,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boos } template -ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { +ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(ExplicitQualitativeCheckResult const& other) { if (other.isResultForAllStates()) { storm::storage::BitVector const& bvValues = other.getTruthValuesVector(); @@ -73,7 +73,7 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(Expl values = newVector; } else { - ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); + typename ExplicitQualitativeCheckResult::map_type const& bitMap = other.getTruthValuesMap(); map_type newMap; for (auto const& e : bitMap) { @@ -109,8 +109,8 @@ void ExplicitQuantitativeCheckResult::filter(QualitativeCheckResult c STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); if (this->isResultForAllStates()) { map_type newMap; @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); } } diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index e9c9ac487d..125752ca14 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -16,6 +16,7 @@ namespace storm { namespace modelchecker { // Forward declaration +template class ExplicitQualitativeCheckResult; template @@ -39,7 +40,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& other); virtual ~ExplicitQuantitativeCheckResult() = default; diff --git a/src/storm/modelchecker/results/LexicographicCheckResult.cpp b/src/storm/modelchecker/results/LexicographicCheckResult.cpp index 027f21f3ef..0206554088 100644 --- a/src/storm/modelchecker/results/LexicographicCheckResult.cpp +++ b/src/storm/modelchecker/results/LexicographicCheckResult.cpp @@ -43,8 +43,8 @@ void LexicographicCheckResult::filter(QualitativeCheckResult const& f STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter explicit check result with non-explicit filter."); STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter."); - ExplicitQualitativeCheckResult const& explicitFilter = filter.asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); + ExplicitQualitativeCheckResult const& explicitFilter = filter.template asExplicitQualitativeCheckResult(); + typename ExplicitQualitativeCheckResult::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector(); STORM_LOG_THROW(filterTruthValues.getNumberOfSetBits() == 1 && filterTruthValues.get(state), storm::exceptions::InvalidOperationException, "The check result fails to contain some results referred to by the filter."); diff --git a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp index 4828c13ef7..2f3206ac29 100644 --- a/src/storm/storage/bisimulation/BisimulationDecomposition.cpp +++ b/src/storm/storage/bisimulation/BisimulationDecomposition.cpp @@ -160,8 +160,8 @@ void BisimulationDecomposition::Options::checkAndSetMe storm::modelchecker::SparsePropositionalModelChecker checker(model); std::unique_ptr phiStatesCheckResult = checker.check(*leftSubformula); std::unique_ptr psiStatesCheckResult = checker.check(*rightSubformula); - phiStates = phiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); - psiStates = psiStatesCheckResult->asExplicitQualitativeCheckResult().getTruthValuesVector(); + phiStates = phiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = psiStatesCheckResult->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { optimalityType = boost::none; } diff --git a/src/storm/transformer/MemoryIncorporation.cpp b/src/storm/transformer/MemoryIncorporation.cpp index a0d894e6a3..14554ec711 100644 --- a/src/storm/transformer/MemoryIncorporation.cpp +++ b/src/storm/transformer/MemoryIncorporation.cpp @@ -27,7 +27,8 @@ storm::storage::MemoryStructure getGoalMemory(SparseModelType const& model, stor "The subformula " << propositionalGoalStateFormula << " should be propositional."); storm::modelchecker::SparsePropositionalModelChecker mc(model); - storm::storage::BitVector goalStates = mc.check(propositionalGoalStateFormula)->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(propositionalGoalStateFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied for all initial states. In such a case the trivial memory structure suffices. if (model.getInitialStates().isSubsetOf(goalStates)) { diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp index ceab40c2fe..4abd1731d5 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp @@ -52,7 +52,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -100,7 +100,7 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -149,7 +149,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -202,7 +202,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -256,7 +256,7 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp index 0c865a12ea..cf556ea3a0 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp @@ -144,7 +144,7 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -191,7 +191,7 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -268,7 +268,7 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -359,7 +359,7 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -412,7 +412,7 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp index b3c587afd2..46ab3d299b 100644 --- a/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/MilpPermissiveSchedulerTest.cpp @@ -55,7 +55,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -63,7 +63,7 @@ TEST(MilpPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); } diff --git a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp index 84594a1389..99aa4fa1b8 100644 --- a/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp +++ b/src/test/storm-permissive/analysis/SmtPermissiveSchedulerTest.cpp @@ -49,7 +49,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker0(*mdp); std::unique_ptr result0 = checker0.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult0 = result0->template asExplicitQualitativeCheckResult(); ASSERT_FALSE(qualitativeResult0[0]); @@ -57,7 +57,7 @@ TEST(SmtPermissiveSchedulerTest, DieSelection) { storm::modelchecker::SparseMdpPrctlModelChecker> checker1(submdp); std::unique_ptr result1 = checker1.check(env, formula02b); - storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->asExplicitQualitativeCheckResult(); + storm::modelchecker::ExplicitQualitativeCheckResult& qualitativeResult1 = result1->template asExplicitQualitativeCheckResult(); EXPECT_TRUE(qualitativeResult1[0]); diff --git a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp index e546e33be6..2692e8c546 100644 --- a/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/CtmcCslModelCheckerTest.cpp @@ -318,7 +318,7 @@ class CtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp index c7273dd2a4..36e162ab5b 100644 --- a/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/LraCtmcCslModelCheckerTest.cpp @@ -381,7 +381,7 @@ class LraCtmcCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp index 4010abee25..3a398d1b1e 100644 --- a/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/csl/MarkovAutomatonCslModelCheckerTest.cpp @@ -245,7 +245,7 @@ class MarkovAutomatonCslModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp index 755a60f403..42fd7aa01e 100644 --- a/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/MultiObjectiveSchedRestModelCheckerTest.cpp @@ -274,13 +274,13 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } ++formulaIndex; { @@ -293,7 +293,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, steps) { { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } @@ -359,7 +359,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } ++formulaIndex; @@ -371,7 +371,7 @@ TYPED_TEST(MultiObjectiveSchedRestModelCheckerTest, mecs) { } else { auto result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[formulaIndex]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[*mdp->getInitialStates().begin()]); } } } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp index 94df68f83b..074797ec94 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaCbMultiObjectiveModelCheckerTest.cpp @@ -43,9 +43,9 @@ TEST_F(SparseMaCbMultiObjectiveModelCheckerTest, server) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } diff --git a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp index 74a47f3f6a..f4a19f9597 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMaPcaaMultiObjectiveModelCheckerTest.cpp @@ -172,12 +172,12 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_achievability_3Obj std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) { @@ -210,7 +210,7 @@ TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_quantitative_3Obj) std::unique_ptr result2 = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *ma, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result2->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result2->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result2->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMaPcaaMultiObjectiveModelCheckerTest, jobscheduler_pareto_2Obj) { diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp index baa4726654..16250a581f 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpCbMultiObjectiveModelCheckerTest.cpp @@ -43,11 +43,11 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { @@ -69,7 +69,7 @@ TEST_F(SparseMdpCbMultiObjectiveModelCheckerTest, zeroconf) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } /* This test takes a little bit too long ... @@ -88,6 +88,6 @@ formulas)->as>(); uint_fast64_ std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(*mdp, formulas[0]->asMultiObjectiveFormula()) ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } */ diff --git a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp index d08c62033d..8a40aa4161 100644 --- a/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/multiobjective/SparseMdpPcaaMultiObjectiveModelCheckerTest.cpp @@ -228,11 +228,11 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, consensus) { result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[1]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[2]->asMultiObjectiveFormula()); ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); - EXPECT_FALSE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_FALSE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, zeroconf) { @@ -304,7 +304,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, tiny_rewards_negative) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { @@ -328,7 +328,7 @@ TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, scheduler) { std::unique_ptr result = storm::modelchecker::multiobjective::performMultiObjectiveModelChecking(env, *mdp, formulas[0]->asMultiObjectiveFormula()); - EXPECT_TRUE(result->asExplicitQualitativeCheckResult()[initState]); + EXPECT_TRUE(result->template asExplicitQualitativeCheckResult()[initState]); } TEST(SparseMdpPcaaMultiObjectiveModelCheckerTest, dpm) { diff --git a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp index 5083138f3b..a5a8fe0e26 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/DtmcPrctlModelCheckerTest.cpp @@ -644,7 +644,7 @@ class DtmcPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp index 8c01df8684..26d4b4622e 100644 --- a/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/MdpPrctlModelCheckerTest.cpp @@ -670,7 +670,7 @@ class MdpPrctlModelCheckerTest : public ::testing::Test { std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) const { if (isSparseModel()) { - return std::make_unique(model->template as()->getInitialStates()); + return std::make_unique>(model->template as()->getInitialStates()); } else { return std::make_unique>( model->template as()->getReachableStates(), model->template as()->getInitialStates()); diff --git a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp index 635b352b69..c2204c444d 100644 --- a/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/QuantileQueryTest.cpp @@ -164,7 +164,7 @@ class QuantileQueryTest : public ::testing::Test { std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) const { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } }; diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 27a9254a16..3d509f2fbc 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -17,11 +17,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, From ee9f051ecc3d6094efe8280296ed56756c45c1e5 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:44:13 +0100 Subject: [PATCH 02/27] Remember scheduler from quantitative scheduler when applying bounds --- resources/3rdparty/l3pp | 1 + .../ExplicitQualitativeCheckResult.cpp | 31 +++++++++++++++++-- .../results/ExplicitQualitativeCheckResult.h | 11 +++++-- .../ExplicitQuantitativeCheckResult.cpp | 4 +-- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 160000 resources/3rdparty/l3pp diff --git a/resources/3rdparty/l3pp b/resources/3rdparty/l3pp new file mode 160000 index 0000000000..e4f8d7fe6c --- /dev/null +++ b/resources/3rdparty/l3pp @@ -0,0 +1 @@ +Subproject commit e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 9404a7c355..f39ac58a74 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -41,13 +41,16 @@ ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm: } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues) : truthValues(truthValues) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler) + : truthValues(truthValues), scheduler(scheduler) { // Intentionally left empty. } template -ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues) - : truthValues(std::move(truthValues)) { +ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler) + : truthValues(std::move(truthValues)), scheduler(scheduler) { // Intentionally left empty. } @@ -270,6 +273,28 @@ void ExplicitQualitativeCheckResult::filter(QualitativeCheckResult co } } +template +bool ExplicitQualitativeCheckResult::hasScheduler() const { + return static_cast(scheduler); +} + +template +void ExplicitQualitativeCheckResult::setScheduler(std::unique_ptr>&& scheduler) { + this->scheduler = std::move(scheduler); +} + +template +storm::storage::Scheduler const& ExplicitQualitativeCheckResult::getScheduler() const { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + +template +storm::storage::Scheduler& ExplicitQualitativeCheckResult::getScheduler() { + STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); + return *scheduler.get(); +} + template void insertJsonEntry(storm::json& json, uint64_t const& id, bool value, std::optional const& stateValuations = std::nullopt, diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 9e67d1b277..14d781ef86 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -30,8 +30,10 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { ExplicitQualitativeCheckResult(storm::storage::sparse::state_type state, bool value); ExplicitQualitativeCheckResult(vector_type const& truthValues); ExplicitQualitativeCheckResult(vector_type&& truthValues); - ExplicitQualitativeCheckResult(boost::variant const& truthValues); - ExplicitQualitativeCheckResult(boost::variant&& truthValues); + ExplicitQualitativeCheckResult(boost::variant const& truthValues, + boost::optional>> scheduler = boost::none); + ExplicitQualitativeCheckResult(boost::variant&& truthValues, + boost::optional>> scheduler = boost::none); ExplicitQualitativeCheckResult(ExplicitQualitativeCheckResult const& other) = default; ExplicitQualitativeCheckResult& operator=(ExplicitQualitativeCheckResult const& other) = default; @@ -63,6 +65,11 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { virtual void filter(QualitativeCheckResult const& filter) override; + virtual bool hasScheduler() const override; + void setScheduler(std::unique_ptr>&& scheduler); + storm::storage::Scheduler const& getScheduler() const; + storm::storage::Scheduler& getScheduler(); + template storm::json toJson(std::optional const& stateValuations = std::nullopt, std::optional const& stateLabels = std::nullopt) const; diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index 278ef000b4..f9dc8f2bef 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -369,7 +369,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } else { map_type const& valuesAsMap = boost::get(values); std::map result; @@ -395,7 +395,7 @@ std::unique_ptr ExplicitQuantitativeCheckResult::compare } break; } - return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result))); + return std::unique_ptr(new ExplicitQualitativeCheckResult(std::move(result), std::move(scheduler))); } } From 1868e4421eb6c70c37c5f8a7b030ffa4271c91f9 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 26 Nov 2025 15:49:56 +0100 Subject: [PATCH 03/27] Export schedulers for qualitative models in the cli --- src/storm-cli-utilities/model-handling.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 6f7eaee4b2..62dc3a4279 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -1348,6 +1348,13 @@ void verifyModel(std::shared_ptr> const& auto const& paretoRes = result->template asExplicitParetoCurveCheckResult(); storm::api::exportParetoScheduler(sparseModel, paretoRes.getPoints(), paretoRes.getSchedulers(), schedulerExportPath.string()); } + } else if (result->isExplicitQualitativeCheckResult()) { + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export for interval models is not supported."); + } else { + storm::api::exportScheduler(sparseModel, result->template asExplicitQualitativeCheckResult().getScheduler(), + schedulerExportPath.string()); + } } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Scheduler export not supported for this value type."); } From 0da7fd862ebf3fc3938d951481f0b5f35e022d1a Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:21:40 +0100 Subject: [PATCH 04/27] Fix test --- .../transformer/IntervalEndComponentPreserverCheckTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp index bdc748e6e0..6fd2a97347 100644 --- a/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp +++ b/src/test/storm-pars/transformer/IntervalEndComponentPreserverCheckTest.cpp @@ -53,7 +53,7 @@ void testModelInterval(std::string programFile, std::string formulaAsString, std storm::modelchecker::SparsePropositionalModelChecker> propositionalChecker(*dtmc); storm::storage::BitVector psiStates = propositionalChecker.check(checkTask.getFormula().asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()) - ->asExplicitQualitativeCheckResult() + ->template asExplicitQualitativeCheckResult() .getTruthValuesVector(); std::vector target(model->getNumberOfStates(), storm::utility::zero()); From 798d3e4f0e49c64cc3560e2429e38ff00ddfac4f Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:25:11 +0100 Subject: [PATCH 05/27] Format --- src/storm-cli-utilities/model-handling.h | 18 +++---- ...SparseDtmcParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseMdpParameterLiftingModelChecker.cpp | 25 ++++++---- .../SparseParametricDtmcSimplifier.cpp | 15 +++--- .../SparseParametricMdpSimplifier.cpp | 15 +++--- .../SparseMultiObjectivePreprocessor.cpp | 48 ++++++++++++------- .../helper/rewardbounded/ProductModel.cpp | 18 ++++--- .../monotonicity/MonotonicityCheckerTest.cpp | 15 ++++-- .../region/monotonicity/OrderExtenderTest.cpp | 15 ++++-- 9 files changed, 121 insertions(+), 73 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 62dc3a4279..1e81947d93 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -903,14 +903,14 @@ inline void printCounterexample(std::shared_ptr -requires(!std::derived_from>) inline void generateCounterexamples(std::shared_ptr const&, - SymbolicInput const&) { + requires(!std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const&, SymbolicInput const&) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Counterexample generation is not supported for this data-type."); } template -requires(std::derived_from>) inline void generateCounterexamples(std::shared_ptr const& sparseModel, - SymbolicInput const& input) { + requires(std::derived_from>) +inline void generateCounterexamples(std::shared_ptr const& sparseModel, SymbolicInput const& input) { using ValueType = typename ModelType::ValueType; for (auto& rewModel : sparseModel->getRewardModels()) { @@ -966,8 +966,8 @@ requires(std::derived_from>) inl } template -requires(!storm::IsIntervalType) void printFilteredResult(std::unique_ptr const& result, - storm::modelchecker::FilterType ft) { + requires(!storm::IsIntervalType) +void printFilteredResult(std::unique_ptr const& result, storm::modelchecker::FilterType ft) { if (result->isQuantitative()) { if (ft == storm::modelchecker::FilterType::VALUES) { STORM_PRINT(*result); @@ -1034,9 +1034,9 @@ inline void printModelCheckingProperty(storm::jani::Property const& property) { } template -requires(!storm::IsIntervalType) void printResult(std::unique_ptr const& result, - storm::logic::Formula const& filterStatesFormula, - storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { + requires(!storm::IsIntervalType) +void printResult(std::unique_ptr const& result, storm::logic::Formula const& filterStatesFormula, + storm::modelchecker::FilterType const& filterType, storm::utility::Stopwatch* watch = nullptr) { if (result) { std::stringstream ss; ss << "'" << filterStatesFormula << "'"; diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 150f271501..002151ac7c 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -150,10 +150,12 @@ void SparseDtmcParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound); @@ -192,10 +194,12 @@ void SparseDtmcParameterLiftingModelCheckertemplate asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -264,8 +268,9 @@ void SparseDtmcParameterLiftingModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = storm::utility::graph::performProb1( this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates); diff --git a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp index ff81f266b4..4294ad72b5 100644 --- a/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseMdpParameterLiftingModelChecker.cpp @@ -109,10 +109,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates maybeStates = storm::solver::minimize(checkTask.getOptimizationDirection()) @@ -152,10 +154,12 @@ void SparseMdpParameterLiftingModelChecker::speci STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) && propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector phiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = - std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates std::pair statesWithProbability01 = @@ -203,8 +207,9 @@ void SparseMdpParameterLiftingModelChecker::speci storm::modelchecker::SparsePropositionalModelChecker propositionalChecker(*this->parametricModel); STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported"); - storm::storage::BitVector targetStates = - std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // get the maybeStates storm::storage::BitVector infinityStates = diff --git a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp index ea66d7728e..2910fa4881 100644 --- a/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricDtmcSimplifier.cpp @@ -29,10 +29,12 @@ bool SparseParametricDtmcSimplifier::simplifyForUntilProbabilit STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->originalModel, phiStates, psiStates); // Only consider the maybestates that are reachable from one initial state without hopping over a target (i.e., prob1) state @@ -151,8 +153,9 @@ bool SparseParametricDtmcSimplifier::simplifyForReachabilityRew STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward targetStates = storm::utility::graph::performProb1(this->originalModel.getBackwardTransitions(), originalRewardModel.getStatesWithZeroReward(this->originalModel.getTransitionMatrix()), targetStates); diff --git a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp index 4026d9dcfb..ed9ac1efbe 100644 --- a/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp +++ b/src/storm-pars/transformer/SparseParametricMdpSimplifier.cpp @@ -34,10 +34,12 @@ bool SparseParametricMdpSimplifier::simplifyForUntilProbabiliti STORM_LOG_DEBUG("Can not simplify when Until-formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector phiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); - storm::storage::BitVector psiStates = std::move( - propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector phiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); + storm::storage::BitVector psiStates = std::move(propositionalChecker.check(formula.getSubformula().asUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); std::pair statesWithProbability01 = minimizing ? storm::utility::graph::performProb01Min(this->originalModel, phiStates, psiStates) : storm::utility::graph::performProb01Max(this->originalModel, phiStates, psiStates); @@ -181,8 +183,9 @@ bool SparseParametricMdpSimplifier::simplifyForReachabilityRewa STORM_LOG_DEBUG("Can not simplify when reachability reward formula has non-propositional subformula(s). Formula: " << formula); return false; } - storm::storage::BitVector targetStates = std::move( - propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + storm::storage::BitVector targetStates = std::move(propositionalChecker.check(formula.getSubformula().asEventuallyFormula().getSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); // The set of target states can be extended by the states that reach target with probability 1 without collecting any reward // TODO for the call of Prob1E we could restrict the analysis to actions with zero reward instead of states with zero reward targetStates = diff --git a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp index 1a51f2cafc..91dc7be1b2 100644 --- a/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp +++ b/src/storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessor.cpp @@ -128,8 +128,10 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s auto const& pathFormula = opFormula->asOperatorFormula().getSubformula(); if (opFormula->isProbabilityOperatorFormula()) { if (pathFormula.isUntilFormula()) { - auto lhs = mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = + mc.check(pathFormula.asUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto rhs = + mc.check(pathFormula.asUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs | rhs); } else if (pathFormula.isBoundedUntilFormula()) { @@ -138,10 +140,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector absorbingStatesForSubSubformula; for (uint64_t i = 0; i < pathFormula.asBoundedUntilFormula().getDimension(); ++i) { auto subPathFormula = pathFormula.asBoundedUntilFormula().restrictToDimension(i); - auto lhs = - mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = - mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i))->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula(i)) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound(i)) { absorbingStatesForSubSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -151,8 +155,12 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s absorbingStatesForSubformula &= absorbingStatesForSubSubformula; } } else { - auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto lhs = mc.check(pathFormula.asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); + auto rhs = mc.check(pathFormula.asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, lhs, rhs); if (pathFormula.asBoundedUntilFormula().hasLowerBound()) { absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, ~lhs); @@ -161,12 +169,14 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } } else if (pathFormula.isGloballyFormula()) { - auto phi = mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asGloballyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); auto notPhi = ~phi; absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, phi, notPhi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, notPhi); } else if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, ~phi, phi); absorbingStatesForSubformula |= getOnlyReachableViaPhi(*model, phi); } else { @@ -181,7 +191,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s storm::storage::BitVector statesWithoutReward = rewardModel.get().getStatesWithZeroReward(model->getTransitionMatrix()); // Make states that can not reach a state with non-zero reward absorbing absorbingStatesForSubformula = storm::utility::graph::performProb0A(backwardTransitions, statesWithoutReward, ~statesWithoutReward); - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Make states that reach phi with prob 1 while only visiting states with reward 0 absorbing absorbingStatesForSubformula |= storm::utility::graph::performProb1A( model->getTransitionMatrix(), model->getTransitionMatrix().getRowGroupIndices(), backwardTransitions, statesWithoutReward, phi); @@ -210,7 +221,8 @@ void SparseMultiObjectivePreprocessor::removeIrrelevantStates(s } } else if (opFormula->isTimeOperatorFormula()) { if (pathFormula.isEventuallyFormula()) { - auto phi = mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + auto phi = + mc.check(pathFormula.asEventuallyFormula().getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); absorbingStatesForSubformula = getOnlyReachableViaPhi(*model, phi); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The subformula of " << pathFormula << " is not supported."); @@ -432,7 +444,8 @@ void SparseMultiObjectivePreprocessor::preprocessLongRunAverage // Create and add the new reward model that only gives one reward for goal states storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); std::vector lraRewards(data.model->getNumberOfStates(), storm::utility::zero()); storm::utility::vector::setVectorValues(lraRewards, subFormulaResult, storm::utility::one()); data.model->addRewardModel(rewardModelName, typename SparseModelType::RewardModelType(std::move(lraRewards))); @@ -445,7 +458,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Try to transform the formula to expected total (or cumulative) rewards storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector rightSubformulaResult = mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector rightSubformulaResult = + mc.check(formula.getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Check if the formula is already satisfied in the initial state because then the transformation to expected rewards will fail. // TODO: Handle this case more properly STORM_LOG_THROW((data.model->getInitialStates() & rightSubformulaResult).empty(), storm::exceptions::NotImplementedException, @@ -455,7 +469,8 @@ void SparseMultiObjectivePreprocessor::preprocessUntilFormula(s // Whenever a state that violates the left subformula or satisfies the right subformula is reached, the objective is 'decided', i.e., no more reward should // be collected from there - storm::storage::BitVector notLeftOrRight = mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector notLeftOrRight = + mc.check(formula.getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); notLeftOrRight.complement(); notLeftOrRight |= rightSubformulaResult; @@ -542,7 +557,8 @@ void SparseMultiObjectivePreprocessor::preprocessEventuallyForm // Analyze the subformula storm::modelchecker::SparsePropositionalModelChecker mc(*data.model); - storm::storage::BitVector subFormulaResult = mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector subFormulaResult = + mc.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the states that are reachable from a goal state storm::storage::BitVector allStates(data.model->getNumberOfStates(), true), noStates(data.model->getNumberOfStates(), false); diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp index 02b9e2f177..ccc196db4e 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/ProductModel.cpp @@ -132,9 +132,12 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( for (auto dim : objectiveDimensions[objIndex]) { auto const& dimension = dimensions[dim]; STORM_LOG_ASSERT(dimension.formula->isBoundedUntilFormula(), "Unexpected Formula type"); - constraintStates &= - (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector() | - mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector()); + constraintStates &= (mc.check(dimension.formula->asBoundedUntilFormula().getLeftSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector() | + mc.check(dimension.formula->asBoundedUntilFormula().getRightSubformula()) + ->template asExplicitQualitativeCheckResult() + .getTruthValuesVector()); } // Build the transitions between the memory states @@ -155,7 +158,8 @@ storm::storage::MemoryStructure ProductModel::computeMemoryStructure( storm::logic::BinaryBooleanStateFormula::OperatorType::And, transitionFormula, subObjFormula); } - storm::storage::BitVector transitionStates = mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector transitionStates = + mc.check(*transitionFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); if (memStatePrimeBV.empty()) { transitionStates |= ~constraintStates; } else { @@ -426,9 +430,11 @@ std::vector> ProductModel::computeObjectiveRew } } - storm::storage::BitVector relevantStates = mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector relevantStates = + mc.check(*relevantStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector relevantChoices = getProduct().getTransitionMatrix().getRowFilter(relevantStates); - storm::storage::BitVector goalStates = mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector goalStates = + mc.check(*goalStatesFormula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); for (auto choice : relevantChoices) { objRew[choice] += getProduct().getTransitionMatrix().getConstrainedRowSum(choice, goalStates); } diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp index 4abd1731d5..9a78b6f47c 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/MonotonicityCheckerTest.cpp @@ -52,7 +52,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_larger_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -100,7 +101,8 @@ TEST_F(MonotonicityCheckerTest, Simple1_small_region) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -149,7 +151,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy1) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -202,7 +205,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy2) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -256,7 +260,8 @@ TEST_F(MonotonicityCheckerTest, Casestudy3) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); diff --git a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp index cf556ea3a0..a50109532e 100644 --- a/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp +++ b/src/test/storm-pars/modelchecker/region/monotonicity/OrderExtenderTest.cpp @@ -144,7 +144,8 @@ TEST_F(OrderExtenderTest, Brp_with_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -191,7 +192,8 @@ TEST_F(OrderExtenderTest, Brp_without_bisimulation_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -268,7 +270,8 @@ TEST_F(OrderExtenderTest, simple1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -359,7 +362,8 @@ TEST_F(OrderExtenderTest, casestudy1_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); @@ -412,7 +416,8 @@ TEST_F(OrderExtenderTest, casestudy2_on_matrix) { storm::storage::BitVector psiStates; phiStates = storm::storage::BitVector(model->getTransitionMatrix().getRowCount(), true); storm::logic::EventuallyFormula formula = formulas[0]->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula(); - psiStates = propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = + propositionalChecker.check(formula.getSubformula())->template asExplicitQualitativeCheckResult().getTruthValuesVector(); // Get the maybeStates std::pair statesWithProbability01 = storm::utility::graph::performProb01(model->getBackwardTransitions(), phiStates, psiStates); From 73e73d8d5552d293002109fe25e24c214aaabb3d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 15:34:29 +0100 Subject: [PATCH 06/27] remove weird git thing --- resources/3rdparty/l3pp | 1 - 1 file changed, 1 deletion(-) delete mode 160000 resources/3rdparty/l3pp diff --git a/resources/3rdparty/l3pp b/resources/3rdparty/l3pp deleted file mode 160000 index e4f8d7fe6c..0000000000 --- a/resources/3rdparty/l3pp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 From f3f81e1aff674933e888b528026e6e0a5ae84426 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 3 Dec 2025 17:00:00 +0100 Subject: [PATCH 07/27] fix one ValueType --- .../SparseDerivativeInstantiationModelChecker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp index ce1ae41f60..8f57bb92f7 100644 --- a/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp +++ b/src/storm-pars/derivative/SparseDerivativeInstantiationModelChecker.cpp @@ -143,20 +143,20 @@ void SparseDerivativeInstantiationModelChecker::spec if (this->currentFormula->isRewardOperatorFormula()) { auto subformula = modelchecker::CheckTask( this->currentFormula->asRewardOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } else { if (this->currentFormula->asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { auto rightSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getRightSubformula()); auto leftSubformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asUntilFormula().getLeftSubformula()); - target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); - avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(rightSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + avoid = propositionalChecker.check(leftSubformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); avoid.complement(); } else { auto subformula = modelchecker::CheckTask( this->currentFormula->asProbabilityOperatorFormula().getSubformula().asEventuallyFormula().getSubformula()); - target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + target = propositionalChecker.check(subformula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); } } initialStateModel = model.getStates("init").getNextSetIndex(0); From 02350c239dc7e068819fa726c2e7279901011996 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 4 Mar 2026 16:59:58 +0100 Subject: [PATCH 08/27] Refactor ExplicitQualitativeCheckResult constructor to use std::optional for scheduler parameter --- .../modelchecker/results/ExplicitQualitativeCheckResult.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 1ca56bc279..8707f463ed 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -42,14 +42,14 @@ ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(storm: template ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant const& truthValues, - boost::optional>> scheduler) + std::optional>> scheduler) : truthValues(truthValues), scheduler(scheduler) { // Intentionally left empty. } template ExplicitQualitativeCheckResult::ExplicitQualitativeCheckResult(boost::variant&& truthValues, - boost::optional>> scheduler) + std::optional>> scheduler) : truthValues(std::move(truthValues)), scheduler(scheduler) { // Intentionally left empty. } From a82759ae27667098653ddf58cb62d542d8016552 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 5 Mar 2026 15:25:30 +0100 Subject: [PATCH 09/27] fix some new location and swich to std::optional --- .../modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp | 6 +++--- .../modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp | 2 +- src/storm/modelchecker/results/CheckResult.cpp | 1 + .../results/ExplicitQualitativeCheckResult.cpp | 7 +++---- .../modelchecker/results/ExplicitQualitativeCheckResult.h | 6 +++--- .../results/ExplicitQuantitativeCheckResult.cpp | 8 ++++---- .../results/ExplicitQuantitativeCheckResult.h | 6 +++--- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 8 ++++---- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp index 3164eeee04..7324d97da1 100644 --- a/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp +++ b/src/storm/modelchecker/multiobjective/pcaa/SparsePcaaQuery.cpp @@ -227,7 +227,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie if (!optObjIndex.has_value()) { if (!overApproximation->contains(thresholds)) { // The thresholds are not achievable - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); } referencePoint = thresholds; } else { @@ -247,7 +247,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie auto optRes = overApproximation->intersection(thresholdPolytope)->optimize(optDirVector); if (!optRes.second) { // The thresholds are not achievable - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, false)); } referencePoint = thresholds; referencePoint[optObjIndex.value()] = @@ -275,7 +275,7 @@ SparsePcaaQuery::tryAnswerOrNextWeightsAchie return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialStateOfOriginalModel, resultForOriginalModel)); } else { - return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, true)); + return std::unique_ptr(new ExplicitQualitativeCheckResult(initialStateOfOriginalModel, true)); } } diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 8f8fd1f980..394fe5702c 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -325,7 +325,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityTimes( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 0bdd406f21..94c0ed9d26 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -1,6 +1,7 @@ #include "storm/modelchecker/results/CheckResult.h" #include "storm/adapters/RationalFunctionAdapter.h" +#include "storm/adapters/IntervalAdapter.h" #include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 8707f463ed..50b9a9e16c 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -1,3 +1,4 @@ +#include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" // Must come first. TODO: fix #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" @@ -286,13 +287,13 @@ void ExplicitQualitativeCheckResult::setScheduler(std::unique_ptr storm::storage::Scheduler const& ExplicitQualitativeCheckResult::getScheduler() const { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template storm::storage::Scheduler& ExplicitQualitativeCheckResult::getScheduler() { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template @@ -337,7 +338,6 @@ template class ExplicitQualitativeCheckResult; template storm::json ExplicitQualitativeCheckResult::toJson(std::optional const&, std::optional const&) const; -#ifdef STORM_HAVE_CARL template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; @@ -358,7 +358,6 @@ template storm::json ExplicitQualitativeCheckResult::to std::optional const&) const; template storm::json ExplicitQualitativeCheckResult::toJson( std::optional const&, std::optional const&) const; -#endif } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 6825f4bce5..95db1271bb 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -30,9 +30,9 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { ExplicitQualitativeCheckResult(vector_type const& truthValues); ExplicitQualitativeCheckResult(vector_type&& truthValues); ExplicitQualitativeCheckResult(boost::variant const& truthValues, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQualitativeCheckResult(boost::variant&& truthValues, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQualitativeCheckResult(ExplicitQualitativeCheckResult const& other) = default; ExplicitQualitativeCheckResult& operator=(ExplicitQualitativeCheckResult const& other) = default; @@ -79,7 +79,7 @@ class ExplicitQualitativeCheckResult : public QualitativeCheckResult { boost::variant truthValues; // An optional scheduler that accompanies the values. - boost::optional>> scheduler; + std::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp index ec8222fe09..d775b924e4 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.cpp @@ -48,14 +48,14 @@ ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(vect template ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boost::variant const& values, - boost::optional>> scheduler) + std::optional>> scheduler) : values(values), scheduler(scheduler) { // Intentionally left empty. } template ExplicitQuantitativeCheckResult::ExplicitQuantitativeCheckResult(boost::variant&& values, - boost::optional>> scheduler) + std::optional>> scheduler) : values(std::move(values)), scheduler(scheduler) { // Intentionally left empty. } @@ -226,13 +226,13 @@ void ExplicitQuantitativeCheckResult::setScheduler(std::unique_ptr storm::storage::Scheduler const& ExplicitQuantitativeCheckResult::getScheduler() const { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template storm::storage::Scheduler& ExplicitQuantitativeCheckResult::getScheduler() { STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler."); - return *scheduler.get(); + return *scheduler.value(); } template diff --git a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h index 125752ca14..bf543cd180 100644 --- a/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQuantitativeCheckResult.h @@ -32,9 +32,9 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult const& values, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQuantitativeCheckResult(boost::variant&& values, - boost::optional>> scheduler = boost::none); + std::optional>> scheduler = {}); ExplicitQuantitativeCheckResult(ExplicitQuantitativeCheckResult const& other) = default; ExplicitQuantitativeCheckResult& operator=(ExplicitQuantitativeCheckResult const& other) = default; @@ -85,7 +85,7 @@ class ExplicitQuantitativeCheckResult : public QuantitativeCheckResult values; // An optional scheduler that accompanies the values. - boost::optional>> scheduler; + std::optional>> scheduler; }; } // namespace modelchecker } // namespace storm diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 1ee43344b7..07369bfbbc 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -16,11 +16,11 @@ std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } std::unique_ptr getInitialStateFilter(std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, @@ -138,7 +138,7 @@ void checkModelForQualitativeResult(std::string const& path, std::string const& ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); for (size_t i = 0; i < expectedResultVector[0].size(); i++) { - EXPECT_EQ(expectedResultVector[0].get(i), result->asExplicitQualitativeCheckResult()[i]); + EXPECT_EQ(expectedResultVector[0].get(i), result->template asExplicitQualitativeCheckResult()[i]); } auto task2 = storm::modelchecker::CheckTask(*formulas[1]); @@ -148,7 +148,7 @@ void checkModelForQualitativeResult(std::string const& path, std::string const& ASSERT_TRUE(result->isExplicitQualitativeCheckResult()); for (size_t i = 0; i < expectedResultVector[1].size(); i++) { - EXPECT_EQ(expectedResultVector[1].get(i), result->asExplicitQualitativeCheckResult()[i]); + EXPECT_EQ(expectedResultVector[1].get(i), result->template asExplicitQualitativeCheckResult()[i]); } } From f07309c5c00dc83790bb0d84d57f3262ef7bae68 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 5 Mar 2026 15:29:43 +0100 Subject: [PATCH 10/27] format --- src/storm/modelchecker/results/CheckResult.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/modelchecker/results/CheckResult.cpp b/src/storm/modelchecker/results/CheckResult.cpp index 94c0ed9d26..f6c6827c0b 100644 --- a/src/storm/modelchecker/results/CheckResult.cpp +++ b/src/storm/modelchecker/results/CheckResult.cpp @@ -1,7 +1,7 @@ #include "storm/modelchecker/results/CheckResult.h" -#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/RationalFunctionAdapter.h" #include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" From 4be794c5a5964b10c2271b67c16a845cabd251a7 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 10:46:55 +0100 Subject: [PATCH 11/27] Update ExplicitQualitativeCheckResult usage to use SolutionType and include IntervalForward in tests --- src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp | 4 ++-- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 394fe5702c..39c60fea41 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -153,8 +153,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 07369bfbbc..2cb9f531a3 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -1,4 +1,5 @@ #include "storm-config.h" +#include "storm/adapters/IntervalForward.h" #include "test/storm_gtest.h" #include "storm-parsers/api/model_descriptions.h" From 7e57f56b2dee2a778574db5b28ed31543d77c486 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 6 Mar 2026 11:20:47 +0100 Subject: [PATCH 12/27] Fix other qualitative check result value types --- .../prctl/SparseDtmcPrctlModelChecker.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 39c60fea41..e54a69b4ef 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -108,8 +108,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c "Formula needs to have discrete upper step bound."); std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicStepBoundedHorizonHelper helper; std::vector numericResult = helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -129,7 +129,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities( env, this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); @@ -171,7 +171,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities( env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), @@ -192,7 +192,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; auto apSets = helper.computeApSets(pathFormula.getAPMapping(), formulaChecker); std::vector numericResult = helper.computeDAProductProbabilities(env, *pathFormula.readAutomaton(), apSets); @@ -213,7 +213,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto formulaChecker = [&](storm::logic::Formula const& formula) { - return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); + return this->check(env, formula)->template asExplicitQualitativeCheckResult().getTruthValuesVector(); }; std::vector numericResult = helper.computeLTLProbabilities(env, pathFormula, formulaChecker); @@ -308,7 +308,7 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c "Computing rewards on uncertain model requires graph-preservation."); } std::unique_ptr subResultPointer = this->check(env, eventuallyFormula.getSubformula()); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards( @@ -380,13 +380,13 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c } else { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(env, stateFormula); - ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); storm::modelchecker::helper::SparseDeterministicInfiniteHorizonHelper helper(this->getModel().getTransitionMatrix()); storm::modelchecker::helper::setInformationFromCheckTaskDeterministic(helper, checkTask, this->getModel()); auto values = helper.computeLongRunAverageProbabilities(env, subResult.getTruthValuesVector()); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(values))); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(values))); } } @@ -418,8 +418,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asEventuallyFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities( @@ -443,8 +443,8 @@ std::unique_ptr SparseDtmcPrctlModelChecker::c std::unique_ptr leftResultPointer = this->check(env, conditionalFormula.getSubformula().asReachabilityRewardFormula().getSubformula()); std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalRewards( From c7268369c32a88e55a4e5fe81742e044c64e23a8 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 10 Mar 2026 13:16:33 +0100 Subject: [PATCH 13/27] Add exact Intervals and bounded model checking of intervals --- src/storm-cli-utilities/model-handling.h | 80 +++++++--- src/storm-parsers/parser/ValueParser.cpp | 48 ++++++ src/storm/adapters/IntervalForward.h | 8 + src/storm/io/DirectEncodingExporter.cpp | 5 + .../modelchecker/AbstractModelChecker.cpp | 5 + src/storm/modelchecker/AbstractModelChecker.h | 20 ++- ...ndeterministicStepBoundedHorizonHelper.cpp | 65 +++++--- ...NondeterministicStepBoundedHorizonHelper.h | 12 +- .../hints/ExplicitModelCheckerHint.cpp | 1 + .../modelchecker/hints/ModelCheckerHint.cpp | 2 + .../prctl/SparseMdpPrctlModelChecker.cpp | 104 ++++++------- .../prctl/SparseMdpPrctlModelChecker.h | 2 +- .../SparseMdpEndComponentInformation.cpp | 10 +- .../prctl/helper/SparseMdpPrctlHelper.cpp | 103 +++++++++++-- .../prctl/helper/SparseMdpPrctlHelper.h | 6 + .../MultiDimensionalRewardUnfolding.cpp | 2 + .../SparsePropositionalModelChecker.cpp | 8 + .../SparsePropositionalModelChecker.h | 20 ++- .../ExplicitQualitativeCheckResult.cpp | 1 + src/storm/models/sparse/Ctmc.cpp | 2 + .../models/sparse/DeterministicModel.cpp | 2 + src/storm/models/sparse/Dtmc.cpp | 3 + src/storm/models/sparse/MarkovAutomaton.cpp | 2 + src/storm/models/sparse/Mdp.cpp | 2 + src/storm/models/sparse/Model.cpp | 4 +- .../models/sparse/NondeterministicModel.cpp | 4 +- src/storm/models/sparse/Pomdp.cpp | 2 + src/storm/models/sparse/Smg.cpp | 2 + .../models/sparse/StandardRewardModel.cpp | 42 +++++ .../models/sparse/StochasticTwoPlayerGame.cpp | 4 +- .../settings/modules/GeneralSettings.cpp | 6 + src/storm/settings/modules/GeneralSettings.h | 8 + .../IterativeMinMaxLinearEquationSolver.cpp | 34 ++-- src/storm/solver/LinearEquationSolver.cpp | 2 +- .../solver/MinMaxLinearEquationSolver.cpp | 10 +- src/storm/solver/SolveGoal.cpp | 1 + .../StandardMinMaxLinearEquationSolver.cpp | 1 + .../solver/helper/SchedulerTrackingHelper.cpp | 2 + .../solver/helper/ValueIterationHelper.cpp | 2 + .../solver/helper/ValueIterationOperator.cpp | 4 +- .../solver/helper/ValueIterationOperator.h | 32 +++- src/storm/solver/multiplier/Multiplier.cpp | 82 ++++++---- src/storm/solver/multiplier/Multiplier.h | 36 +++-- .../multiplier/ViOperatorMultiplier.cpp | 105 +++++++------ .../solver/multiplier/ViOperatorMultiplier.h | 17 +- src/storm/storage/Distribution.cpp | 5 + .../MaximalEndComponentDecomposition.cpp | 4 + src/storm/storage/Scheduler.cpp | 1 + src/storm/storage/SchedulerChoice.cpp | 2 + src/storm/storage/SparseMatrix.cpp | 25 ++- src/storm/storage/SparseMatrix.h | 7 + ...tronglyConnectedComponentDecomposition.cpp | 1 + .../MemoryStructureBuilder.cpp | 2 + .../SparseModelMemoryProduct.cpp | 2 + src/storm/transformer/AddUncertainty.cpp | 14 +- src/storm/transformer/AddUncertainty.h | 3 +- src/storm/transformer/SubsystemBuilder.cpp | 9 ++ src/storm/utility/ConstantsComparator.cpp | 1 + src/storm/utility/NumberTraits.h | 13 ++ src/storm/utility/builder.cpp | 6 + src/storm/utility/constants.cpp | 52 +++++++ src/storm/utility/graph.cpp | 145 ++++++++++++++++++ .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 50 +++++- 63 files changed, 992 insertions(+), 263 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index f28dc7faf2..2394c58bcc 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -154,7 +154,7 @@ struct ModelProcessingInformation { bool transformToJani; // Which data type is to be used for numbers ... - enum class ValueType { FinitePrecision, Exact, Parametric }; + enum class ValueType { FinitePrecision, Exact, Parametric, FinitePrecisionInterval, ExactInterval }; ValueType buildValueType; // ... during model building ValueType verificationValueType; // ... during model verification @@ -222,9 +222,17 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co if (generalSettings.isParametricSet()) { mpi.verificationValueType = ModelProcessingInformation::ValueType::Parametric; } else if (generalSettings.isExactSet()) { - mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; + if (generalSettings.isIntervalSet()) { + mpi.verificationValueType = ModelProcessingInformation::ValueType::ExactInterval; + } else { + mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; + } } else { - mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; + if (generalSettings.isIntervalSet()) { + mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecisionInterval; + } else { + mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; + } } auto originalVerificationValueType = mpi.verificationValueType; @@ -270,6 +278,12 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co case ModelProcessingInformation::ValueType::FinitePrecision: return storm::utility::canHandle( mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); + case ModelProcessingInformation::ValueType::FinitePrecisionInterval: + return storm::utility::canHandle( + mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); + case ModelProcessingInformation::ValueType::ExactInterval: + return storm::utility::canHandle( + mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); } return false; }; @@ -381,6 +395,10 @@ auto applyValueType(ModelProcessingInformation::ValueType vt, auto const& callba return callback.template operator()(); case Parametric: return callback.template operator()(); + case FinitePrecisionInterval: + return callback.template operator()(); + case ExactInterval: + return callback.template operator()(); } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected value type."); } @@ -400,6 +418,10 @@ auto applyDdLibValueType(storm::dd::DdType dd, ModelProcessingInformation::Value return callback.template operator()(); case Parametric: return callback.template operator()(); + case FinitePrecisionInterval: + return callback.template operator()(); + case ExactInterval: + return callback.template operator()(); } } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected DDType or value type."); @@ -591,8 +613,12 @@ std::shared_ptr buildModelExplicit(storm::settings::mo storm::parser::DirectEncodingValueType valueType{Default}; if constexpr (std::is_same_v) { valueType = Double; + } else if constexpr (std::is_same_v) { + valueType = DoubleInterval; } else if constexpr (std::is_same_v) { valueType = Rational; + } else if constexpr (std::is_same_v) { + valueType = RationalInterval; } else { static_assert(std::is_same_v, "Unexpected value type."); valueType = Parametric; @@ -1285,30 +1311,38 @@ inline std::vector> parseInjectedRef template void verifyWithAbstractionRefinementEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); - storm::gbar::api::AbstractionRefinementOptions options( - parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), - parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); - - verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, - std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); - return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), - storm::api::createTask(formula, true), options); - }); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Abstraction-refinement engine does not support interval value types."); + } else { + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); + storm::gbar::api::AbstractionRefinementOptions options( + parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), + parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); + + verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, + std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); + return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), + storm::api::createTask(formula, true), options); + }); + } } template void verifyWithExplorationEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, - "Exploration does not support other data-types than floating points."); - verifyProperties( - input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); - return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); - }); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Exploration engine does not support interval value types."); + } else { + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, + "Exploration does not support other data-types than floating points."); + verifyProperties( + input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); + return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); + }); + } } template diff --git a/src/storm-parsers/parser/ValueParser.cpp b/src/storm-parsers/parser/ValueParser.cpp index 00df851f84..4bb0e35e88 100644 --- a/src/storm-parsers/parser/ValueParser.cpp +++ b/src/storm-parsers/parser/ValueParser.cpp @@ -119,6 +119,51 @@ bool parseInterval(std::string const& value, storm::Interval& result) { return true; } +bool parseRationalInterval(std::string const& value, storm::RationalInterval& result) { + // Try whether it is a constant. + if (storm::RationalNumber pointResult; parseNumber(value, pointResult)) { + result = storm::RationalInterval(pointResult); + return true; + } + + std::string intermediate = value; + boost::trim(intermediate); + carl::BoundType leftBound; + carl::BoundType rightBound; + if (intermediate.front() == '(') { + leftBound = carl::BoundType::STRICT; + } else if (intermediate.front() == '[') { + leftBound = carl::BoundType::WEAK; + } else { + return false; // Expect start with '(' or '['. + } + if (intermediate.back() == ')') { + rightBound = carl::BoundType::STRICT; + } else if (intermediate.back() == ']') { + rightBound = carl::BoundType::WEAK; + } else { + return false; // Expected end with ')' or ']'. + } + intermediate = intermediate.substr(1, intermediate.size() - 2); + + std::vector words; + boost::split(words, intermediate, boost::is_any_of(",")); + if (words.size() != 2) { + return false; // Did not find exactly one comma. + } + storm::RationalNumber leftVal, rightVal; + boost::trim(words[0]); + if (!parseNumber(words[0], leftVal)) { + return false; // lower value of interval invalid. + } + boost::trim(words[1]); + if (!parseNumber(words[1], rightVal)) { + return false; // upper value of interval invalid. + } + result = storm::RationalInterval(leftVal, leftBound, rightVal, rightBound); + return true; +} + template bool parseNumber(std::string const& value, NumberType& result) { if constexpr (std::is_same_v) { @@ -127,6 +172,8 @@ bool parseNumber(std::string const& value, NumberType& result) { return carl::try_parse(value, result); } else if constexpr (std::is_same_v) { return parseInterval(value, result); + } else if constexpr (std::is_same_v) { + return parseRationalInterval(value, result); } else { return boost::conversion::try_lexical_convert(value, result); } @@ -137,6 +184,7 @@ template class ValueParser; template class ValueParser; template class ValueParser; template class ValueParser; +template class ValueParser; template std::size_t parseNumber(std::string const&); diff --git a/src/storm/adapters/IntervalForward.h b/src/storm/adapters/IntervalForward.h index ddc9a5d284..f0fc334b2e 100644 --- a/src/storm/adapters/IntervalForward.h +++ b/src/storm/adapters/IntervalForward.h @@ -1,5 +1,7 @@ #pragma once +#include "storm/adapters/RationalNumberForward.h" + namespace carl { template class Interval; @@ -11,6 +13,7 @@ namespace storm { * Interval type */ typedef carl::Interval Interval; +typedef carl::Interval RationalInterval; namespace detail { template @@ -23,6 +26,11 @@ struct IntervalMetaProgrammingHelper { using BaseType = double; static const bool isInterval = true; }; +template<> +struct IntervalMetaProgrammingHelper { + using BaseType = storm::RationalNumber; + static const bool isInterval = true; +}; } // namespace detail /*! diff --git a/src/storm/io/DirectEncodingExporter.cpp b/src/storm/io/DirectEncodingExporter.cpp index 39366362e3..26679ca7f0 100644 --- a/src/storm/io/DirectEncodingExporter.cpp +++ b/src/storm/io/DirectEncodingExporter.cpp @@ -72,6 +72,8 @@ void explicitExportSparseModel(std::ostream& os, std::shared_ptr) { os << "double-interval"; + } else if constexpr (std::is_same_v) { + os << "rational-interval"; } else if constexpr (std::is_same_v) { os << "parametric"; } else { @@ -338,5 +340,8 @@ template void explicitExportSparseModel(std::ostream& o std::vector const& parameters, DirectEncodingExporterOptions const& options); template void explicitExportSparseModel(std::ostream& os, std::shared_ptr> sparseModel, std::vector const& parameters, DirectEncodingExporterOptions const& options); +template void explicitExportSparseModel(std::ostream& os, + std::shared_ptr> sparseModel, + std::vector const& parameters, DirectEncodingExporterOptions const& options); } // namespace io } // namespace storm diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index 92122e5605..56664fcf2a 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -473,6 +473,9 @@ template class AbstractModelChecker>; template class AbstractModelChecker>>; template class AbstractModelChecker>>; +template class AbstractModelChecker>>; +template class AbstractModelChecker>>; + template class AbstractModelChecker>; template class AbstractModelChecker>; template class AbstractModelChecker>; @@ -491,6 +494,8 @@ template class AbstractModelChecker>; template class AbstractModelChecker>; +template class AbstractModelChecker>; + // DD template class AbstractModelChecker>; template class AbstractModelChecker>; diff --git a/src/storm/modelchecker/AbstractModelChecker.h b/src/storm/modelchecker/AbstractModelChecker.h index d1ec2e86ff..51261bddce 100644 --- a/src/storm/modelchecker/AbstractModelChecker.h +++ b/src/storm/modelchecker/AbstractModelChecker.h @@ -15,13 +15,31 @@ class CheckResult; template class AbstractModelChecker { + private: + // Due to a GCC bug we have to add this dummy template type here + // https://stackoverflow.com/questions/49707184/explicit-specialization-in-non-namespace-scope-does-not-compile-in-gcc + template + struct GetSolutionType { + using type = T; + }; + + template + struct GetSolutionType { + using type = double; + }; + + template + struct GetSolutionType { + using type = storm::RationalNumber; + }; + public: virtual ~AbstractModelChecker() { // Intentionally left empty. } typedef typename ModelType::ValueType ValueType; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = typename GetSolutionType::type; /*! * Returns the name of the model checker class (e.g., for display in error messages). diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index 02cb13fbca..9eedacca02 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -1,9 +1,14 @@ #include "storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h" +#include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" +#include "storm/adapters/RationalNumberAdapter.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/modelchecker/hints/ExplicitModelCheckerHint.h" #include "storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.h" #include "storm/models/sparse/StandardRewardModel.h" +#include "storm/storage/BitVector.h" #include "storm/utility/graph.h" #include "storm/utility/macros.h" #include "storm/utility/vector.h" @@ -17,22 +22,20 @@ namespace storm { namespace modelchecker { namespace helper { -template -SparseNondeterministicStepBoundedHorizonHelper::SparseNondeterministicStepBoundedHorizonHelper( +template +SparseNondeterministicStepBoundedHorizonHelper::SparseNondeterministicStepBoundedHorizonHelper( /*storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions*/) // transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) { // Intentionally left empty. } -template -std::vector SparseNondeterministicStepBoundedHorizonHelper::compute(Environment const& env, storm::solver::SolveGoal&& goal, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, - storm::storage::BitVector const& phiStates, - storm::storage::BitVector const& psiStates, uint64_t lowerBound, - uint64_t upperBound, ModelCheckerHint const& hint) { - std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); +template +std::vector SparseNondeterministicStepBoundedHorizonHelper::compute( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + uint64_t lowerBound, uint64_t upperBound, ModelCheckerHint const& hint) { + std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); storm::storage::BitVector makeZeroColumns; // Determine the states that have 0 probability of reaching the target states. @@ -56,20 +59,44 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper STORM_LOG_INFO("Preprocessing: " << maybeStates.getNumberOfSetBits() << " non-target states with probability greater 0."); if (!maybeStates.empty()) { - // We can eliminate the rows and columns from the original transition probability matrix that have probability 0. - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false, makeZeroColumns); - std::vector b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, psiStates); + storm::storage::SparseMatrix submatrix; + std::vector b; + uint64_t subresultSize; + + if constexpr (storm::IsIntervalType) { + // For intervals, we cannot remove all non maybe states as that would lead to the upper probability of rows summing to below 1. + // Instead we only drop all outgoing transitions of non maybe states. + // See src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp:624 for more details. + submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); + + storm::utility::vector::setAllValues(b, transitionMatrix.getRowFilter(psiStates)); + + subresultSize = transitionMatrix.getRowCount(); + } else { + // We can eliminate the rows and columns from the original transition probability matrix that have probability 0. + submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false, makeZeroColumns); + + b = transitionMatrix.getConstrainedRowGroupSumVector(maybeStates, psiStates); + subresultSize = maybeStates.getNumberOfSetBits(); + } // Create the vector with which to multiply. - std::vector subresult(maybeStates.getNumberOfSetBits()); + std::vector subresult(subresultSize); - auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); + auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); if (lowerBound == 0) { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound); } else { multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1); - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); - auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); + + storm::storage::SparseMatrix submatrix; + if constexpr (storm::IsIntervalType) { + submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates)); + } else { + submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, false); + } + + auto multiplier = storm::solver::MultiplierFactory().create(env, submatrix); b = std::vector(b.size(), storm::utility::zero()); multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, lowerBound - 1); } @@ -77,13 +104,15 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper storm::utility::vector::setVectorValues(result, maybeStates, subresult); } if (lowerBound == 0) { - storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); + storm::utility::vector::setVectorValues(result, psiStates, storm::utility::one()); } return result; } template class SparseNondeterministicStepBoundedHorizonHelper; template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; +template class SparseNondeterministicStepBoundedHorizonHelper; } // namespace helper } // namespace modelchecker } // namespace storm \ No newline at end of file diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h index fae2a12eae..304cee3ed9 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.h @@ -10,15 +10,15 @@ namespace storm { namespace modelchecker { namespace helper { -template +template class SparseNondeterministicStepBoundedHorizonHelper { public: SparseNondeterministicStepBoundedHorizonHelper(); - std::vector compute(Environment const& env, storm::solver::SolveGoal&& goal, - storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, - storm::storage::BitVector const& psiStates, uint64_t lowerBound, uint64_t upperBound, - ModelCheckerHint const& hint = ModelCheckerHint()); + std::vector compute(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, uint64_t lowerBound, uint64_t upperBound, + ModelCheckerHint const& hint = ModelCheckerHint()); private: }; diff --git a/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp b/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp index e35a064071..915155cf78 100644 --- a/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp +++ b/src/storm/modelchecker/hints/ExplicitModelCheckerHint.cpp @@ -122,6 +122,7 @@ template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; template class ExplicitModelCheckerHint; +template class ExplicitModelCheckerHint; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/hints/ModelCheckerHint.cpp b/src/storm/modelchecker/hints/ModelCheckerHint.cpp index af5991fb16..073e6b884f 100644 --- a/src/storm/modelchecker/hints/ModelCheckerHint.cpp +++ b/src/storm/modelchecker/hints/ModelCheckerHint.cpp @@ -34,6 +34,8 @@ template ExplicitModelCheckerHint const& ModelCheckerHi template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); template ExplicitModelCheckerHint const& ModelCheckerHint::asExplicitModelCheckerHint() const; template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); +template ExplicitModelCheckerHint const& ModelCheckerHint::asExplicitModelCheckerHint() const; +template ExplicitModelCheckerHint& ModelCheckerHint::asExplicitModelCheckerHint(); } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 0d21f5c533..55c4102e46 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -37,13 +37,16 @@ template bool SparseMdpPrctlModelChecker::canHandleStatic(CheckTask const& checkTask, bool* requiresSingleInitialState) { storm::logic::Formula const& formula = checkTask.getFormula(); - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { if (formula.isInFragment(storm::logic::propositional())) { return true; } if (formula.isInFragment(storm::logic::reachability())) { return true; } + if (formula.isInFragment(storm::logic::prctlstar().setBoundedUntilFormulasAllowed(true))) { + return true; + } } else { if (formula.isInFragment(storm::logic::prctlstar() .setLongRunAverageRewardFormulasAllowed(true) @@ -111,14 +114,14 @@ bool SparseMdpPrctlModelChecker::canHandle(CheckTask std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented bounded until with intervals"); - return nullptr; - } else { - storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); - STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, - "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); - if (pathFormula.isMultiDimensional() || pathFormula.getTimeBoundReference().isRewardBound()) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, + "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + if (pathFormula.isMultiDimensional() || pathFormula.getTimeBoundReference().isRewardBound()) { + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi dimensional bounded until with intervals"); + return nullptr; + } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, "Checking non-trivial bounded until probabilities can only be computed for the initial states of the model."); STORM_LOG_WARN_COND(!checkTask.isQualitativeSet(), "Checking non-trivial bounded until formulas is not optimized w.r.t. qualitative queries"); @@ -131,23 +134,21 @@ std::unique_ptr SparseMdpPrctlModelChecker::com auto numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeRewardBoundedValues( env, checkTask.getOptimizationDirection(), rewardUnfolding, this->getModel().getInitialStates()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); - } else { - STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have (a single) upper step bound."); - STORM_LOG_THROW(pathFormula.hasIntegerLowerBound(), storm::exceptions::InvalidPropertyException, - "Formula lower step bound must be discrete/integral."); - STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, - "Formula needs to have discrete upper time bound."); - std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); - std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); - storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; - std::vector numericResult = - helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), - pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), checkTask.getHint()); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } + } else { + STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have (a single) upper step bound."); + STORM_LOG_THROW(pathFormula.hasIntegerLowerBound(), storm::exceptions::InvalidPropertyException, "Formula lower step bound must be discrete/integral."); + STORM_LOG_THROW(pathFormula.hasIntegerUpperBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have discrete upper time bound."); + std::unique_ptr leftResultPointer = this->check(env, pathFormula.getLeftSubformula()); + std::unique_ptr rightResultPointer = this->check(env, pathFormula.getRightSubformula()); + ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); + ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); + storm::modelchecker::helper::SparseNondeterministicStepBoundedHorizonHelper helper; + std::vector numericResult = + helper.compute(env, storm::solver::SolveGoal(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), + pathFormula.getNonStrictLowerBound(), pathFormula.getNonStrictUpperBound(), checkTask.getHint()); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } } @@ -206,7 +207,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeHOAPathProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented automata-props with intervals"); } else { storm::logic::HOAPathFormula const& pathFormula = checkTask.getFormula(); @@ -233,7 +234,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLTLProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LTL with intervals"); } else { storm::logic::PathFormula const& pathFormula = checkTask.getFormula(); @@ -278,12 +279,12 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr rightResultPointer = this->check(env, conditionalFormula.getConditionFormula().asEventuallyFormula().getSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->template asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->template asExplicitQualitativeCheckResult(); - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), - this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), - leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + return storm::modelchecker::computeConditionalProbabilities( + env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), + this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } } @@ -294,24 +295,20 @@ std::unique_ptr SparseMdpPrctlModelChecker::com STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); if (rewardPathFormula.isMultiDimensional() || rewardPathFormula.getTimeBoundReference().isRewardBound()) { - if constexpr (std::is_same_v) { - throw exceptions::NotImplementedException() << "Multi-reward bounded is not supported with interval models"; - } else { - STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, - "Checking reward bounded cumulative reward formulas can only be done for the initial states of the model."); - STORM_LOG_THROW(!checkTask.getFormula().hasRewardAccumulation(), storm::exceptions::InvalidOperationException, - "Checking reward bounded cumulative reward formulas is not supported if reward accumulations are given."); - STORM_LOG_WARN_COND(!checkTask.isQualitativeSet(), "Checking reward bounded until formulas is not optimized w.r.t. qualitative queries"); - storm::logic::OperatorInformation opInfo(checkTask.getOptimizationDirection()); - if (checkTask.isBoundSet()) { - opInfo.bound = checkTask.getBound(); - } - auto formula = std::make_shared(checkTask.getFormula().asSharedPointer(), checkTask.getRewardModel(), opInfo); - helper::rewardbounded::MultiDimensionalRewardUnfolding rewardUnfolding(this->getModel(), formula); - auto numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeRewardBoundedValues( - env, checkTask.getOptimizationDirection(), rewardUnfolding, this->getModel().getInitialStates()); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); + STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, + "Checking reward bounded cumulative reward formulas can only be done for the initial states of the model."); + STORM_LOG_THROW(!checkTask.getFormula().hasRewardAccumulation(), storm::exceptions::InvalidOperationException, + "Checking reward bounded cumulative reward formulas is not supported if reward accumulations are given."); + STORM_LOG_WARN_COND(!checkTask.isQualitativeSet(), "Checking reward bounded until formulas is not optimized w.r.t. qualitative queries"); + storm::logic::OperatorInformation opInfo(checkTask.getOptimizationDirection()); + if (checkTask.isBoundSet()) { + opInfo.bound = checkTask.getBound(); } + auto formula = std::make_shared(checkTask.getFormula().asSharedPointer(), checkTask.getRewardModel(), opInfo); + helper::rewardbounded::MultiDimensionalRewardUnfolding rewardUnfolding(this->getModel(), formula); + auto numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeRewardBoundedValues( + env, checkTask.getOptimizationDirection(), rewardUnfolding, this->getModel().getInitialStates()); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } else { STORM_LOG_THROW(rewardPathFormula.hasIntegerBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask); @@ -439,7 +436,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageProbabilities( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented LRA probabilities with intervals"); } else { storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); @@ -464,7 +461,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageRewards( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lra with intervals"); } else { STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, @@ -485,7 +482,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::checkMultiObjectiveFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented multi-objective with intervals"); } else { return multiobjective::performMultiObjectiveModelChecking(env, this->getModel(), checkTask.getFormula(), checkTask.isProduceSchedulersSet()); @@ -495,7 +492,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkLexObjectiveFormula( const Environment& env, const CheckTask& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented lexicographic model checking with intervals"); } else { auto formulaChecker = [&](storm::logic::Formula const& formula) { @@ -510,7 +507,7 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template std::unique_ptr SparseMdpPrctlModelChecker::checkQuantileFormula( Environment const& env, CheckTask const& checkTask) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not yet implemented quantile formulas with intervals"); } else { STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidOperationException, @@ -533,5 +530,6 @@ std::unique_ptr SparseMdpPrctlModelChecker::che template class SparseMdpPrctlModelChecker>; template class SparseMdpPrctlModelChecker>; template class SparseMdpPrctlModelChecker>; +template class SparseMdpPrctlModelChecker>; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h index aa39728344..5a7f10a1fe 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -14,7 +14,7 @@ class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker, double, ValueType>::type; + using SolutionType = storm::IntervalBaseType; explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp index 275318d813..9ef02c1c25 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpEndComponentInformation.cpp @@ -105,7 +105,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation* columnSumVector, std::vector* summandResultVector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } @@ -247,7 +247,7 @@ SparseMdpEndComponentInformation SparseMdpEndComponentInformation& submatrix, std::vector& subvector, bool gatherExitChoices) { SparseMdpEndComponentInformation result(endComponentDecomposition, maybeStates); // TODO: Just like SparseMdpPrctlHelper::computeFixedPointSystemUntilProbabilities, this method must be adapted for intervals. - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support the elimination of end components and the creation of an adequate equation system with interval models."); } @@ -421,6 +421,7 @@ void SparseMdpEndComponentInformation::setScheduler(storm::storage::S template class SparseMdpEndComponentInformation; template class SparseMdpEndComponentInformation; template class SparseMdpEndComponentInformation; +template class SparseMdpEndComponentInformation; template void SparseMdpEndComponentInformation::setScheduler(storm::storage::Scheduler& scheduler, storm::storage::BitVector const& maybeStates, storm::storage::SparseMatrix const& transitionMatrix, @@ -438,6 +439,11 @@ template void SparseMdpEndComponentInformation::setScheduler(st storm::storage::SparseMatrix const& backwardTransitions, std::vector const& fromResult); +template void SparseMdpEndComponentInformation::setScheduler( + storm::storage::Scheduler& scheduler, storm::storage::BitVector const& maybeStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, std::vector const& fromResult); + // template class SparseMdpEndComponentInformation; } // namespace helper diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index ce93657d0d..1afc0a3a39 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -43,7 +43,7 @@ template std::map SparseMdpPrctlHelper::computeRewardBoundedValues( Environment const& env, OptimizationDirection dir, rewardbounded::MultiDimensionalRewardUnfolding& rewardUnfolding, storm::storage::BitVector const& initialStates) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models."); } else { storm::utility::Stopwatch swAll(true), swBuild, swCheck; @@ -133,8 +133,8 @@ template std::vector SparseMdpPrctlHelper::computeNextProbabilities( Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates) { - if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with reward models."); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models."); } else { // Create the vector with which to multiply and initialize it correctly. std::vector result(transitionMatrix.getRowGroupCount()); @@ -612,7 +612,7 @@ void computeFixedPointSystemUntilProbabilities(storm::solver::SolveGoal const& transitionMatrix, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix& submatrix, std::vector& b) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { // For non-interval based models, we can eliminate the rows and columns from the original transition probability matrix for states // whose probabilities are already known... However, there is information in the transition to those states. // Thus, we cannot eliminate them all. @@ -757,7 +757,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support this end component with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -768,7 +768,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (!storm::IsIntervalType) { // For non-interval models, we only operated on the maybe states, and we must recover the qualitative values for the other state. storm::utility::vector::setVectorValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); } else { @@ -777,7 +777,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper>(*scheduler, resultForMaybeStates.getScheduler(), + extractSchedulerChoices>(*scheduler, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates); } } @@ -833,7 +833,7 @@ template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepCount) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantenous rewards with interval models."); } else { // Only compute the result if the model has a state-based reward this->getModel(). @@ -854,7 +854,7 @@ template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models."); } else { // Only compute the result if the model has at least one reward this->getModel(). @@ -1061,6 +1061,9 @@ std::vector SparseMdpPrctlHelper::compute bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) { // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); + if constexpr (std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); + } else { return computeReachabilityRewardsHelper( env, std::move(goal), transitionMatrix, backwardTransitions, [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { @@ -1083,6 +1086,45 @@ std::vector SparseMdpPrctlHelper::compute }) .values; } +} + +template +std::vector SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, + storm::storage::BitVector const& targetStates, bool qualitative) { + // Only compute the result if the reward model is not empty. + STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); + if constexpr (std::is_same_v) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support interval rewards with rational interval models."); + } else { + return computeReachabilityRewardsHelper( + env, std::move(goal), transitionMatrix, backwardTransitions, + [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result; + result.reserve(rowCount); + std::vector subIntervalVector = + intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + for (auto const& interval : subIntervalVector) { + result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); + } + return result; + }, + targetStates, qualitative, false, + [&]() { + return intervalRewardModel.getStatesWithFilter(transitionMatrix, [&](storm::RationalInterval const& i) { + return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); + }); + }, + [&]() { + return intervalRewardModel.getChoicesWithFilter(transitionMatrix, [&](storm::RationalInterval const& i) { + return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); + }); + }) + .values; + } +} template<> std::vector SparseMdpPrctlHelper::computeReachabilityRewards( @@ -1092,6 +1134,15 @@ std::vector SparseMdpPrctlHelper:: STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); } +template<> +std::vector SparseMdpPrctlHelper::computeReachabilityRewards(Environment const& env, storm::solver::SolveGoal&&, + storm::storage::SparseMatrix const&, + storm::storage::SparseMatrix const&, + storm::models::sparse::StandardRewardModel const&, bool, + storm::storage::BitVector const&, bool) { + STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type."); +} + struct QualitativeStateSetsReachabilityRewards { storm::storage::BitVector maybeStates; storm::storage::BitVector infinityStates; @@ -1332,7 +1383,7 @@ template void computeUpperRewardBounds(SparseMdpHintType& hintInformation, storm::OptimizationDirection const& direction, storm::storage::SparseMatrix const& submatrix, std::vector const& choiceRewards, std::vector const& oneStepTargetProbabilities) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models."); } else { // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17). @@ -1371,7 +1422,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> scheduler; if (produceScheduler) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support producing schedulers in this function with interval models."); } else { scheduler = std::make_unique>(transitionMatrix.getRowGroupCount()); @@ -1416,7 +1467,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper> ecInformation; if (hintInformation.getEliminateEndComponents()) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation = computeFixedPointSystemReachabilityRewardsEliminateEndComponents( @@ -1441,7 +1492,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models."); } else { ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues()); @@ -1472,7 +1523,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelperisDeterministicScheduler(), "Expected a deterministic scheduler"); STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler"); - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { return MDPSparseModelCheckingHelperReturnType(std::move(result)); } else { return MDPSparseModelCheckingHelperReturnType(std::move(result), std::move(scheduler)); @@ -1546,6 +1597,30 @@ template MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper const& backwardTransitions, storm::models::sparse::StandardRewardModel const& rewardModel, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint); +template class SparseMdpPrctlHelper; +template std::vector SparseMdpPrctlHelper::computeInstantaneousRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepCount); +template std::vector SparseMdpPrctlHelper::computeCumulativeRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::models::sparse::StandardRewardModel const& rewardModel, uint_fast64_t stepBound); +template MDPSparseModelCheckingHelperReturnType +SparseMdpPrctlHelper::computeReachabilityRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, + bool produceScheduler, ModelCheckerHint const& hint); +template MDPSparseModelCheckingHelperReturnType +SparseMdpPrctlHelper::computeTotalRewards( + Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& rewardModel, bool qualitative, bool produceScheduler, + ModelCheckerHint const& hint); + } // namespace helper } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index eb9576b0da..cbcc545b4d 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -98,6 +98,12 @@ class SparseMdpPrctlHelper { storm::models::sparse::StandardRewardModel const& intervalRewardModel, bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); + static std::vector computeReachabilityRewards(Environment const& env, storm::solver::SolveGoal&& goal, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::models::sparse::StandardRewardModel const& intervalRewardModel, + bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative); + private: static MDPSparseModelCheckingHelperReturnType computeReachabilityRewardsHelper( Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp index 6f3533e6a8..552122bbc2 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp @@ -964,6 +964,8 @@ template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; +// template class MultiDimensionalRewardUnfolding; +// template class MultiDimensionalRewardUnfolding; } // namespace rewardbounded } // namespace helper } // namespace modelchecker diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp index d0f2648c07..120fac31db 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -65,6 +65,11 @@ template class SparsePropositionalModelChecker>>; template class SparsePropositionalModelChecker>>; +template class SparsePropositionalModelChecker< + storm::models::sparse::Mdp>>; +template class SparsePropositionalModelChecker< + storm::models::sparse::Smg>>; + template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; @@ -82,5 +87,8 @@ template class SparsePropositionalModelChecker>; template class SparsePropositionalModelChecker>; + +template class SparsePropositionalModelChecker>; +template class SparsePropositionalModelChecker>; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h index 52a6c3c137..7de1792319 100644 --- a/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h +++ b/src/storm/modelchecker/propositional/SparsePropositionalModelChecker.h @@ -8,10 +8,28 @@ namespace modelchecker { template class SparsePropositionalModelChecker : public AbstractModelChecker { + private: + // Due to a GCC bug we have to add this dummy template type here + // https://stackoverflow.com/questions/49707184/explicit-specialization-in-non-namespace-scope-does-not-compile-in-gcc + template + struct GetSolutionType { + using type = T; + }; + + template + struct GetSolutionType { + using type = double; + }; + + template + struct GetSolutionType { + using type = storm::RationalNumber; + }; + public: typedef typename SparseModelType::ValueType ValueType; typedef typename SparseModelType::RewardModelType RewardModelType; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = typename GetSolutionType::type; explicit SparsePropositionalModelChecker(SparseModelType const& model); diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 50b9a9e16c..76d86175b0 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,6 +3,7 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/JsonAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" diff --git a/src/storm/models/sparse/Ctmc.cpp b/src/storm/models/sparse/Ctmc.cpp index ccb39cad09..88ebbbd7e6 100644 --- a/src/storm/models/sparse/Ctmc.cpp +++ b/src/storm/models/sparse/Ctmc.cpp @@ -96,8 +96,10 @@ storm::storage::SparseMatrix Ctmc::comput template class Ctmc; template class Ctmc; template class Ctmc>; +template class Ctmc>; template class Ctmc; template class Ctmc; +template class Ctmc; } // namespace sparse } // namespace models } // namespace storm diff --git a/src/storm/models/sparse/DeterministicModel.cpp b/src/storm/models/sparse/DeterministicModel.cpp index 956c4e2e0c..c4d326380f 100644 --- a/src/storm/models/sparse/DeterministicModel.cpp +++ b/src/storm/models/sparse/DeterministicModel.cpp @@ -65,7 +65,9 @@ void DeterministicModel::writeDotToStream(std::ostre template class DeterministicModel; template class DeterministicModel>; template class DeterministicModel; +template class DeterministicModel>; template class DeterministicModel; +template class DeterministicModel; template class DeterministicModel; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Dtmc.cpp b/src/storm/models/sparse/Dtmc.cpp index 29ff1bd0a3..887dceff3d 100644 --- a/src/storm/models/sparse/Dtmc.cpp +++ b/src/storm/models/sparse/Dtmc.cpp @@ -3,6 +3,7 @@ #include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/models/sparse/StandardRewardModel.h" namespace storm { @@ -47,7 +48,9 @@ void Dtmc::reduceToStateBasedRewards() { template class Dtmc; template class Dtmc>; template class Dtmc; +template class Dtmc>; template class Dtmc; +template class Dtmc; template class Dtmc; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/MarkovAutomaton.cpp b/src/storm/models/sparse/MarkovAutomaton.cpp index 73d18d6b2f..c5fd21397e 100644 --- a/src/storm/models/sparse/MarkovAutomaton.cpp +++ b/src/storm/models/sparse/MarkovAutomaton.cpp @@ -250,7 +250,9 @@ void MarkovAutomaton::printModelInformationToStream( template class MarkovAutomaton; template class MarkovAutomaton>; template class MarkovAutomaton; +template class MarkovAutomaton>; template class MarkovAutomaton; +template class MarkovAutomaton; template class MarkovAutomaton; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Mdp.cpp b/src/storm/models/sparse/Mdp.cpp index d07bbf49da..60d4f636d3 100644 --- a/src/storm/models/sparse/Mdp.cpp +++ b/src/storm/models/sparse/Mdp.cpp @@ -44,7 +44,9 @@ Mdp::Mdp(storm::storage::sparse::ModelComponents; template class Mdp>; template class Mdp; +template class Mdp>; template class Mdp; +template class Mdp; template class Mdp; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Model.cpp b/src/storm/models/sparse/Model.cpp index dada7de970..f283bfaa90 100644 --- a/src/storm/models/sparse/Model.cpp +++ b/src/storm/models/sparse/Model.cpp @@ -644,7 +644,7 @@ bool Model::supportsParameters() const { template bool Model::supportsUncertainty() const { - return std::is_same::value; + return storm::IsIntervalType; } template @@ -729,7 +729,9 @@ std::set getAllParameters(Model; template class Model>; template class Model; +template class Model>; template class Model; +template class Model; template class Model; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/NondeterministicModel.cpp b/src/storm/models/sparse/NondeterministicModel.cpp index 0a256f75a4..5ee47ec3ed 100644 --- a/src/storm/models/sparse/NondeterministicModel.cpp +++ b/src/storm/models/sparse/NondeterministicModel.cpp @@ -190,8 +190,10 @@ uint_least64_t NondeterministicModel::getChoiceIndex template class NondeterministicModel; template class NondeterministicModel>; -template class NondeterministicModel; template class NondeterministicModel; +template class NondeterministicModel>; +template class NondeterministicModel; +template class NondeterministicModel; template class NondeterministicModel; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Pomdp.cpp b/src/storm/models/sparse/Pomdp.cpp index 69ecda855d..8f52964b25 100644 --- a/src/storm/models/sparse/Pomdp.cpp +++ b/src/storm/models/sparse/Pomdp.cpp @@ -156,7 +156,9 @@ std::size_t Pomdp::hash() const { template class Pomdp; template class Pomdp>; template class Pomdp; +template class Pomdp>; template class Pomdp; +template class Pomdp; template class Pomdp; } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/Smg.cpp b/src/storm/models/sparse/Smg.cpp index 9f7d708a1f..2a67a930bc 100644 --- a/src/storm/models/sparse/Smg.cpp +++ b/src/storm/models/sparse/Smg.cpp @@ -80,7 +80,9 @@ storm::storage::BitVector Smg::computeStatesOfCoalit template class Smg; template class Smg>; template class Smg; +template class Smg>; template class Smg; +template class Smg; template class Smg; } // namespace sparse diff --git a/src/storm/models/sparse/StandardRewardModel.cpp b/src/storm/models/sparse/StandardRewardModel.cpp index bdcdf92ecd..6c8c8f03c6 100644 --- a/src/storm/models/sparse/StandardRewardModel.cpp +++ b/src/storm/models/sparse/StandardRewardModel.cpp @@ -662,6 +662,48 @@ template storm::storage::BitVector StandardRewardModel::getChoi storm::storage::SparseMatrix const& transitionMatrix) const; template class StandardRewardModel; template std::ostream& operator<< (std::ostream& out, StandardRewardModel const& rewardModel); + +template std::vector StandardRewardModel::getTotalRewardVector( + uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& filter) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& weights) const; +template std::vector StandardRewardModel::getTotalRewardVector( + uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& filter) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix) const; +template std::vector StandardRewardModel::getTotalRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& weights) const; +template std::vector StandardRewardModel::getTotalActionRewardVector( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& stateRewardWeights) const; +template storm::storage::BitVector StandardRewardModel::getStatesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getStatesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithFilter( + storm::storage::SparseMatrix const& transitionMatrix, std::function const& filter) const; +template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalNumber const& newValue); +template void StandardRewardModel::setStateActionReward(uint_fast64_t choiceIndex, storm::RationalInterval const& newValue); +template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalNumber const& newValue); +template void StandardRewardModel::setStateReward(uint_fast64_t state, storm::RationalInterval const& newValue); +template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, + storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::clearRewardAtState(uint_fast64_t state, + storm::storage::SparseMatrix const& transitionMatrix); +template void StandardRewardModel::reduceToStateBasedRewards( + storm::storage::SparseMatrix const& transitionMatrix, bool reduceToStateRewards, std::vector const* weights); +template void StandardRewardModel::reduceToStateBasedRewards( + storm::storage::SparseMatrix const& transitionMatrix, bool reduceToStateRewards, + std::vector const* weights); +template storm::storage::BitVector StandardRewardModel::getStatesWithZeroReward( + storm::storage::SparseMatrix const& transitionMatrix) const; +template storm::storage::BitVector StandardRewardModel::getChoicesWithZeroReward( + storm::storage::SparseMatrix const& transitionMatrix) const; +template class StandardRewardModel; +template std::ostream& operator<< (std::ostream& out, StandardRewardModel const& rewardModel); } // namespace sparse } // namespace models diff --git a/src/storm/models/sparse/StochasticTwoPlayerGame.cpp b/src/storm/models/sparse/StochasticTwoPlayerGame.cpp index 47cc89ea67..c85bc0b163 100644 --- a/src/storm/models/sparse/StochasticTwoPlayerGame.cpp +++ b/src/storm/models/sparse/StochasticTwoPlayerGame.cpp @@ -63,8 +63,10 @@ storm::models::sparse::ChoiceLabeling const& StochasticTwoPlayerGame; template class StochasticTwoPlayerGame>; -template class StochasticTwoPlayerGame; template class StochasticTwoPlayerGame; +template class StochasticTwoPlayerGame>; +template class StochasticTwoPlayerGame; +template class StochasticTwoPlayerGame; template class StochasticTwoPlayerGame; } // namespace sparse diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp index d2efd632e8..8b440ee61f 100644 --- a/src/storm/settings/modules/GeneralSettings.cpp +++ b/src/storm/settings/modules/GeneralSettings.cpp @@ -32,6 +32,7 @@ const std::string GeneralSettings::bisimulationOptionShortName = "bisim"; const std::string GeneralSettings::parametricOptionName = "parametric"; const std::string GeneralSettings::exactOptionName = "exact"; const std::string GeneralSettings::soundOptionName = "sound"; +const std::string GeneralSettings::intervalOptionName = "interval"; GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { this->addOption( @@ -85,6 +86,7 @@ GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { .build()) .build()); this->addOption(storm::settings::OptionBuilder(moduleName, soundOptionName, false, "Sets whether to force sound model checking.").build()); + this->addOption(storm::settings::OptionBuilder(moduleName, intervalOptionName, false, "Sets whether to enable interval model checking.").build()); } bool GeneralSettings::isHelpSet() const { @@ -152,6 +154,10 @@ bool GeneralSettings::isSoundSet() const { return this->getOption(soundOptionName).getHasOptionBeenSet(); } +bool GeneralSettings::isIntervalSet() const { + return this->getOption(intervalOptionName).getHasOptionBeenSet(); +} + void GeneralSettings::finalize() { // Intentionally left empty. } diff --git a/src/storm/settings/modules/GeneralSettings.h b/src/storm/settings/modules/GeneralSettings.h index 1723583b14..2e2e12620f 100644 --- a/src/storm/settings/modules/GeneralSettings.h +++ b/src/storm/settings/modules/GeneralSettings.h @@ -123,6 +123,13 @@ class GeneralSettings : public ModuleSettings { */ bool isSoundSet() const; + /*! + * Retrieves whether the option enabling interval models is set. + * + * @return True if the option was set + */ + bool isIntervalSet() const; + bool check() const override; void finalize() override; @@ -149,6 +156,7 @@ class GeneralSettings : public ModuleSettings { static const std::string parametricOptionName; static const std::string exactOptionName; static const std::string soundOptionName; + static const std::string intervalOptionName; }; } // namespace modules diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 3fe6aa749d..32040e68ec 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -4,6 +4,7 @@ #include #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/environment/solver/OviSolverEnvironment.h" @@ -63,7 +64,7 @@ MinMaxMethod IterativeMinMaxLinearEquationSolver::getMe "different method."); method = MinMaxMethod::PolicyIteration; } else { - STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); + // STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); } } else if (env.solver().isForceSoundness() && method != MinMaxMethod::SoundValueIteration && method != MinMaxMethod::IntervalIteration && method != MinMaxMethod::PolicyIteration && method != MinMaxMethod::RationalSearch && method != MinMaxMethod::OptimisticValueIteration && @@ -135,7 +136,7 @@ void IterativeMinMaxLinearEquationSolver::setUpViOperat // The trivial row grouping minmax operator makes sense over intervals. viOperatorTriv = std::make_shared>(); viOperatorTriv->setMatrixBackwards(*this->A); - if constexpr (!std::is_same_v) { + if constexpr (!storm::IsIntervalType) { // It might be that someone is using a minmaxlinearequationsolver with an advanced VI algorithm // but is just passing a DTMC over doubles. In this case we need to populate this VI operator. // It behaves exactly the same as the trivial row grouping operator, but it is currently hardcoded @@ -168,7 +169,7 @@ template void IterativeMinMaxLinearEquationSolver::extractScheduler(std::vector& x, std::vector const& b, OptimizationDirection const& dir, UncertaintyResolutionMode uncertaintyResolutionMode, bool updateX) const { - if (std::is_same_v && this->A->hasTrivialRowGrouping()) { + if (storm::IsIntervalType && this->A->hasTrivialRowGrouping()) { // Create robust scheduler index if it doesn't exist yet if (!this->robustSchedulerIndex) { this->robustSchedulerIndex = std::vector(x.size(), 0); @@ -201,7 +202,7 @@ void IterativeMinMaxLinearEquationSolver::extractSchedu setUpViOperator(); } if (viOperatorTriv) { - if constexpr (std::is_same() && std::is_same()) { + if constexpr (storm::IsIntervalType && storm::IsIntervalType) { storm::solver::helper::SchedulerTrackingHelper schedHelper(viOperatorTriv); schedHelper.computeScheduler(x, b, dir, *this->schedulerChoices, uncertaintyResolutionMode, updateX ? &x : nullptr, this->robustSchedulerIndex); } else { @@ -218,8 +219,8 @@ template bool IterativeMinMaxLinearEquationSolver::solveInducedEquationSystem( Environment const& env, std::unique_ptr>& linearEquationSolver, std::vector const& scheduler, std::vector& x, std::vector& subB, std::vector const& originalB, OptimizationDirection dir) const { - if constexpr (std::is_same_v) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement solving induced equation systems for interval-based models outside of robust VI."); // Implementing this requires linear equation systems with different value types and solution types (or some appropriate casting) @@ -251,7 +252,7 @@ bool IterativeMinMaxLinearEquationSolver::solveInducedE for (uint64_t i = 0; i < row.getNumberOfEntries(); i++, schedulerIterator++) { if (!utility::isZero(probLeft)) { auto const& entry = rowIter[*schedulerIterator]; - auto const diameter = entry.getValue().upper() - entry.getValue().lower(); + SolutionType const diameter = entry.getValue().upper() - entry.getValue().lower(); auto const value = utility::min(probLeft, diameter); tmp[*schedulerIterator] += value; probLeft -= value; @@ -334,7 +335,7 @@ template bool IterativeMinMaxLinearEquationSolver::performPolicyIteration( Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b, std::vector&& initialPolicy) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement policy iteration for interval-based models."); return false; } else { @@ -460,7 +461,7 @@ MinMaxLinearEquationSolverRequirements IterativeMinMaxLinearEquationSolver) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ASSERT(!needsLinEqSolver, "Intervals should not require a linear equation solver."); // nothing to be done; } else if (needsLinEqSolver) { @@ -561,7 +562,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsOptimisticValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement optimistic value iteration for interval-based models."); return false; } else { @@ -617,7 +618,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsGuessingValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement guessing value iteration for interval-based models."); return false; } else { @@ -784,8 +785,8 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsIntervalIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement intervaliteration for interval-based models"); + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We did not implement interval iteration for interval-based models"); return false; } else { setUpViOperator(); @@ -827,7 +828,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsSoundValueIteration(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "SoundVI does not handle interval-based models"); return false; } else { @@ -879,7 +880,7 @@ bool IterativeMinMaxLinearEquationSolver::solveEquation template bool IterativeMinMaxLinearEquationSolver::solveEquationsViToPi(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "ViToPi does not handle interval-based models"); return false; } @@ -914,7 +915,7 @@ template bool IterativeMinMaxLinearEquationSolver::solveEquationsRationalSearch(Environment const& env, OptimizationDirection dir, std::vector& x, std::vector const& b) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Rational search does not handle interval-based models"); return false; } else { @@ -986,6 +987,7 @@ void IterativeMinMaxLinearEquationSolver::clearCache() template class IterativeMinMaxLinearEquationSolver; template class IterativeMinMaxLinearEquationSolver; template class IterativeMinMaxLinearEquationSolver; +template class IterativeMinMaxLinearEquationSolver; } // namespace solver } // namespace storm diff --git a/src/storm/solver/LinearEquationSolver.cpp b/src/storm/solver/LinearEquationSolver.cpp index 51d43b1bcd..3ad3d168d9 100644 --- a/src/storm/solver/LinearEquationSolver.cpp +++ b/src/storm/solver/LinearEquationSolver.cpp @@ -148,7 +148,7 @@ template std::unique_ptr> GeneralLinearEquationSolverFactory::create(Environment const& env) const { EquationSolverType type = env.solver().getLinearEquationSolverType(); - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We have not implemented interval-based linear equation solvers"); } diff --git a/src/storm/solver/MinMaxLinearEquationSolver.cpp b/src/storm/solver/MinMaxLinearEquationSolver.cpp index 81242b0296..5ee11d5e9a 100644 --- a/src/storm/solver/MinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/MinMaxLinearEquationSolver.cpp @@ -252,19 +252,19 @@ std::unique_ptr> GeneralMinM result = std::make_unique>( std::make_unique>()); } else if (method == MinMaxMethod::Topological) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("Topological method not implemented for ValueType==Interval."); } else { result = std::make_unique>(); } } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("LP method not implemented for ValueType==Interval."); } else { result = std::make_unique>(storm::utility::solver::getLpSolverFactory()); } } else if (method == MinMaxMethod::Acyclic) { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { STORM_LOG_ERROR("Acyclic method not implemented for ValueType==Interval"); } else { result = std::make_unique>(); @@ -322,4 +322,8 @@ template class GeneralMinMaxLinearEquationSolverFactory; template class MinMaxLinearEquationSolver; template class MinMaxLinearEquationSolverFactory; template class GeneralMinMaxLinearEquationSolverFactory; + +template class MinMaxLinearEquationSolver; +template class MinMaxLinearEquationSolverFactory; +template class GeneralMinMaxLinearEquationSolverFactory; } // namespace storm::solver diff --git a/src/storm/solver/SolveGoal.cpp b/src/storm/solver/SolveGoal.cpp index c42b8a9d8a..90d00ceff8 100644 --- a/src/storm/solver/SolveGoal.cpp +++ b/src/storm/solver/SolveGoal.cpp @@ -147,6 +147,7 @@ template class SolveGoal; template class SolveGoal; template class SolveGoal; template class SolveGoal; +template class SolveGoal; } // namespace solver } // namespace storm diff --git a/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp b/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp index 7f35cbb08f..1f9736902e 100644 --- a/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/StandardMinMaxLinearEquationSolver.cpp @@ -43,5 +43,6 @@ void StandardMinMaxLinearEquationSolver::setMatrix(stor template class StandardMinMaxLinearEquationSolver; template class StandardMinMaxLinearEquationSolver; template class StandardMinMaxLinearEquationSolver; +template class StandardMinMaxLinearEquationSolver; } // namespace storm::solver diff --git a/src/storm/solver/helper/SchedulerTrackingHelper.cpp b/src/storm/solver/helper/SchedulerTrackingHelper.cpp index 13e0ba5eaa..0a296626c1 100644 --- a/src/storm/solver/helper/SchedulerTrackingHelper.cpp +++ b/src/storm/solver/helper/SchedulerTrackingHelper.cpp @@ -135,5 +135,7 @@ template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; template class SchedulerTrackingHelper; +template class SchedulerTrackingHelper; +template class SchedulerTrackingHelper; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationHelper.cpp b/src/storm/solver/helper/ValueIterationHelper.cpp index 586b6ae9ae..72e6918851 100644 --- a/src/storm/solver/helper/ValueIterationHelper.cpp +++ b/src/storm/solver/helper/ValueIterationHelper.cpp @@ -172,5 +172,7 @@ template class ValueIterationHelper; template class ValueIterationHelper; template class ValueIterationHelper; template class ValueIterationHelper; +template class ValueIterationHelper; +template class ValueIterationHelper; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index 4ab2674bf5..44dbc87aa0 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -53,7 +53,7 @@ void ValueIterationOperator::setMat matrixColumns.back() = StartOfRowGroupIndicator; // This is the start of the next row group } } else { - if constexpr (std::is_same::value) { + if constexpr (storm::IsIntervalType) { matrixColumns.push_back(StartOfRowIndicator); // Indicate start of first row for (auto rowIndex : indexRange(0, numRows)) { bool hasOnlyConstants = true; @@ -204,5 +204,7 @@ template class ValueIterationOperator; template class ValueIterationOperator; template class ValueIterationOperator; template class ValueIterationOperator; +template class ValueIterationOperator; +template class ValueIterationOperator; } // namespace storm::solver::helper diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index f14d976f6f..a3172ad40e 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -241,6 +242,15 @@ class ValueIterationOperator { return {(*offsets.first)[offsetIndex], offsets.second}; } + template + OpT robustInitializeRowRes(std::vector const&, OffT const& offsets, uint64_t offsetIndex) const { + if constexpr (RobustDirection == OptimizationDirection::Maximize) { + return offsets.upper(); + } else { + return offsets.lower(); + } + } + template OpT robustInitializeRowRes(std::vector const&, std::vector const& offsets, uint64_t offsetIndex) const { if constexpr (RobustDirection == OptimizationDirection::Maximize) { @@ -272,7 +282,7 @@ class ValueIterationOperator { template auto applyRow(std::vector::const_iterator& matrixColumnIt, typename std::vector::const_iterator& matrixValueIt, OperandType const& operand, OffsetType const& offsets, uint64_t offsetIndex) const { - if constexpr (std::is_same_v) { + if constexpr (storm::IsIntervalType) { return applyRowRobust(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); } else { return applyRowStandard(matrixColumnIt, matrixValueIt, operand, offsets, offsetIndex); @@ -312,13 +322,13 @@ class ValueIterationOperator { auto applyRowRobust(std::vector::const_iterator& matrixColumnIt, typename std::vector::const_iterator& matrixValueIt, OperandType const& operand, OffsetType const& offsets, uint64_t offsetIndex) const { STORM_LOG_ASSERT(*matrixColumnIt >= StartOfRowIndicator, "VI Operator in invalid state."); - auto result{robustInitializeRowRes(operand, offsets, offsetIndex)}; + SolutionType result{robustInitializeRowRes(operand, offsets, offsetIndex)}; applyCache.robustOrder.clear(); if (applyCache.hasOnlyConstants.size() > 0 && applyCache.hasOnlyConstants.get(offsetIndex)) { for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt) { - auto const lower = matrixValueIt->lower(); + SolutionType const lower = matrixValueIt->lower(); if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -332,7 +342,7 @@ class ValueIterationOperator { SolutionType remainingValue{storm::utility::one()}; uint64_t orderCounter = 0; for (++matrixColumnIt; *matrixColumnIt < StartOfRowIndicator; ++matrixColumnIt, ++matrixValueIt, ++orderCounter) { - auto const lower = matrixValueIt->lower(); + SolutionType const lower = matrixValueIt->lower(); if constexpr (isPair::value) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Value Iteration is not implemented with pairs and interval-models."); // Notice the unclear semantics here in terms of how to order things. @@ -340,8 +350,8 @@ class ValueIterationOperator { result += operand[*matrixColumnIt] * lower; } remainingValue -= lower; - auto const diameter = matrixValueIt->upper() - lower; - if (!storm::utility::isZero(diameter)) { + SolutionType const diameter = static_cast(-lower + matrixValueIt->upper()); + if (!storm::utility::isZero(diameter)) { applyCache.robustOrder.emplace_back(operand[*matrixColumnIt], std::make_pair(diameter, orderCounter)); } } @@ -353,7 +363,7 @@ class ValueIterationOperator { std::sort(applyCache.robustOrder.begin(), applyCache.robustOrder.end(), cmp); for (auto const& pair : applyCache.robustOrder) { - auto availableMass = std::min(pair.second.first, remainingValue); + SolutionType availableMass = std::min(pair.second.first, remainingValue); result += availableMass * pair.first; remainingValue -= availableMass; if (storm::utility::isZero(remainingValue)) { @@ -462,8 +472,14 @@ class ValueIterationOperator { storage::BitVector hasOnlyConstants; }; + template + struct ApplyCache { + mutable std::vector>> robustOrder; + storage::BitVector hasOnlyConstants; + }; + /*! - * Cache for robust value iteration, empty struct for other ValueTypes than storm::Interval. + * Cache for robust value iteration, empty struct for other ValueTypes than storm::Interval and storm::RationalInterval. */ ApplyCache applyCache; diff --git a/src/storm/solver/multiplier/Multiplier.cpp b/src/storm/solver/multiplier/Multiplier.cpp index e12fb09b4a..7b30a6afca 100644 --- a/src/storm/solver/multiplier/Multiplier.cpp +++ b/src/storm/solver/multiplier/Multiplier.cpp @@ -1,4 +1,5 @@ #include "storm/solver/multiplier/Multiplier.h" +#include #include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" @@ -17,30 +18,33 @@ namespace storm { namespace solver { -template -Multiplier::Multiplier(storm::storage::SparseMatrix const& matrix) : matrix(matrix) { +template +Multiplier::Multiplier(storm::storage::SparseMatrix const& matrix) : matrix(matrix) { // Intentionally left empty. } -template -void Multiplier::clearCache() const { +template +void Multiplier::clearCache() const { cachedVector.reset(); } -template -void Multiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, - std::vector const* b, std::vector& result, std::vector* choices) const { +template +void Multiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, + std::vector const* b, std::vector& result, + std::vector* choices) const { multiplyAndReduce(env, dir, this->matrix.getRowGroupIndices(), x, b, result, choices); } -template -void Multiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, std::vector* choices, bool backwards) const { +template +void Multiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, std::vector* choices, + bool backwards) const { multiplyAndReduceGaussSeidel(env, dir, this->matrix.getRowGroupIndices(), x, b, choices, backwards); } -template -void Multiplier::repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const { +template +void Multiplier::repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, + uint64_t n) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); @@ -54,9 +58,9 @@ void Multiplier::repeatedMultiply(Environment const& env, std::vector } } -template -void Multiplier::repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n) const { +template +void Multiplier::repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, uint64_t n) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); @@ -70,15 +74,16 @@ void Multiplier::repeatedMultiplyAndReduce(Environment const& env, Op } } -template -void Multiplier::repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n, ValueType factor) const { +template +void Multiplier::repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, + std::vector& x, std::vector const* b, uint64_t n, + SolutionType factor) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); - std::transform(x.begin(), x.end(), x.begin(), [factor](ValueType& c) { return c * factor; }); + std::transform(x.begin(), x.end(), x.begin(), [factor](SolutionType& c) { return c * factor; }); multiplyAndReduce(env, dir, x, b, x); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); @@ -87,15 +92,15 @@ void Multiplier::repeatedMultiplyAndReduceWithFactor(Environment cons } } -template -void Multiplier::repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, uint64_t n, - ValueType factor) const { +template +void Multiplier::repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, + uint64_t n, SolutionType factor) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); - std::transform(x.begin(), x.end(), x.begin(), [factor](ValueType& c) { return c * factor; }); + std::transform(x.begin(), x.end(), x.begin(), [factor](SolutionType& c) { return c * factor; }); multiply(env, x, b, x); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); @@ -104,39 +109,44 @@ void Multiplier::repeatedMultiplyWithFactor(Environment const& env, s } } -template - -std::vector& Multiplier::provideCachedVector(uint64_t size) const { +template +std::vector& Multiplier::provideCachedVector(uint64_t size) const { if (this->cachedVector) { this->cachedVector->resize(size); } else { - this->cachedVector = std::make_unique>(size); + this->cachedVector = std::make_unique>(size); } return *this->cachedVector; } -template -std::unique_ptr> MultiplierFactory::create(Environment const& env, storm::storage::SparseMatrix const& matrix) { +template +std::unique_ptr> MultiplierFactory::create(Environment const& env, + storm::storage::SparseMatrix const& matrix) { auto type = env.solver().multiplier().getType(); // Adjust the type if the ValueType is not supported - if (type == MultiplierType::ViOperator && (std::is_same_v || std::is_same_v)) { + if (type == MultiplierType::ViOperator && + (std::is_same_v || (storm::IsIntervalType && storm::IsIntervalType))) { STORM_LOG_INFO("Switching multiplier type from 'vioperator' to 'native' because the given ValueType is not supported by the VI Operator multiplier."); type = MultiplierType::Native; } switch (type) { case MultiplierType::ViOperator: - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || (storm::IsIntervalType && storm::IsIntervalType)) { throw storm::exceptions::NotImplementedException() << "VI Operator multiplier not supported with given value type."; } if (matrix.hasTrivialRowGrouping()) { - return std::make_unique>(matrix); + return std::make_unique>(matrix); } else { - return std::make_unique>(matrix); + return std::make_unique>(matrix); } case MultiplierType::Native: - return std::make_unique>(matrix); + if constexpr (std::is_same_v) { + return std::make_unique>(matrix); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Native multiplier not implemented for unequal ValueType and SolutionType."); + } } STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentException, "Unknown MultiplierType"); } @@ -149,6 +159,10 @@ template class Multiplier; template class MultiplierFactory; template class Multiplier; template class MultiplierFactory; +template class Multiplier; +template class MultiplierFactory; +template class Multiplier; +template class MultiplierFactory; } // namespace solver } // namespace storm diff --git a/src/storm/solver/multiplier/Multiplier.h b/src/storm/solver/multiplier/Multiplier.h index fe8e0f7d4a..3a8bccd009 100644 --- a/src/storm/solver/multiplier/Multiplier.h +++ b/src/storm/solver/multiplier/Multiplier.h @@ -17,7 +17,7 @@ class SparseMatrix; namespace solver { -template +template class Multiplier { public: Multiplier(storm::storage::SparseMatrix const& matrix); @@ -39,7 +39,8 @@ class Multiplier { * @param result The target vector into which to write the multiplication result. Its length must be equal * to the number of rows of A. Can be the same as the x vector. */ - virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, std::vector& result) const = 0; + virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, + std::vector& result) const = 0; /*! * Performs a matrix-vector multiplication in gauss-seidel style. @@ -50,7 +51,7 @@ class Multiplier { * to the number of rows of A. * @param backwards if true, the iterations will be performed beginning from the last row and ending at the first row. */ - virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const = 0; + virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const = 0; /*! * Performs a matrix-vector multiplication x' = A*x + b and then minimizes/maximizes over the row groups @@ -66,10 +67,10 @@ class Multiplier { * to the number of rows of A. Can be the same as the x vector. * @param choices If given, the choices made in the reduction process are written to this vector. */ - void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, - std::vector& result, std::vector* choices = nullptr) const; + void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, + std::vector& result, std::vector* choices = nullptr) const; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector const& x, std::vector const* b, std::vector& result, + std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const = 0; /*! @@ -87,10 +88,10 @@ class Multiplier { * @param choices If given, the choices made in the reduction process are written to this vector. * @param backwards if true, the iterations will be performed beginning from the last rowgroup and ending at the first rowgroup. */ - void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, + void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector& x, std::vector const* b, std::vector* choices = nullptr, + std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const = 0; /*! @@ -104,7 +105,7 @@ class Multiplier { * to the number of rows of A. * @param n The number of times to perform the multiplication. */ - void repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const; + void repeatedMultiply(Environment const& env, std::vector& x, std::vector const* b, uint64_t n) const; /*! * Performs repeated matrix-vector multiplication x' = A*x + b and then minimizes/maximizes over the row groups @@ -119,7 +120,7 @@ class Multiplier { * to the number of rows of A. * @param n The number of times to perform the multiplication. */ - void repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, + void repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, uint64_t n) const; /*! * Performs repeated matrix-vector multiplication x' = A*(factor * x) + b. Vector x is scaled by factor in each iteration. @@ -133,7 +134,8 @@ class Multiplier { * @param n The number of times to perform the multiplication. * @param factor The scalar to multiply with in each iteration. */ - void repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, uint64_t n, ValueType factor) const; + void repeatedMultiplyWithFactor(Environment const& env, std::vector& x, std::vector const* b, uint64_t n, + SolutionType factor) const; /*! * Performs repeated matrix-vector multiplication x' = A*(factor * x) + b, minimizes/maximizes over the row groups @@ -149,23 +151,23 @@ class Multiplier { * @param n The number of times to perform the multiplication. * @param factor The scalar to multiply with in each iteration. */ - void repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n, ValueType factor) const; + void repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, + std::vector const* b, uint64_t n, SolutionType factor) const; protected: - std::vector& provideCachedVector(uint64_t size) const; + std::vector& provideCachedVector(uint64_t size) const; - mutable std::unique_ptr> cachedVector; + mutable std::unique_ptr> cachedVector; storm::storage::SparseMatrix const& matrix; }; -template +template class MultiplierFactory { public: MultiplierFactory() = default; ~MultiplierFactory() = default; - std::unique_ptr> create(Environment const& env, storm::storage::SparseMatrix const& matrix); + std::unique_ptr> create(Environment const& env, storm::storage::SparseMatrix const& matrix); }; } // namespace solver diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index fce6106637..fc85ce4cd1 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -1,5 +1,6 @@ #include "ViOperatorMultiplier.h" +#include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/exceptions/NotSupportedException.h" #include "storm/solver/helper/ValueIterationOperator.h" @@ -142,14 +143,15 @@ class PlainMultiplicationBackend { } // namespace detail -template -ViOperatorMultiplier::ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix) - : Multiplier(matrix) { +template +ViOperatorMultiplier::ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix) + : Multiplier(matrix) { // Intentionally left empty. } -template -typename ViOperatorMultiplier::ViOpT& ViOperatorMultiplier::initialize() const { +template +typename ViOperatorMultiplier::ViOpT& +ViOperatorMultiplier::initialize() const { if (!viOperatorFwd) { return initialize(false); // default to backward operator } else { @@ -157,8 +159,9 @@ typename ViOperatorMultiplier::ViOpT& ViOperatorM } } -template -typename ViOperatorMultiplier::ViOpT& ViOperatorMultiplier::initialize(bool backwards) const { +template +typename ViOperatorMultiplier::ViOpT& +ViOperatorMultiplier::initialize(bool backwards) const { auto& viOp = backwards ? viOperatorBwd : viOperatorFwd; if (!viOp) { viOp = std::make_unique(); @@ -171,9 +174,9 @@ typename ViOperatorMultiplier::ViOpT& ViOperatorM return *viOp; } -template -void ViOperatorMultiplier::multiply(Environment const& env, std::vector const& x, std::vector const* b, - std::vector& result) const { +template +void ViOperatorMultiplier::multiply(Environment const& env, std::vector const& x, + std::vector const* b, std::vector& result) const { if (&result == &x) { auto& tmpResult = this->provideCachedVector(x.size()); multiply(env, x, b, tmpResult); @@ -181,7 +184,7 @@ void ViOperatorMultiplier::multiply(Environment c return; } auto const& viOp = initialize(); - detail::PlainMultiplicationBackend backend(result); + detail::PlainMultiplicationBackend backend(result); // Below, we just add 'result' as a dummy argument to the apply method. // The backend already takes care of filling the result vector while processing the rows. if (b) { @@ -191,12 +194,12 @@ void ViOperatorMultiplier::multiply(Environment c } } -template -void ViOperatorMultiplier::multiplyGaussSeidel(Environment const& /*env*/, std::vector& x, - std::vector const* b, bool backwards) const { +template +void ViOperatorMultiplier::multiplyGaussSeidel(Environment const& /*env*/, std::vector& x, + std::vector const* b, bool backwards) const { STORM_LOG_THROW(TrivialRowGrouping, storm::exceptions::NotSupportedException, "This multiplier does not support multiplications without reduction when invoked with non-trivial row groups"); - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; auto const& viOp = initialize(backwards); if (b) { viOp.applyInPlace(x, *b, backend); @@ -205,11 +208,12 @@ void ViOperatorMultiplier::multiplyGaussSeidel(En } } -template -void ViOperatorMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, - std::vector const& rowGroupIndices, std::vector const& x, - std::vector const* b, std::vector& result, - std::vector* choices) const { +template +void ViOperatorMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, + std::vector const& rowGroupIndices, + std::vector const& x, std::vector const* b, + std::vector& result, + std::vector* choices) const { if (&result == &x) { auto& tmpResult = this->provideCachedVector(x.size()); multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, choices); @@ -219,37 +223,44 @@ void ViOperatorMultiplier::multiplyAndReduce(Envi STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException, "The row group indices must be the same as the ones stored in the matrix of this multiplier"); auto const& viOp = initialize(); - auto apply = [&](BT& backend) { - if (b) { - viOp.apply(x, result, *b, backend); + auto apply = [&](BT& backend, OptimizationDirection od) { + if (od == OptimizationDirection::Minimize) { + if (b) { + viOp.template applyRobust(x, result, *b, backend); + } else { + viOp.template applyRobust(x, result, storm::utility::zero(), backend); + } } else { - viOp.apply(x, result, storm::utility::zero(), backend); + if (b) { + viOp.template applyRobust(x, result, *b, backend); + } else { + viOp.template applyRobust(x, result, storm::utility::zero(), backend); + } } }; if (storm::solver::minimize(dir)) { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + apply(backend, OptimizationDirection::Maximize); } else { - detail::MultiplierBackend backend; - apply(backend); + detail::MultiplierBackend backend; + apply(backend, OptimizationDirection::Maximize); } } else { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + apply(backend, OptimizationDirection::Minimize); } else { - detail::MultiplierBackend backend; - apply(backend); + detail::MultiplierBackend backend; + apply(backend, OptimizationDirection::Minimize); } } } -template -void ViOperatorMultiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, - std::vector const& rowGroupIndices, std::vector& x, - std::vector const* b, std::vector* choices, - bool backwards) const { +template +void ViOperatorMultiplier::multiplyAndReduceGaussSeidel( + Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, + std::vector const* b, std::vector* choices, bool backwards) const { STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException, "The row group indices must be the same as the ones stored in the matrix of this multiplier"); auto const& viOp = initialize(backwards); @@ -262,28 +273,28 @@ void ViOperatorMultiplier::multiplyAndReduceGauss }; if (storm::solver::minimize(dir)) { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } else { if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); + detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); apply(backend); } else { - detail::MultiplierBackend backend; + detail::MultiplierBackend backend; apply(backend); } } } -template -void ViOperatorMultiplier::clearCache() const { +template +void ViOperatorMultiplier::clearCache() const { viOperatorBwd.reset(); viOperatorFwd.reset(); - Multiplier::clearCache(); + Multiplier::clearCache(); }; template class ViOperatorMultiplier; @@ -292,4 +303,10 @@ template class ViOperatorMultiplier; template class ViOperatorMultiplier; template class ViOperatorMultiplier; +template class ViOperatorMultiplier; +template class ViOperatorMultiplier; + +template class ViOperatorMultiplier; +template class ViOperatorMultiplier; + } // namespace storm::solver diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.h b/src/storm/solver/multiplier/ViOperatorMultiplier.h index 209ff9ee01..daeae609d3 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.h +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.h @@ -14,25 +14,26 @@ class SparseMatrix; namespace solver { -template -class ViOperatorMultiplier : public Multiplier { +template +class ViOperatorMultiplier : public Multiplier { public: ViOperatorMultiplier(storm::storage::SparseMatrix const& matrix); virtual ~ViOperatorMultiplier() = default; - virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, - std::vector& result) const override; - virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const override; + virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, + std::vector& result) const override; + virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, + bool backwards = true) const override; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector const& x, std::vector const* b, std::vector& result, + std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const override; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, - std::vector& x, std::vector const* b, std::vector* choices = nullptr, + std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const override; virtual void clearCache() const override; private: - using ViOpT = storm::solver::helper::ValueIterationOperator; + using ViOpT = storm::solver::helper::ValueIterationOperator; ViOpT& initialize() const; ViOpT& initialize(bool backwards) const; diff --git a/src/storm/storage/Distribution.cpp b/src/storm/storage/Distribution.cpp index 8ed053f11e..77b771e9f3 100644 --- a/src/storm/storage/Distribution.cpp +++ b/src/storm/storage/Distribution.cpp @@ -230,5 +230,10 @@ template std::ostream& operator<<(std::ostream& out, Distribution; template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); +template class Distribution; +template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); +template class Distribution; +template std::ostream& operator<<(std::ostream& out, Distribution const& distribution); + } // namespace storage } // namespace storm diff --git a/src/storm/storage/MaximalEndComponentDecomposition.cpp b/src/storm/storage/MaximalEndComponentDecomposition.cpp index 1df4402f1d..6e7763f048 100644 --- a/src/storm/storage/MaximalEndComponentDecomposition.cpp +++ b/src/storm/storage/MaximalEndComponentDecomposition.cpp @@ -252,6 +252,10 @@ template class MaximalEndComponentDecomposition; template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( storm::models::sparse::NondeterministicModel const& model); +template class MaximalEndComponentDecomposition; +template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( + storm::models::sparse::NondeterministicModel const& model); + template class MaximalEndComponentDecomposition; template MaximalEndComponentDecomposition::MaximalEndComponentDecomposition( storm::models::sparse::NondeterministicModel const& model); diff --git a/src/storm/storage/Scheduler.cpp b/src/storm/storage/Scheduler.cpp index a5db7a903c..1dacf8d86d 100644 --- a/src/storm/storage/Scheduler.cpp +++ b/src/storm/storage/Scheduler.cpp @@ -391,6 +391,7 @@ template class Scheduler; template class Scheduler; template class Scheduler; template class Scheduler; +template class Scheduler; } // namespace storage } // namespace storm diff --git a/src/storm/storage/SchedulerChoice.cpp b/src/storm/storage/SchedulerChoice.cpp index 3c89c96efc..668052c88b 100644 --- a/src/storm/storage/SchedulerChoice.cpp +++ b/src/storm/storage/SchedulerChoice.cpp @@ -75,6 +75,8 @@ template class SchedulerChoice; template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); template class SchedulerChoice; template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); +template class SchedulerChoice; +template std::ostream& operator<<(std::ostream& out, SchedulerChoice const& schedulerChoice); } // namespace storage } // namespace storm diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index d64bfc0f94..c10db5a6fd 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -672,15 +672,20 @@ typename SparseMatrix::index_type SparseMatrix::getEntryCo template typename SparseMatrix::index_type SparseMatrix::getRowGroupEntryCount(index_type const group) const { - index_type result = 0; if (!this->hasTrivialRowGrouping()) { + index_type result = 0; for (auto row : this->getRowGroupIndices(group)) { result += (this->rowIndications[row + 1] - this->rowIndications[row]); } + return result; } else { - result += (this->rowIndications[group + 1] - this->rowIndications[group]); + return (this->rowIndications[group + 1] - this->rowIndications[group]); } - return result; +} + +template +typename SparseMatrix::index_type SparseMatrix::getRowEntryCount(index_type const row) const { + return (this->rowIndications[row + 1] - this->rowIndications[row]); } template @@ -2532,5 +2537,19 @@ template bool SparseMatrix::isSubmatrixOf(SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; +// Rational Intervals +template std::vector SparseMatrix::getPointwiseProductRowSumVector( + storm::storage::SparseMatrix const& otherMatrix) const; +template class MatrixEntry::index_type, RationalInterval>; +template std::ostream& operator<<(std::ostream& out, MatrixEntry::index_type, RationalInterval> const& entry); +template class SparseMatrixBuilder; +template class SparseMatrix; +template std::ostream& operator<<(std::ostream& out, SparseMatrix const& matrix); +template std::vector SparseMatrix::getPointwiseProductRowSumVector( + storm::storage::SparseMatrix const& otherMatrix) const; +template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; + +template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; + } // namespace storage } // namespace storm diff --git a/src/storm/storage/SparseMatrix.h b/src/storm/storage/SparseMatrix.h index 5ccccceb85..f7eea9c4ce 100644 --- a/src/storm/storage/SparseMatrix.h +++ b/src/storm/storage/SparseMatrix.h @@ -531,6 +531,13 @@ class SparseMatrix { */ index_type getRowGroupEntryCount(index_type const group) const; + /*! + * Returns the number of entries in the given row of the matrix. + * @param row Which row + * @return Number of entries + */ + index_type getRowEntryCount(index_type const row) const; + /*! * Returns the cached number of nonzero entries in the matrix. * diff --git a/src/storm/storage/StronglyConnectedComponentDecomposition.cpp b/src/storm/storage/StronglyConnectedComponentDecomposition.cpp index 48808a2448..507339d3e7 100644 --- a/src/storm/storage/StronglyConnectedComponentDecomposition.cpp +++ b/src/storm/storage/StronglyConnectedComponentDecomposition.cpp @@ -343,5 +343,6 @@ template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; template class StronglyConnectedComponentDecomposition; +template class StronglyConnectedComponentDecomposition; } // namespace storm::storage diff --git a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp index 7f2d19b3c0..3de2e01489 100644 --- a/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp +++ b/src/storm/storage/memorystructure/MemoryStructureBuilder.cpp @@ -135,9 +135,11 @@ MemoryStructure MemoryStructureBuilder::buildTrivial template class MemoryStructureBuilder; template class MemoryStructureBuilder>; +template class MemoryStructureBuilder>; template class MemoryStructureBuilder; template class MemoryStructureBuilder; template class MemoryStructureBuilder; +template class MemoryStructureBuilder; } // namespace storage } // namespace storm diff --git a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp index fbb85aa97d..6bcea8b21a 100644 --- a/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp +++ b/src/storm/storage/memorystructure/SparseModelMemoryProduct.cpp @@ -571,9 +571,11 @@ SparseModelMemoryProductReverseData SparseModelMemoryProduct; template class SparseModelMemoryProduct>; +template class SparseModelMemoryProduct>; template class SparseModelMemoryProduct; template class SparseModelMemoryProduct; template class SparseModelMemoryProduct; +template class SparseModelMemoryProduct; } // namespace storage } // namespace storm diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index 64713ccfa1..a571208c97 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -17,15 +17,22 @@ template AddUncertainty::AddUncertainty(std::shared_ptr> const& originalModel) : origModel(originalModel) {} template -std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability) { +std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability, + uint64_t maxSuccessors) { // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { - for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { - newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); + if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { + for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { + newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); + } + } else { + for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { + newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), 0, 0)); + } } } storm::storage::sparse::ModelComponents modelComponents(newMatrixBuilder.build(), origModel->getStateLabeling()); @@ -80,4 +87,5 @@ storm::Interval AddUncertainty::addUncertainty(ValueType const& vt, d } template class AddUncertainty; +template class AddUncertainty; } // namespace storm::transformer \ No newline at end of file diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index f31088c1ca..7e0ae97986 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -16,7 +16,8 @@ template class AddUncertainty { public: AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001); + std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, + uint64_t maxSuccessors = 10000000); private: storm::Interval addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); diff --git a/src/storm/transformer/SubsystemBuilder.cpp b/src/storm/transformer/SubsystemBuilder.cpp index cbc6f8539a..c19983994e 100644 --- a/src/storm/transformer/SubsystemBuilder.cpp +++ b/src/storm/transformer/SubsystemBuilder.cpp @@ -225,6 +225,10 @@ template SubsystemBuilderReturnType> const& originalModel, storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions()); +template SubsystemBuilderReturnType> buildSubsystem( + storm::models::sparse::Model> const& originalModel, + storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, + SubsystemBuilderOptions options = SubsystemBuilderOptions()); template SubsystemBuilderReturnType buildSubsystem(storm::models::sparse::Model const& originalModel, storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, @@ -238,6 +242,11 @@ template SubsystemBuilderReturnType buildSubsystem(storm::model storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions()); +template SubsystemBuilderReturnType buildSubsystem(storm::models::sparse::Model const& originalModel, + storm::storage::BitVector const& subsystemStates, + storm::storage::BitVector const& subsystemActions, + bool keepUnreachableStates = true, + SubsystemBuilderOptions options = SubsystemBuilderOptions()); } // namespace transformer } // namespace storm diff --git a/src/storm/utility/ConstantsComparator.cpp b/src/storm/utility/ConstantsComparator.cpp index 5513626567..7a80f4b17a 100644 --- a/src/storm/utility/ConstantsComparator.cpp +++ b/src/storm/utility/ConstantsComparator.cpp @@ -65,5 +65,6 @@ template class ConstantsComparator; template class ConstantsComparator; template class ConstantsComparator; +template class ConstantsComparator; } // namespace utility } // namespace storm diff --git a/src/storm/utility/NumberTraits.h b/src/storm/utility/NumberTraits.h index 0ef102199b..408471dfa6 100644 --- a/src/storm/utility/NumberTraits.h +++ b/src/storm/utility/NumberTraits.h @@ -1,5 +1,6 @@ #pragma once +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalFunctionForward.h" #include "storm/adapters/RationalNumberForward.h" @@ -40,6 +41,18 @@ struct NumberTraits { }; #endif +template<> +struct NumberTraits { + static const bool SupportsExponential = false; + static const bool IsExact = false; +}; + +template<> +struct NumberTraits { + static const bool SupportsExponential = false; + static const bool IsExact = true; +}; + template<> struct NumberTraits { static const bool SupportsExponential = false; diff --git a/src/storm/utility/builder.cpp b/src/storm/utility/builder.cpp index 0e67de3fb8..1a19e27316 100644 --- a/src/storm/utility/builder.cpp +++ b/src/storm/utility/builder.cpp @@ -43,12 +43,18 @@ template std::shared_ptr> buildModelFromCom template std::shared_ptr>> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents>&& components); +template std::shared_ptr>> +buildModelFromComponents( + storm::models::ModelType modelType, + storm::storage::sparse::ModelComponents>&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); template std::shared_ptr> buildModelFromComponents( storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); +template std::shared_ptr> buildModelFromComponents( + storm::models::ModelType modelType, storm::storage::sparse::ModelComponents&& components); } // namespace builder } // namespace utility diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index c2d63d1cf5..0e32f2187e 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -809,6 +809,11 @@ bool isConstant(storm::Interval const& a) { return a.isPointInterval(); } +template<> +bool isConstant(storm::RationalInterval const& a) { + return a.isPointInterval(); +} + template<> bool isInfinity(storm::RationalFunction const& a) { // FIXME: this should be treated more properly. @@ -1009,6 +1014,11 @@ storm::Interval convertNumber(uint64_t const& number) { return storm::Interval(convertNumber(number)); } +template<> +storm::RationalInterval convertNumber(double const& number) { + return storm::RationalInterval(convertNumber(number)); +} + #if defined(STORM_HAVE_GMP) template<> storm::Interval convertNumber(storm::GmpRationalNumber const& n) { @@ -1020,6 +1030,17 @@ storm::GmpRationalNumber convertNumber(storm::Interval const& number) { STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); return convertNumber(number.lower()); } + +template<> +storm::RationalInterval convertNumber(storm::GmpRationalNumber const& n) { + return storm::RationalInterval(convertNumber(n)); +} + +template<> +storm::GmpRationalNumber convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); + return convertNumber(number.lower()); +} #endif #if defined(STORM_HAVE_CLN) @@ -1033,6 +1054,17 @@ storm::ClnRationalNumber convertNumber(storm::Interval const& number) { STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); return convertNumber(number.lower()); } + +template<> +storm::RationalInterval convertNumber(storm::ClnRationalNumber const& n) { + return storm::RationalInterval(convertNumber(n)); +} + +template<> +storm::ClnRationalNumber convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert"); + return convertNumber(number.lower()); +} #endif template<> @@ -1041,6 +1073,12 @@ double convertNumber(storm::Interval const& number) { return number.lower(); } +template<> +double convertNumber(storm::RationalInterval const& number) { + STORM_LOG_ASSERT(number.isPointInterval(), "Rational interval must be a point interval to convert"); + return convertNumber(number.lower()); +} + template<> storm::Interval abs(storm::Interval const& interval) { return interval.abs(); @@ -1053,6 +1091,11 @@ bool isApproxEqual(storm::Interval const& a, storm::Interval const& b, storm::In isApproxEqual(a.upper(), b.upper(), precision.center(), relative); } +template<> +storm::RationalInterval abs(storm::RationalInterval const& interval) { + return interval.abs(); +} + // Explicit instantiations. // double @@ -1219,5 +1262,14 @@ template bool isBetween(Interval const&, Interval const&, Interval const& value, template std::string to_string(storm::Interval const& value); +// Instantiations for intervals. +template RationalInterval one(); +template RationalInterval zero(); +template bool isOne(RationalInterval const& value); +template bool isZero(RationalInterval const& value); +template bool isInfinity(RationalInterval const& value); +template bool isAlmostZero(RationalInterval const& value); + +template std::string to_string(storm::RationalInterval const& value); } // namespace utility } // namespace storm diff --git a/src/storm/utility/graph.cpp b/src/storm/utility/graph.cpp index e407834ecf..8964fde8ab 100644 --- a/src/storm/utility/graph.cpp +++ b/src/storm/utility/graph.cpp @@ -1962,6 +1962,10 @@ template storm::storage::BitVector performProb0E( template storm::storage::BitVector performProb0E( storm::models::sparse::NondeterministicModel> const& model, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); +template storm::storage::BitVector performProb0E( + storm::models::sparse::NondeterministicModel> const& model, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); template storm::storage::BitVector performProb0E(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, @@ -1973,6 +1977,10 @@ template storm::storage::BitVector performProb1A( template storm::storage::BitVector performProb1A( storm::models::sparse::NondeterministicModel> const& model, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); +template storm::storage::BitVector performProb1A( + storm::models::sparse::NondeterministicModel> const& model, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); template storm::storage::BitVector performProb1A(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, @@ -2264,6 +2272,143 @@ template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix getTopologicalSort(storm::storage::SparseMatrix const& matrix, std::vector const& firstStates); // End storm::interval +// Instantiations for storm::Rationalinterval + +template storm::storage::BitVector getReachableOneStep(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates); + +template storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix 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 const& choiceFilter); + +template storm::storage::BitVector getBsccCover(storm::storage::SparseMatrix const& transitionMatrix); + +template bool hasCycle(storm::storage::SparseMatrix const& transitionMatrix, + boost::optional const& subsystem); + +template bool checkIfECWithChoiceExists(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices); + +template std::vector getDistances(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::BitVector const& initialStates, boost::optional const& subsystem); + +template storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0); + +template storm::storage::BitVector performProb1(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + storm::storage::BitVector const& statesWithProbabilityGreater0); + +template storm::storage::BitVector performProb1(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01( + storm::models::sparse::DeterministicModel const& model, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01( + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template void computeSchedulerProbGreater0E(storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + storm::storage::Scheduler& scheduler, + boost::optional const& rowFilter); + +template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::Scheduler& scheduler); + +template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::Scheduler& scheduler); + +template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, + storm::storage::SparseMatrix const& transitionMatrix, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + storm::storage::Scheduler& scheduler, + boost::optional const& rowFilter = boost::none); + +template storm::storage::BitVector performProbGreater0E(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0); + +template storm::storage::BitVector performProb0A(storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb1E(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + boost::optional const& choiceConstraint = boost::none); + +template storm::storage::BitVector performProb1E(storm::models::sparse::NondeterministicModel const& model, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01Max( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01Max( + storm::models::sparse::NondeterministicModel const& model, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProbGreater0A(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, + bool useStepBound = false, uint_fast64_t maximalSteps = 0, + boost::optional const& choiceConstraint = boost::none); + +template storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel const& model, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb0E(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template storm::storage::BitVector performProb1A(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, + storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + +template std::pair performProb01Min( + storm::storage::SparseMatrix const& transitionMatrix, std::vector const& nondeterministicChoiceIndices, + storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template std::pair performProb01Min( + storm::models::sparse::NondeterministicModel const& model, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates); + +template ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& player1RowGrouping, + storm::storage::SparseMatrix const& player1BackwardTransitions, + std::vector const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, + storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair); + +template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix const& transitionMatrix, + std::vector const& player1RowGrouping, + storm::storage::SparseMatrix const& player1BackwardTransitions, + std::vector const& player2BackwardTransitions, storm::storage::BitVector const& phiStates, + storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction, + storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair, + boost::optional const& player1Candidates); + +template std::vector getTopologicalSort(storm::storage::SparseMatrix const& matrix, + std::vector const& firstStates); +// End storm::Rationalinterval template storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates, diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index d49c63f129..46e9b8e9b6 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -1,4 +1,6 @@ #include "storm-config.h" +#include "storm/adapters/RationalNumberForward.h" +#include "storm/exceptions/NotImplementedException.h" #include "test/storm_gtest.h" #include "storm-parsers/api/model_descriptions.h" @@ -25,6 +27,11 @@ std::unique_ptr getInitialStateFilt return std::make_unique>(model->getInitialStates()); } +std::unique_ptr getInitialStateFilter( + std::shared_ptr> const& model) { + return std::make_unique(model->getInitialStates()); +} + double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, std::unique_ptr& result) { auto filter = getInitialStateFilter(model); @@ -39,6 +46,13 @@ double getQuantitativeResultAtInitialState(std::shared_ptrasQuantitativeCheckResult().getMin(); } +storm::RationalNumber getQuantitativeResultAtInitialState(std::shared_ptr> const& model, + std::unique_ptr& result) { + auto filter = getInitialStateFilter(model); + result->filter(*filter); + return result->asQuantitativeCheckResult().getMin(); +} + void expectThrow(std::string const& path, std::string const& formulaString) { std::shared_ptr> modelPtr = storm::parser::parseDirectEncodingModel(path); std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); @@ -51,7 +65,7 @@ void expectThrow(std::string const& path, std::string const& formulaString) { auto task = storm::modelchecker::CheckTask(*formulas[0]); auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); - STORM_SILENT_EXPECT_THROW(checker.check(env, task), storm::exceptions::InvalidArgumentException); + STORM_SILENT_EXPECT_THROW(checker.check(env, task), storm::exceptions::NotImplementedException); } void checkModel(std::string const& path, std::string const& formulaString, double maxmin, double maxmax, double minmax, double minmin, bool produceScheduler) { @@ -124,6 +138,36 @@ void checkPrismModelForQuantitativeResult(std::string const& path, std::string c EXPECT_NEAR(maxmax, getQuantitativeResultAtInitialState(mdp, resultMaxMax), 0.0001); } +void checkModelRational(std::string const& path, std::string const& formulaString, storm::RationalNumber maxmin, storm::RationalNumber maxmax, + storm::RationalNumber minmax, storm::RationalNumber minmin, bool produceScheduler) { + std::shared_ptr> modelPtr = + storm::parser::DirectEncodingParser::parseModel(path); + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); + storm::Environment env; + env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + + std::shared_ptr> mdp = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Mdp, modelPtr->getType()); + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setProduceSchedulers(produceScheduler); + + auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); + auto resultMax = checker.check(env, taskMax); + EXPECT_EQ(maxmin, getQuantitativeResultAtInitialState(mdp, resultMax)); + taskMax.setRobustUncertainty(false); + auto resultMaxNonRobust = checker.check(env, taskMax); + EXPECT_EQ(maxmax, getQuantitativeResultAtInitialState(mdp, resultMaxNonRobust)); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[1]); + taskMin.setProduceSchedulers(produceScheduler); + + auto resultMin = checker.check(env, taskMin); + EXPECT_EQ(minmax, getQuantitativeResultAtInitialState(mdp, resultMin)); + taskMin.setRobustUncertainty(false); + auto resultMinNonRobust = checker.check(env, taskMin); + EXPECT_EQ(minmin, getQuantitativeResultAtInitialState(mdp, resultMinNonRobust)); +} + TEST(RobustMdpModelCheckerTest, RobotMinMaxTest) { #ifndef STORM_HAVE_Z3 GTEST_SKIP() << "Z3 not available."; @@ -177,7 +221,9 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - expectThrow(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"]"); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.5, 0.5, 0.5, 0.5, true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(1, 2), + storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { From 1e81ea3d63877b1411d9ae2f87234bdc3e7d8447 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 11 Mar 2026 13:42:49 +0100 Subject: [PATCH 14/27] Move conditional code for later commit. --- src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index 55c4102e46..a562790211 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -282,9 +282,9 @@ std::unique_ptr SparseMdpPrctlModelChecker::com if constexpr (storm::IsIntervalType) { throw exceptions::NotImplementedException() << "Conditional Probabilities are not supported with interval models"; } else { - return storm::modelchecker::computeConditionalProbabilities( - env, storm::solver::SolveGoal(this->getModel(), checkTask), checkTask, this->getModel().getTransitionMatrix(), - this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); + return storm::modelchecker::computeConditionalProbabilities(env, storm::solver::SolveGoal(this->getModel(), checkTask), + this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), + leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector()); } } From 68a67f0cbdb718775f820053c61b2eb138ed5d3f Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 11 Mar 2026 13:47:42 +0100 Subject: [PATCH 15/27] format --- .../prctl/helper/SparseMdpPrctlHelper.cpp | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 1afc0a3a39..cb205d7cae 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -778,7 +778,7 @@ MDPSparseModelCheckingHelperReturnType SparseMdpPrctlHelper>(*scheduler, resultForMaybeStates.getScheduler(), - qualitativeStateSets.maybeStates); + qualitativeStateSets.maybeStates); } } } @@ -1064,28 +1064,28 @@ std::vector SparseMdpPrctlHelper::compute if constexpr (std::is_same_v) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); } else { - return computeReachabilityRewardsHelper( - env, std::move(goal), transitionMatrix, backwardTransitions, - [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { - std::vector result; - result.reserve(rowCount); - std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); - for (auto const& interval : subIntervalVector) { - result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); - } - return result; - }, - targetStates, qualitative, false, - [&]() { - return intervalRewardModel.getStatesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }, - [&]() { - return intervalRewardModel.getChoicesWithFilter( - transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); - }) - .values; -} + return computeReachabilityRewardsHelper( + env, std::move(goal), transitionMatrix, backwardTransitions, + [&](uint_fast64_t rowCount, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result; + result.reserve(rowCount); + std::vector subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates); + for (auto const& interval : subIntervalVector) { + result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper()); + } + return result; + }, + targetStates, qualitative, false, + [&]() { + return intervalRewardModel.getStatesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }, + [&]() { + return intervalRewardModel.getChoicesWithFilter( + transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); }); + }) + .values; + } } template From 981c96587b70510b0c294b869b76875c84e2a52a Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 11 Mar 2026 16:55:09 +0100 Subject: [PATCH 16/27] Enhance support for RationalNumber in AddUncertainty transformer and related components and added tests - Updated AddUncertainty transformer to handle RationalNumber types, allowing for exact arithmetic with RationalInterval. - Modified various helper functions and model checkers to accommodate RationalNumber and RationalInterval. - Introduced new tests for RationalNumber scenarios in model checking and uncertainty transformations. - Ensured compatibility with existing models while expanding functionality for uncertain models using RationalNumber. --- src/storm-cli-utilities/model-handling.h | 80 ++----- .../parser/DirectEncodingParser.cpp | 5 + src/storm/builder/ExplicitModelBuilder.cpp | 1 + src/storm/builder/RewardModelBuilder.cpp | 1 + src/storm/generator/Choice.cpp | 1 + src/storm/generator/Distribution.cpp | 2 + src/storm/generator/DistributionEntry.cpp | 3 + src/storm/generator/NextStateGenerator.cpp | 4 + .../generator/PrismNextStateGenerator.cpp | 1 + src/storm/generator/StateBehavior.cpp | 1 + .../modelchecker/AbstractModelChecker.cpp | 1 + .../prctl/SparseDtmcPrctlModelChecker.cpp | 5 +- .../prctl/SparseDtmcPrctlModelChecker.h | 3 +- .../prctl/SparseMdpPrctlModelChecker.cpp | 16 ++ .../prctl/helper/SparseDtmcPrctlHelper.cpp | 1 + .../MultiDimensionalRewardUnfolding.cpp | 2 - .../solver/helper/SchedulerTrackingHelper.cpp | 2 +- .../solver/helper/ValueIterationHelper.cpp | 4 +- .../solver/helper/ValueIterationOperator.cpp | 3 +- src/storm/transformer/AddUncertainty.cpp | 46 ++-- src/storm/transformer/AddUncertainty.h | 16 +- src/storm/utility/constants.cpp | 15 ++ .../dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 209 ++++++++++++++++++ .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 102 ++++++++- .../storm/transformer/AddUncertaintyTest.cpp | 33 +++ 25 files changed, 458 insertions(+), 99 deletions(-) diff --git a/src/storm-cli-utilities/model-handling.h b/src/storm-cli-utilities/model-handling.h index 2394c58bcc..f28dc7faf2 100644 --- a/src/storm-cli-utilities/model-handling.h +++ b/src/storm-cli-utilities/model-handling.h @@ -154,7 +154,7 @@ struct ModelProcessingInformation { bool transformToJani; // Which data type is to be used for numbers ... - enum class ValueType { FinitePrecision, Exact, Parametric, FinitePrecisionInterval, ExactInterval }; + enum class ValueType { FinitePrecision, Exact, Parametric }; ValueType buildValueType; // ... during model building ValueType verificationValueType; // ... during model verification @@ -222,17 +222,9 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co if (generalSettings.isParametricSet()) { mpi.verificationValueType = ModelProcessingInformation::ValueType::Parametric; } else if (generalSettings.isExactSet()) { - if (generalSettings.isIntervalSet()) { - mpi.verificationValueType = ModelProcessingInformation::ValueType::ExactInterval; - } else { - mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; - } + mpi.verificationValueType = ModelProcessingInformation::ValueType::Exact; } else { - if (generalSettings.isIntervalSet()) { - mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecisionInterval; - } else { - mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; - } + mpi.verificationValueType = ModelProcessingInformation::ValueType::FinitePrecision; } auto originalVerificationValueType = mpi.verificationValueType; @@ -278,12 +270,6 @@ inline ModelProcessingInformation getModelProcessingInformation(SymbolicInput co case ModelProcessingInformation::ValueType::FinitePrecision: return storm::utility::canHandle( mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); - case ModelProcessingInformation::ValueType::FinitePrecisionInterval: - return storm::utility::canHandle( - mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); - case ModelProcessingInformation::ValueType::ExactInterval: - return storm::utility::canHandle( - mpi.engine, input.preprocessedProperties.is_initialized() ? input.preprocessedProperties.get() : input.properties, input.model.get()); } return false; }; @@ -395,10 +381,6 @@ auto applyValueType(ModelProcessingInformation::ValueType vt, auto const& callba return callback.template operator()(); case Parametric: return callback.template operator()(); - case FinitePrecisionInterval: - return callback.template operator()(); - case ExactInterval: - return callback.template operator()(); } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected value type."); } @@ -418,10 +400,6 @@ auto applyDdLibValueType(storm::dd::DdType dd, ModelProcessingInformation::Value return callback.template operator()(); case Parametric: return callback.template operator()(); - case FinitePrecisionInterval: - return callback.template operator()(); - case ExactInterval: - return callback.template operator()(); } } STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected DDType or value type."); @@ -613,12 +591,8 @@ std::shared_ptr buildModelExplicit(storm::settings::mo storm::parser::DirectEncodingValueType valueType{Default}; if constexpr (std::is_same_v) { valueType = Double; - } else if constexpr (std::is_same_v) { - valueType = DoubleInterval; } else if constexpr (std::is_same_v) { valueType = Rational; - } else if constexpr (std::is_same_v) { - valueType = RationalInterval; } else { static_assert(std::is_same_v, "Unexpected value type."); valueType = Parametric; @@ -1311,38 +1285,30 @@ inline std::vector> parseInjectedRef template void verifyWithAbstractionRefinementEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - if constexpr (storm::IsIntervalType) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Abstraction-refinement engine does not support interval value types."); - } else { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); - storm::gbar::api::AbstractionRefinementOptions options( - parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), - parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); - - verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, - std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); - return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), - storm::api::createTask(formula, true), options); - }); - } + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + storm::settings::modules::AbstractionSettings const& abstractionSettings = storm::settings::getModule(); + storm::gbar::api::AbstractionRefinementOptions options( + parseConstraints(input.model->getManager(), abstractionSettings.getConstraintString()), + parseInjectedRefinementPredicates(input.model->getManager(), abstractionSettings.getInjectedRefinementPredicates())); + + verifyProperties(input, [&input, &options, &mpi](std::shared_ptr const& formula, + std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Abstraction-refinement can only filter initial states."); + return storm::gbar::api::verifyWithAbstractionRefinementEngine(mpi.env, input.model.get(), + storm::api::createTask(formula, true), options); + }); } template void verifyWithExplorationEngine(SymbolicInput const& input, ModelProcessingInformation const& mpi) { - if constexpr (storm::IsIntervalType) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Exploration engine does not support interval value types."); - } else { - STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); - STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, - "Exploration does not support other data-types than floating points."); - verifyProperties( - input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { - STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); - return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); - }); - } + STORM_LOG_ASSERT(input.model, "Expected symbolic model description."); + STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, + "Exploration does not support other data-types than floating points."); + verifyProperties( + input, [&input, &mpi](std::shared_ptr const& formula, std::shared_ptr const& states) { + STORM_LOG_THROW(states->isInitialFormula(), storm::exceptions::NotSupportedException, "Exploration can only filter initial states."); + return storm::api::verifyWithExplorationEngine(mpi.env, input.model.get(), storm::api::createTask(formula, true)); + }); } template diff --git a/src/storm-parsers/parser/DirectEncodingParser.cpp b/src/storm-parsers/parser/DirectEncodingParser.cpp index 8cdc5d0ef6..f8e1badbd0 100644 --- a/src/storm-parsers/parser/DirectEncodingParser.cpp +++ b/src/storm-parsers/parser/DirectEncodingParser.cpp @@ -9,6 +9,7 @@ #include "storm-parsers/parser/ValueParser.h" #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/exceptions/AbortException.h" @@ -87,6 +88,8 @@ bool isCompatibleValueType(DirectEncodingValueType fileValueType) { return fileValueType == Double || fileValueType == Rational; } else if constexpr (std::is_same_v) { return fileValueType == Double || fileValueType == Rational || fileValueType == DoubleInterval || fileValueType == RationalInterval; + } else if constexpr (std::is_same_v) { + return fileValueType == Double || fileValueType == Rational || fileValueType == DoubleInterval || fileValueType == RationalInterval; } else if constexpr (std::is_same_v) { return fileValueType == Double || fileValueType == Rational || fileValueType == Parametric; } else { @@ -581,6 +584,8 @@ template std::shared_ptr> pa std::filesystem::path const& file, DirectEncodingParserOptions const& options); template std::shared_ptr> parseDirectEncodingModel(std::filesystem::path const& file, DirectEncodingParserOptions const& options); +template std::shared_ptr> parseDirectEncodingModel( + std::filesystem::path const& file, DirectEncodingParserOptions const& options); template std::shared_ptr> parseDirectEncodingModel( std::filesystem::path const& file, DirectEncodingParserOptions const& options); diff --git a/src/storm/builder/ExplicitModelBuilder.cpp b/src/storm/builder/ExplicitModelBuilder.cpp index 4f7a195177..55dbcfdc8a 100644 --- a/src/storm/builder/ExplicitModelBuilder.cpp +++ b/src/storm/builder/ExplicitModelBuilder.cpp @@ -431,6 +431,7 @@ template class ExplicitModelBuilder, uint32_t>; template class ExplicitModelBuilder, uint32_t>; // TODO: where is this used? template class ExplicitModelBuilder, uint32_t>; +template class ExplicitModelBuilder, uint32_t>; } // namespace builder } // namespace storm diff --git a/src/storm/builder/RewardModelBuilder.cpp b/src/storm/builder/RewardModelBuilder.cpp index 6b01224047..d6681c99ad 100644 --- a/src/storm/builder/RewardModelBuilder.cpp +++ b/src/storm/builder/RewardModelBuilder.cpp @@ -66,6 +66,7 @@ template class RewardModelBuilder; template class RewardModelBuilder; template class RewardModelBuilder; template class RewardModelBuilder; +template class RewardModelBuilder; } // namespace builder } // namespace storm diff --git a/src/storm/generator/Choice.cpp b/src/storm/generator/Choice.cpp index 6350cb0d6d..a082330868 100644 --- a/src/storm/generator/Choice.cpp +++ b/src/storm/generator/Choice.cpp @@ -205,5 +205,6 @@ template struct Choice; template struct Choice; template struct Choice; template struct Choice; +template struct Choice; } // namespace generator } // namespace storm diff --git a/src/storm/generator/Distribution.cpp b/src/storm/generator/Distribution.cpp index 32969b24a3..8ef23fc3fb 100644 --- a/src/storm/generator/Distribution.cpp +++ b/src/storm/generator/Distribution.cpp @@ -129,10 +129,12 @@ template class Distribution; template class Distribution; template class Distribution; template class Distribution; +template class Distribution; template class Distribution; template class Distribution; template class Distribution; template class Distribution; +template class Distribution; } // namespace storm::generator diff --git a/src/storm/generator/DistributionEntry.cpp b/src/storm/generator/DistributionEntry.cpp index 1545afdc81..9c48bc39d5 100644 --- a/src/storm/generator/DistributionEntry.cpp +++ b/src/storm/generator/DistributionEntry.cpp @@ -1,4 +1,5 @@ #include "storm/generator/DistributionEntry.h" +#include #include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" @@ -41,10 +42,12 @@ template class DistributionEntry; template class DistributionEntry; template class DistributionEntry; template class DistributionEntry; +template class DistributionEntry; template class DistributionEntry; template class DistributionEntry; template class DistributionEntry; template class DistributionEntry; +template class DistributionEntry; } // namespace storm::generator diff --git a/src/storm/generator/NextStateGenerator.cpp b/src/storm/generator/NextStateGenerator.cpp index 4bb73c6394..aa3d1cf334 100644 --- a/src/storm/generator/NextStateGenerator.cpp +++ b/src/storm/generator/NextStateGenerator.cpp @@ -363,5 +363,9 @@ template class NextStateGenerator; template class ActionMask; template class StateValuationFunctionMask; template class NextStateGenerator; + +template class ActionMask; +template class StateValuationFunctionMask; +template class NextStateGenerator; } // namespace generator } // namespace storm diff --git a/src/storm/generator/PrismNextStateGenerator.cpp b/src/storm/generator/PrismNextStateGenerator.cpp index f9a7cd251a..e020c7d6f7 100644 --- a/src/storm/generator/PrismNextStateGenerator.cpp +++ b/src/storm/generator/PrismNextStateGenerator.cpp @@ -1100,5 +1100,6 @@ template class PrismNextStateGenerator; template class PrismNextStateGenerator; template class PrismNextStateGenerator; template class PrismNextStateGenerator; +template class PrismNextStateGenerator; } // namespace generator } // namespace storm diff --git a/src/storm/generator/StateBehavior.cpp b/src/storm/generator/StateBehavior.cpp index f09edce0e6..533a1d4a85 100644 --- a/src/storm/generator/StateBehavior.cpp +++ b/src/storm/generator/StateBehavior.cpp @@ -76,5 +76,6 @@ template class StateBehavior; template class StateBehavior; template class StateBehavior; template class StateBehavior; +template class StateBehavior; } // namespace generator } // namespace storm diff --git a/src/storm/modelchecker/AbstractModelChecker.cpp b/src/storm/modelchecker/AbstractModelChecker.cpp index 56664fcf2a..1a02acc28e 100644 --- a/src/storm/modelchecker/AbstractModelChecker.cpp +++ b/src/storm/modelchecker/AbstractModelChecker.cpp @@ -495,6 +495,7 @@ template class AbstractModelChecker> template class AbstractModelChecker>; template class AbstractModelChecker>; +template class AbstractModelChecker>; // DD template class AbstractModelChecker>; diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index e54a69b4ef..e5ee8b3c78 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -141,7 +141,7 @@ template std::unique_ptr SparseDtmcPrctlModelChecker::computeUntilProbabilities( Environment const& env, CheckTask const& checkTask) { storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); - if (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(checkTask.isUncertaintyResolutionModeSet(), storm::exceptions::InvalidSettingsException, "Uncertainty resolution mode must be set for uncertain (interval) models."); STORM_LOG_THROW(checkTask.getUncertaintyResolutionMode() != UncertaintyResolutionMode::Robust && @@ -297,7 +297,7 @@ template std::unique_ptr SparseDtmcPrctlModelChecker::computeReachabilityRewards( Environment const& env, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); - if (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(checkTask.isUncertaintyResolutionModeSet(), storm::exceptions::InvalidSettingsException, "Uncertainty resolution mode must be set for uncertain (interval) models."); STORM_LOG_THROW(checkTask.getUncertaintyResolutionMode() != UncertaintyResolutionMode::Robust && @@ -537,5 +537,6 @@ template class SparseDtmcPrctlModelChecker>; template class SparseDtmcPrctlModelChecker>; template class SparseDtmcPrctlModelChecker>; template class SparseDtmcPrctlModelChecker>; +template class SparseDtmcPrctlModelChecker>; } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h index 6372205cdc..551b6a48cc 100644 --- a/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h +++ b/src/storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h @@ -1,5 +1,6 @@ #pragma once +#include "storm/adapters/IntervalForward.h" #include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "storm/models/sparse/Dtmc.h" @@ -11,7 +12,7 @@ class SparseDtmcPrctlModelChecker : public SparsePropositionalModelChecker, double, ValueType>::type; + using SolutionType = storm::IntervalBaseType; explicit SparseDtmcPrctlModelChecker(SparseDtmcModelType const& model); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index a562790211..a17ca029dc 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -1,6 +1,7 @@ #include "storm/modelchecker/prctl/SparseMdpPrctlModelChecker.h" #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/exceptions/InvalidPropertyException.h" @@ -291,6 +292,9 @@ std::unique_ptr SparseMdpPrctlModelChecker::com template std::unique_ptr SparseMdpPrctlModelChecker::computeCumulativeRewards( Environment const& env, CheckTask const& checkTask) { + if constexpr (storm::IsIntervalType) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Cumulative reward properties are not implemented for interval models."); + } storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); @@ -325,6 +329,12 @@ std::unique_ptr SparseMdpPrctlModelChecker +std::unique_ptr SparseMdpPrctlModelChecker>::computeDiscountedCumulativeRewards( + Environment const& env, CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Discounted properties are not implemented for interval models."); +} + template std::unique_ptr SparseMdpPrctlModelChecker::computeDiscountedCumulativeRewards( Environment const& env, CheckTask const& checkTask) { @@ -414,6 +424,12 @@ std::unique_ptr SparseMdpPrctlModelChecker +std::unique_ptr SparseMdpPrctlModelChecker>::computeDiscountedTotalRewards( + Environment const& env, CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Discounted properties are not implemented for interval models."); +} + template std::unique_ptr SparseMdpPrctlModelChecker::computeDiscountedTotalRewards( Environment const& env, CheckTask const& checkTask) { diff --git a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp index a8c6153e06..ba0bd28c3a 100644 --- a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp @@ -939,6 +939,7 @@ template class SparseDtmcPrctlHelper; template class SparseDtmcPrctlHelper; template class SparseDtmcPrctlHelper; template class SparseDtmcPrctlHelper, double>; +template class SparseDtmcPrctlHelper, storm::RationalNumber>; } // namespace helper } // namespace modelchecker } // namespace storm diff --git a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp index 552122bbc2..6f3533e6a8 100644 --- a/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp +++ b/src/storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.cpp @@ -964,8 +964,6 @@ template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; template class MultiDimensionalRewardUnfolding; -// template class MultiDimensionalRewardUnfolding; -// template class MultiDimensionalRewardUnfolding; } // namespace rewardbounded } // namespace helper } // namespace modelchecker diff --git a/src/storm/solver/helper/SchedulerTrackingHelper.cpp b/src/storm/solver/helper/SchedulerTrackingHelper.cpp index 0a296626c1..478866794e 100644 --- a/src/storm/solver/helper/SchedulerTrackingHelper.cpp +++ b/src/storm/solver/helper/SchedulerTrackingHelper.cpp @@ -108,7 +108,7 @@ bool SchedulerTrackingHelper::compu std::vector& schedulerStorage, UncertaintyResolutionMode uncertaintyResolutionMode, std::vector* operandOut, boost::optional> const& robustIndices) const { bool robustUncertainty = false; - if (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { robustUncertainty = isUncertaintyResolvedRobust(uncertaintyResolutionMode, dir); } diff --git a/src/storm/solver/helper/ValueIterationHelper.cpp b/src/storm/solver/helper/ValueIterationHelper.cpp index 72e6918851..512a25b3db 100644 --- a/src/storm/solver/helper/ValueIterationHelper.cpp +++ b/src/storm/solver/helper/ValueIterationHelper.cpp @@ -108,7 +108,7 @@ SolverStatus ValueIterationHelper:: MultiplicationStyle mult, UncertaintyResolutionMode const& uncertaintyResolutionMode) const { bool robustUncertainty = false; - if (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { robustUncertainty = isUncertaintyResolvedRobust(uncertaintyResolutionMode, Dir); } @@ -126,7 +126,7 @@ SolverStatus ValueIterationHelper:: std::function const& iterationCallback, MultiplicationStyle mult, UncertaintyResolutionMode const& uncertaintyResolutionMode) const { - if (storm::IsIntervalType) { + if constexpr (storm::IsIntervalType) { STORM_LOG_THROW(uncertaintyResolutionMode != UncertaintyResolutionMode::Unset, storm::exceptions::IllegalFunctionCallException, "Uncertainty resolution mode must be set for uncertain (interval) models."); STORM_LOG_THROW(dir.has_value() || (uncertaintyResolutionMode != UncertaintyResolutionMode::Robust && diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index 44dbc87aa0..4f352705e3 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -3,6 +3,7 @@ #include #include "storm/adapters/IntervalAdapter.h" +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/storage/BitVector.h" #include "storm/storage/SparseMatrix.h" @@ -33,7 +34,7 @@ void ValueIterationOperator::setMat matrixColumns.reserve(matrix.getNonzeroEntryCount() + numRows + 1); // matrixColumns also contain indications for when a row(group) starts // hasOnlyConstants is only used for Interval matrices, currently only populated for iMCs - if constexpr (std::is_same::value) { + if constexpr (storm::IsIntervalType) { applyCache.hasOnlyConstants.clear(); applyCache.hasOnlyConstants.grow(matrix.getRowCount()); } diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index a571208c97..f8102f9bc5 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -8,6 +8,7 @@ #include "storm/models/sparse/Mdp.h" #include "storm/models/sparse/StandardRewardModel.h" #include "storm/storage/SparseMatrix.h" +#include "storm/utility/constants.h" #include "storm/utility/macros.h" #include "storm/utility/vector.h" @@ -17,11 +18,11 @@ template AddUncertainty::AddUncertainty(std::shared_ptr> const& originalModel) : origModel(originalModel) {} template -std::shared_ptr> AddUncertainty::transform(double additiveUncertainty, double minimalTransitionProbability, - uint64_t maxSuccessors) { +std::shared_ptr::IntervalType>> AddUncertainty::transform( + double additiveUncertainty, double minimalTransitionProbability, uint64_t maxSuccessors) { // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = - storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), + storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { @@ -35,24 +36,24 @@ std::shared_ptr> AddUncertainty modelComponents(newMatrixBuilder.build(), origModel->getStateLabeling()); + storm::storage::sparse::ModelComponents modelComponents(newMatrixBuilder.build(), origModel->getStateLabeling()); if (!origModel->getTransitionMatrix().hasTrivialRowGrouping()) { modelComponents.transitionMatrix.setRowGroupIndices(origModel->getTransitionMatrix().getRowGroupIndices()); } // Change value type of standard reward model. - std::unordered_map> newRewardModels; + std::unordered_map> newRewardModels; for (auto const& rewModel : origModel->getRewardModels()) { auto const& oldRewModel = rewModel.second; - std::optional> stateRewards; - std::optional> stateActionRewards; + std::optional> stateRewards; + std::optional> stateActionRewards; if (oldRewModel.hasStateRewards()) { - stateRewards = utility::vector::convertNumericVector(oldRewModel.getStateRewardVector()); + stateRewards = utility::vector::convertNumericVector(oldRewModel.getStateRewardVector()); } if (oldRewModel.hasStateActionRewards()) { - stateActionRewards = utility::vector::convertNumericVector(oldRewModel.getStateActionRewardVector()); + stateActionRewards = utility::vector::convertNumericVector(oldRewModel.getStateActionRewardVector()); } STORM_LOG_THROW(!oldRewModel.hasTransitionRewards(), exceptions::NotImplementedException, "Transition rewards are not supported."); - models::sparse::StandardRewardModel newRewModel(std::move(stateRewards), std::move(stateActionRewards)); + models::sparse::StandardRewardModel newRewModel(std::move(stateRewards), std::move(stateActionRewards)); newRewardModels.emplace(rewModel.first, std::move(newRewModel)); } @@ -64,26 +65,29 @@ std::shared_ptr> AddUncertaintygetType()) { case storm::models::ModelType::Dtmc: - return std::make_shared>(std::move(modelComponents)); + return std::make_shared>(std::move(modelComponents)); case storm::models::ModelType::Mdp: - return std::make_shared>(std::move(modelComponents)); + return std::make_shared>(std::move(modelComponents)); default: STORM_LOG_THROW(false, exceptions::NotImplementedException, "Only DTMC and MDP model types are currently supported."); } } template -storm::Interval AddUncertainty::addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue) { +typename AddUncertainty::IntervalType AddUncertainty::addUncertainty(ValueType const& vt, double additiveUncertainty, + double minimalValue) { if (utility::isOne(vt)) { - return storm::Interval(1.0, 1.0); + return IntervalType(storm::utility::one(), storm::utility::one()); } - double center = storm::utility::convertNumber(vt); - STORM_LOG_THROW(center >= minimalValue, storm::exceptions::InvalidArgumentException, "Transition probability is smaller than minimal value"); - double lowerBound = std::max(center - additiveUncertainty, minimalValue); - double upperBound = std::min(center + additiveUncertainty, 1.0 - minimalValue); - STORM_LOG_ASSERT(lowerBound > 0, "Lower bound must be strictly above zero."); - STORM_LOG_ASSERT(upperBound < 1, "Upper bound must be strictly below one."); - return storm::Interval(lowerBound, upperBound); + ValueType const center = vt; + ValueType const uncertainty = storm::utility::convertNumber(additiveUncertainty); + ValueType const minVal = storm::utility::convertNumber(minimalValue); + STORM_LOG_THROW(center >= minVal, storm::exceptions::InvalidArgumentException, "Transition probability is smaller than minimal value"); + ValueType const lowerBound = storm::utility::max(center - uncertainty, minVal); + ValueType const upperBound = storm::utility::min(center + uncertainty, storm::utility::one() - minVal); + STORM_LOG_ASSERT(storm::utility::isPositive(lowerBound), "Lower bound must be strictly above zero."); + STORM_LOG_ASSERT(upperBound < storm::utility::one(), "Upper bound must be strictly below one."); + return IntervalType(lowerBound, upperBound); } template class AddUncertainty; diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index 7e0ae97986..d3421dc7a2 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -1,6 +1,9 @@ #pragma once +#include + #include "storm/adapters/IntervalForward.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/models/sparse/Model.h" namespace storm::transformer { @@ -10,17 +13,22 @@ namespace storm::transformer { * We currently support only one type of self-defined uncertainty, although additional types of uncertainty are imaginable. * The transformer does maintain reward models, state labels, state valuations, choice labels and choice origins. * - * @tparam ValueType + * When ValueType is storm::RationalNumber the output model uses storm::RationalInterval (exact arithmetic). + * For all other ValueTypes (e.g. double) the output uses storm::Interval (double-precision). + * + * @tparam ValueType The value type of the input model. */ template class AddUncertainty { public: + using IntervalType = std::conditional_t, storm::RationalInterval, storm::Interval>; + AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, - uint64_t maxSuccessors = 10000000); + std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, + uint64_t maxSuccessors = 10000000); private: - storm::Interval addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); + IntervalType addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); std::shared_ptr> origModel; }; diff --git a/src/storm/utility/constants.cpp b/src/storm/utility/constants.cpp index 0e32f2187e..ee928fb062 100644 --- a/src/storm/utility/constants.cpp +++ b/src/storm/utility/constants.cpp @@ -1019,6 +1019,11 @@ storm::RationalInterval convertNumber(double const& number) { return storm::RationalInterval(convertNumber(number)); } +template<> +storm::RationalInterval convertNumber(uint64_t const& number) { + return storm::RationalInterval(convertNumber(number)); +} + #if defined(STORM_HAVE_GMP) template<> storm::Interval convertNumber(storm::GmpRationalNumber const& n) { @@ -1091,6 +1096,13 @@ bool isApproxEqual(storm::Interval const& a, storm::Interval const& b, storm::In isApproxEqual(a.upper(), b.upper(), precision.center(), relative); } +template<> +bool isApproxEqual(storm::RationalInterval const& a, storm::RationalInterval const& b, storm::RationalInterval const& precision, bool relative) { + STORM_LOG_ASSERT(precision.isPointInterval(), "Precision must be a point interval"); + return isApproxEqual(a.lower(), b.lower(), precision.center(), relative) && + isApproxEqual(a.upper(), b.upper(), precision.center(), relative); +} + template<> storm::RationalInterval abs(storm::RationalInterval const& interval) { return interval.abs(); @@ -1269,6 +1281,9 @@ template bool isOne(RationalInterval const& value); template bool isZero(RationalInterval const& value); template bool isInfinity(RationalInterval const& value); template bool isAlmostZero(RationalInterval const& value); +template bool isNonNegative(RationalInterval const& value); +template bool isPositive(RationalInterval const& value); +template bool isBetween(RationalInterval const&, RationalInterval const&, RationalInterval const& value, bool); template std::string to_string(storm::RationalInterval const& value); } // namespace utility diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 2cb9f531a3..f08c7c3fb8 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -1,5 +1,6 @@ #include "storm-config.h" #include "storm/adapters/IntervalForward.h" +#include "storm/adapters/RationalNumberForward.h" #include "test/storm_gtest.h" #include "storm-parsers/api/model_descriptions.h" @@ -14,6 +15,7 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "storm/transformer/AddUncertainty.h" +#include "storm/utility/constants.h" std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { @@ -153,6 +155,133 @@ void checkModelForQualitativeResult(std::string const& path, std::string const& } } +std::unique_ptr getInitialStateFilter( + std::shared_ptr> const& model) { + return std::make_unique>(model->getInitialStates()); +} + +storm::RationalNumber getQuantitativeResultAtInitialState(std::shared_ptr> const& model, + std::unique_ptr& result) { + auto filter = getInitialStateFilter(model); + result->filter(*filter); + return result->asQuantitativeCheckResult().getMin(); +} + +std::unique_ptr getInitialStateFilter( + std::shared_ptr> const& model) { + return std::make_unique>(model->getInitialStates()); +} + +storm::RationalNumber getQuantitativeResultAtInitialState(std::shared_ptr> const& model, + std::unique_ptr& result) { + auto filter = getInitialStateFilter(model); + result->filter(*filter); + return result->asQuantitativeCheckResult().getMin(); +} + +void expectThrowRational(std::string const& path, std::string const& formulaString, + std::optional uncertaintyResolutionMode = std::nullopt) { + std::shared_ptr> modelPtr = storm::parser::parseDirectEncodingModel(path); + + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); + + storm::Environment env; + env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + + std::shared_ptr> dtmc = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType()); + auto task = storm::modelchecker::CheckTask(*formulas[0]); + if (uncertaintyResolutionMode.has_value()) { + task.setUncertaintyResolutionMode(uncertaintyResolutionMode.value()); + } + + auto checker = storm::modelchecker::SparseDtmcPrctlModelChecker>(*dtmc); + STORM_SILENT_EXPECT_THROW(checker.check(env, task), storm::exceptions::BaseException); +} + +void checkExplicitModelForQuantitativeResultRational(std::string const& path, std::string const& formulaString, storm::RationalNumber min, + storm::RationalNumber max) { + std::shared_ptr> modelPtr = storm::parser::parseDirectEncodingModel(path); + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); + storm::Environment env; + env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + + std::shared_ptr> dtmc = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType()); + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Maximize); + + auto checker = storm::modelchecker::SparseDtmcPrctlModelChecker>(*dtmc); + auto resultMax = checker.check(env, taskMax); + EXPECT_EQ(max, getQuantitativeResultAtInitialState(dtmc, resultMax)); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[1]); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Minimize); + + auto resultMin = checker.check(env, taskMin); + EXPECT_EQ(min, getQuantitativeResultAtInitialState(dtmc, resultMin)); +} + +void checkPrismModelForQuantitativeResultRational(std::string const& path, std::string const& formulaString, storm::RationalNumber min, + storm::RationalNumber max) { + storm::prism::Program program = storm::api::parseProgram(path); + program = storm::utility::prism::preprocess(program, ""); + + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); + std::shared_ptr> modelPtr = storm::api::buildSparseModel(program, formulas); + + storm::Environment env; + env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + + std::shared_ptr> dtmc = modelPtr->as>(); + ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType()); + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Maximize); + + auto checker = storm::modelchecker::SparseDtmcPrctlModelChecker>(*dtmc); + auto resultMax = checker.check(env, taskMax); + EXPECT_EQ(max, getQuantitativeResultAtInitialState(dtmc, resultMax)); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[1]); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Minimize); + + auto resultMin = checker.check(env, taskMin); + EXPECT_EQ(min, getQuantitativeResultAtInitialState(dtmc, resultMin)); +} + +void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, double amountOfUncertainty) { + storm::prism::Program program = storm::api::parseProgram(path); + program = storm::utility::prism::preprocess(program, ""); + std::vector> formulas = + storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulaString, program)); + std::shared_ptr> modelPtr = storm::api::buildSparseModel(program, formulas); + auto dtmc = modelPtr->as>(); + + storm::Environment env; + auto taskCertain = storm::modelchecker::CheckTask(*formulas[0]); + auto checker = storm::modelchecker::SparseDtmcPrctlModelChecker>(*dtmc); + auto exresult = checker.check(env, taskCertain); + storm::RationalNumber certainValue = getQuantitativeResultAtInitialState(modelPtr, exresult); + + storm::Environment envIntervals; + envIntervals.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + auto transformer = storm::transformer::AddUncertainty(modelPtr); + auto idtmc = transformer.transform(amountOfUncertainty)->as>(); + auto ichecker = storm::modelchecker::SparseDtmcPrctlModelChecker>(*idtmc); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[0]); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Minimize); + auto iresultMin = ichecker.check(envIntervals, taskMin); + storm::RationalNumber minValue = getQuantitativeResultAtInitialState(idtmc, iresultMin); + EXPECT_LE(minValue, certainValue); + + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Maximize); + auto iresultMax = ichecker.check(envIntervals, taskMax); + storm::RationalNumber maxValue = getQuantitativeResultAtInitialState(idtmc, iresultMax); + EXPECT_LE(certainValue, maxValue); +} + TEST(RobustDtmcModelCheckerTest, Tiny01ReachMaxMinProbs) { // Maximal Reachability probabilities using explicit format. checkExplicitModelForQuantitativeResult(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-01.drn", "P=? [ F \"target\"];P=? [ F \"target\"]", 0.3, 0.5); @@ -228,3 +357,83 @@ TEST(RobustDtmcModelCheckerTest, TinyO2Propositional) { checkModelForQualitativeResult(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-02.drn", "\"target\";!\"target\"", expectedResults); } + +// ---- RationalInterval tests (exact arithmetic) ---- + +TEST(RobustRationalDtmcModelCheckerTest, Tiny01ReachMaxMinProbs) { + checkExplicitModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-01.drn", "P=? [ F \"target\"];P=? [ F \"target\"]", + storm::RationalNumber(3, 10), storm::RationalNumber(1, 2)); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny01MaxReachProbNoUncertaintyResolutionMode) { + expectThrowRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-01.drn", "P=? [ F \"target\"];", + std::make_optional(storm::UncertaintyResolutionMode::Unset)); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny01MaxReachProbNoOptimizationDirectionButRobust) { + expectThrowRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-01.drn", "P=? [ F \"target\"];", + std::make_optional(storm::UncertaintyResolutionMode::Robust)); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny02GloballyMaxMinProbs) { + expectThrowRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-02.drn", "P=? [ G \"target\"];P=? [ G \"target\"]"); +} + +TEST(RobustRationalDtmcModelCheckerTest, DieIntervalsMaxMin) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + checkPrismModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/die-intervals.pm", "P=? [ F \"one\"];P=? [ F \"one\"]", + storm::RationalNumber(4483008223, 94143178827), storm::RationalNumber(35864065784, 94143178827)); +} + +TEST(RobustRationalDtmcModelCheckerTest, BrpIntervalsMaxMin) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + checkPrismModelForQuantitativeResultRational( + STORM_TEST_RESOURCES_DIR "/idtmc/brp-32-2-intervals.pm", "P=? [ F \"error\" ];P=? [ F \"error\" ]", + // The number is to large to be represented as a literal, so we construct it from strings. + storm::RationalNumber("10238464074071514998168131748974289312176706851339248682605279417683104172439385084862067764341447739354976890683145110072150529" + "29484271217452553595194641992099205093706027267658909966207049695357884534755950707204946503657943965652247014748702342577938440" + "579441829932769922685028147340905022682454110960938051" + "/" + "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000"), + storm::RationalNumber("73421101667166357614487085157865792442422423664718103404519649530149236548299533815461648662459394997073289369183682645650367121" + "4626220291672876565353557862092334897" + "/" + "86736173798840354720596224069595336914062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000")); +} + +TEST(RobustRationalDtmcModelCheckerTest, DieIntervalsMaxMinRewards) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + checkPrismModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/die-intervals.pm", "R=? [ F \"done\"];R=? [ F \"done\"]", + storm::RationalNumber(15544649, 4782969), storm::RationalNumber(76715008330675523, 16677181699666569)); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny03MaxMinRewards) { + checkExplicitModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-03.drn", "R=? [ F \"target\"];R=? [ F \"target\"]", + storm::RationalNumber(13, 2), storm::RationalNumber(17, 2)); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny03RewardsNoUncertaintyResolutionMode) { + expectThrowRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-03.drn", "R=? [ F \"target\"]", storm::UncertaintyResolutionMode::Unset); +} + +TEST(RobustRationalDtmcModelCheckerTest, Tiny04MaxMinRewards) { + checkExplicitModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-04.drn", "R=? [ F \"target\"];R=? [ F \"target\"]", + storm::utility::infinity(), storm::utility::infinity()); +} + +TEST(RobustRationalDtmcModelCheckerTest, AddUncertaintyBrpMax) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", 0.01); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", 0.05); +} diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 46e9b8e9b6..c1e3a71cdd 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -27,9 +27,21 @@ std::unique_ptr getInitialStateFilt return std::make_unique>(model->getInitialStates()); } +std::unique_ptr getInitialStateFilter( + std::shared_ptr> const& model) { + return std::make_unique>(model->getInitialStates()); +} + +storm::RationalNumber getQuantitativeResultAtInitialState(std::shared_ptr> const& model, + std::unique_ptr& result) { + auto filter = getInitialStateFilter(model); + result->filter(*filter); + return result->asQuantitativeCheckResult().getMin(); +} + std::unique_ptr getInitialStateFilter( std::shared_ptr> const& model) { - return std::make_unique(model->getInitialStates()); + return std::make_unique>(model->getInitialStates()); } double getQuantitativeResultAtInitialState(std::shared_ptr> const& model, @@ -140,8 +152,8 @@ void checkPrismModelForQuantitativeResult(std::string const& path, std::string c void checkModelRational(std::string const& path, std::string const& formulaString, storm::RationalNumber maxmin, storm::RationalNumber maxmax, storm::RationalNumber minmax, storm::RationalNumber minmin, bool produceScheduler) { - std::shared_ptr> modelPtr = - storm::parser::DirectEncodingParser::parseModel(path); + std::shared_ptr> modelPtr = storm::parser::parseDirectEncodingModel(path); + std::vector> formulas = storm::api::extractFormulasFromProperties(storm::api::parseProperties(formulaString)); storm::Environment env; env.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); @@ -152,18 +164,20 @@ void checkModelRational(std::string const& path, std::string const& formulaStrin taskMax.setProduceSchedulers(produceScheduler); auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Robust); auto resultMax = checker.check(env, taskMax); EXPECT_EQ(maxmin, getQuantitativeResultAtInitialState(mdp, resultMax)); - taskMax.setRobustUncertainty(false); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Cooperative); auto resultMaxNonRobust = checker.check(env, taskMax); EXPECT_EQ(maxmax, getQuantitativeResultAtInitialState(mdp, resultMaxNonRobust)); auto taskMin = storm::modelchecker::CheckTask(*formulas[1]); taskMin.setProduceSchedulers(produceScheduler); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Robust); auto resultMin = checker.check(env, taskMin); EXPECT_EQ(minmax, getQuantitativeResultAtInitialState(mdp, resultMin)); - taskMin.setRobustUncertainty(false); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Cooperative); auto resultMinNonRobust = checker.check(env, taskMin); EXPECT_EQ(minmin, getQuantitativeResultAtInitialState(mdp, resultMinNonRobust)); } @@ -212,6 +226,42 @@ void makeUncertainAndCheck(std::string const& path, std::string const& formulaSt EXPECT_LE(certainValue, maxValue); } +void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, double amountOfUncertainty) { + storm::prism::Program program = storm::api::parseProgram(path); + program = storm::utility::prism::preprocess(program, ""); + std::vector> formulas = + storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulaString, program)); + std::shared_ptr> modelPtr = storm::api::buildSparseModel(program, formulas); + auto mdp = modelPtr->as>(); + + ASSERT_TRUE(formulas[0]->isProbabilityOperatorFormula()); + ASSERT_TRUE(formulas[0]->asProbabilityOperatorFormula().getOptimalityType() == storm::solver::OptimizationDirection::Maximize); + + storm::Environment env; + auto taskCertain = storm::modelchecker::CheckTask(*formulas[0]); + auto checker = storm::modelchecker::SparseMdpPrctlModelChecker>(*mdp); + auto exresult = checker.check(env, taskCertain); + storm::RationalNumber certainValue = getQuantitativeResultAtInitialState(modelPtr, exresult); + + storm::Environment envIntervals; + envIntervals.solver().minMax().setMethod(storm::solver::MinMaxMethod::ValueIteration); + auto transformer = storm::transformer::AddUncertainty(modelPtr); + auto imdp = transformer.transform(amountOfUncertainty)->as>(); + auto ichecker = storm::modelchecker::SparseMdpPrctlModelChecker>(*imdp); + + auto taskMin = storm::modelchecker::CheckTask(*formulas[0]); + taskMin.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Minimize); + auto iresultMin = ichecker.check(envIntervals, taskMin); + storm::RationalNumber minValue = getQuantitativeResultAtInitialState(imdp, iresultMin); + EXPECT_LE(minValue, certainValue); + + auto taskMax = storm::modelchecker::CheckTask(*formulas[0]); + taskMax.setUncertaintyResolutionMode(storm::UncertaintyResolutionMode::Maximize); + auto iresultMax = ichecker.check(envIntervals, taskMax); + storm::RationalNumber maxValue = getQuantitativeResultAtInitialState(imdp, iresultMax); + EXPECT_LE(certainValue, maxValue); +} + TEST(RobustMDPModelCheckingTest, Tiny01maxmin) { checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-01.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", 0.4, 0.5, 0.5, 0.4, false); } @@ -221,9 +271,9 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.5, 0.5, 0.5, 0.5, true); - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(1, 2), - storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.4, 0.4, 0.5, 0.5, true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(2, 5), + storm::RationalNumber(2, 5), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { @@ -238,6 +288,34 @@ TEST(RobustMDPModelCheckingTest, Tiny04maxmin_rewards) { expectThrow(STORM_TEST_RESOURCES_DIR "/imdp/tiny-04.drn", "Rmin=? [ F \"target\"]"); } +// ---- RationalInterval tests (exact arithmetic) ---- + +TEST(RobustRationalMDPModelCheckingTest, Tiny01maxmin) { + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-01.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(2, 5), + storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(2, 5), false); +} + +TEST(RobustRationalMDPModelCheckingTest, Tiny03maxmin) { + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(2, 5), + storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(2, 5), true); +} + +TEST(RobustRationalMDPModelCheckingTest, BoundedTiny03maxmin) { + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(2, 5), + storm::RationalNumber(2, 5), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); +} + +TEST(RobustRationalMDPModelCheckingTest, Tiny04maxmin) { + // Fill in exact rational values once test output is known. + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-04.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(1), + storm::RationalNumber(1), storm::RationalNumber(42857140807299, 100000000000000), storm::RationalNumber(21, 50), false); +} + +TEST(RobustRationalMDPModelCheckingTest, Tiny05maxmin) { + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-05.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(3, 10), + storm::RationalNumber(2, 5), storm::RationalNumber(2, 5), storm::RationalNumber(3, 10), false); +} + TEST(RobustMDPModelCheckingTest, AddUncertaintyCoin22max) { #ifndef STORM_HAVE_Z3 GTEST_SKIP() << "Z3 not available."; @@ -245,3 +323,11 @@ TEST(RobustMDPModelCheckingTest, AddUncertaintyCoin22max) { makeUncertainAndCheck(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.1); makeUncertainAndCheck(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.2); } + +TEST(RobustRationalMDPModelCheckingTest, AddUncertaintyCoin22max) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.1); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.2); +} diff --git a/src/test/storm/transformer/AddUncertaintyTest.cpp b/src/test/storm/transformer/AddUncertaintyTest.cpp index 1911aba39d..300b788d9b 100644 --- a/src/test/storm/transformer/AddUncertaintyTest.cpp +++ b/src/test/storm/transformer/AddUncertaintyTest.cpp @@ -3,6 +3,7 @@ #include "storm-parsers/api/storm-parsers.h" #include "storm-parsers/parser/PrismParser.h" +#include "storm/adapters/RationalNumberForward.h" #include "storm/api/storm.h" #include "storm/transformer/AddUncertainty.h" @@ -37,3 +38,35 @@ TEST(AddUncertaintyTransformerTest, Coin22Test) { EXPECT_EQ(uncertainModel->getNumberOfTransitions(), model->getNumberOfTransitions()); EXPECT_TRUE(uncertainModel->hasUncertainty()); } + +TEST(AddUncertaintyTransformerTest, BrpTestRational) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + storm::prism::Program program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm"); + std::string formulasString = "P=? [ F \"target\"]"; + auto formulas = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasString, program)); + auto model = storm::api::buildSparseModel(program, formulas); + + auto transformer = storm::transformer::AddUncertainty(model); + auto uncertainModel = transformer.transform(0.01); + EXPECT_EQ(uncertainModel->getNumberOfStates(), model->getNumberOfStates()); + EXPECT_EQ(uncertainModel->getNumberOfTransitions(), model->getNumberOfTransitions()); + EXPECT_TRUE(uncertainModel->hasUncertainty()); +} + +TEST(AddUncertaintyTransformerTest, Coin22TestRational) { +#ifndef STORM_HAVE_Z3 + GTEST_SKIP() << "Z3 not available."; +#endif + storm::prism::Program program = storm::parser::PrismParser::parse(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm"); + std::string formulasString = "Pmax=? [ F \"all_coins_equal_1\"]"; + auto formulas = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasString, program)); + auto model = storm::api::buildSparseModel(program, formulas); + + auto transformer = storm::transformer::AddUncertainty(model); + auto uncertainModel = transformer.transform(0.01); + EXPECT_EQ(uncertainModel->getNumberOfStates(), model->getNumberOfStates()); + EXPECT_EQ(uncertainModel->getNumberOfTransitions(), model->getNumberOfTransitions()); + EXPECT_TRUE(uncertainModel->hasUncertainty()); +} From 3b7de9611b8bdd8b6d470e200a16ef29ceea059d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 11 Mar 2026 16:56:01 +0100 Subject: [PATCH 17/27] format --- src/storm/transformer/AddUncertainty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index f8102f9bc5..98d746d7cc 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -23,7 +23,7 @@ std::shared_ptr: // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), - origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); + origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { From 9e7d03eef14fc30916a145ed345048709314ac34 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 11 Mar 2026 17:22:18 +0100 Subject: [PATCH 18/27] write ration numbers using string for cln --- .../dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 8 +++---- .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 22 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index f08c7c3fb8..156c529f56 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -362,7 +362,7 @@ TEST(RobustDtmcModelCheckerTest, TinyO2Propositional) { TEST(RobustRationalDtmcModelCheckerTest, Tiny01ReachMaxMinProbs) { checkExplicitModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-01.drn", "P=? [ F \"target\"];P=? [ F \"target\"]", - storm::RationalNumber(3, 10), storm::RationalNumber(1, 2)); + storm::RationalNumber("3/10"), storm::RationalNumber("1/2")); } TEST(RobustRationalDtmcModelCheckerTest, Tiny01MaxReachProbNoUncertaintyResolutionMode) { @@ -384,7 +384,7 @@ TEST(RobustRationalDtmcModelCheckerTest, DieIntervalsMaxMin) { GTEST_SKIP() << "Z3 not available."; #endif checkPrismModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/die-intervals.pm", "P=? [ F \"one\"];P=? [ F \"one\"]", - storm::RationalNumber(4483008223, 94143178827), storm::RationalNumber(35864065784, 94143178827)); + storm::RationalNumber("4483008223/94143178827"), storm::RationalNumber("35864065784/94143178827")); } TEST(RobustRationalDtmcModelCheckerTest, BrpIntervalsMaxMin) { @@ -413,12 +413,12 @@ TEST(RobustRationalDtmcModelCheckerTest, DieIntervalsMaxMinRewards) { GTEST_SKIP() << "Z3 not available."; #endif checkPrismModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/die-intervals.pm", "R=? [ F \"done\"];R=? [ F \"done\"]", - storm::RationalNumber(15544649, 4782969), storm::RationalNumber(76715008330675523, 16677181699666569)); + storm::RationalNumber("15544649/4782969"), storm::RationalNumber("76715008330675523/16677181699666569")); } TEST(RobustRationalDtmcModelCheckerTest, Tiny03MaxMinRewards) { checkExplicitModelForQuantitativeResultRational(STORM_TEST_RESOURCES_DIR "/idtmc/tiny-03.drn", "R=? [ F \"target\"];R=? [ F \"target\"]", - storm::RationalNumber(13, 2), storm::RationalNumber(17, 2)); + storm::RationalNumber("13/2"), storm::RationalNumber("17/2")); } TEST(RobustRationalDtmcModelCheckerTest, Tiny03RewardsNoUncertaintyResolutionMode) { diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index c1e3a71cdd..84216e7928 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -272,8 +272,8 @@ TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.4, 0.4, 0.5, 0.5, true); - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(2, 5), - storm::RationalNumber(2, 5), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber("2/5"), + storm::RationalNumber("2/5"), storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { @@ -291,29 +291,29 @@ TEST(RobustMDPModelCheckingTest, Tiny04maxmin_rewards) { // ---- RationalInterval tests (exact arithmetic) ---- TEST(RobustRationalMDPModelCheckingTest, Tiny01maxmin) { - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-01.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(2, 5), - storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(2, 5), false); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-01.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber("2/5"), + storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), storm::RationalNumber("2/5"), false); } TEST(RobustRationalMDPModelCheckingTest, Tiny03maxmin) { - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(2, 5), - storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), storm::RationalNumber(2, 5), true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber("2/5"), + storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), storm::RationalNumber("2/5"), true); } TEST(RobustRationalMDPModelCheckingTest, BoundedTiny03maxmin) { - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber(2, 5), - storm::RationalNumber(2, 5), storm::RationalNumber(1, 2), storm::RationalNumber(1, 2), true); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber("2/5"), + storm::RationalNumber("2/5"), storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), true); } TEST(RobustRationalMDPModelCheckingTest, Tiny04maxmin) { // Fill in exact rational values once test output is known. checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-04.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(1), - storm::RationalNumber(1), storm::RationalNumber(42857140807299, 100000000000000), storm::RationalNumber(21, 50), false); + storm::RationalNumber(1), storm::RationalNumber("42857140807299/100000000000000"), storm::RationalNumber("21/50"), false); } TEST(RobustRationalMDPModelCheckingTest, Tiny05maxmin) { - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-05.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber(3, 10), - storm::RationalNumber(2, 5), storm::RationalNumber(2, 5), storm::RationalNumber(3, 10), false); + checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-05.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber("3/10"), + storm::RationalNumber("2/5"), storm::RationalNumber("2/5"), storm::RationalNumber("3/10"), false); } TEST(RobustMDPModelCheckingTest, AddUncertaintyCoin22max) { From 21411c71c0ef7da5cfcab15402849094f240bc37 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 11:46:35 +0100 Subject: [PATCH 19/27] Refactor AddUncertainty transformer to use ValueType for uncertainty parameters and update tests accordingly --- src/storm/transformer/AddUncertainty.cpp | 19 ++++++++----------- src/storm/transformer/AddUncertainty.h | 8 ++++---- src/storm/utility/NumberTraits.h | 4 ++-- .../storm/transformer/AddUncertaintyTest.cpp | 4 ++-- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index 98d746d7cc..a9600f0f7b 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -19,20 +19,20 @@ AddUncertainty::AddUncertainty(std::shared_ptr std::shared_ptr::IntervalType>> AddUncertainty::transform( - double additiveUncertainty, double minimalTransitionProbability, uint64_t maxSuccessors) { + ValueType additiveUncertainty, ValueType minimalTransitionProbability, std::optional maxSuccessors) { // we first build the matrix and later copy the row grouping. auto newMatrixBuilder = storage::SparseMatrixBuilder(origModel->getTransitionMatrix().getRowCount(), origModel->getTransitionMatrix().getColumnCount(), origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { - if (origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors) { + if (maxSuccessors.has_value() && origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors.value()) { for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); } } else { for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { - newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), 0, 0)); + newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), storm::utility::convertNumber(entry.getValue())); } } } @@ -74,17 +74,14 @@ std::shared_ptr: } template -typename AddUncertainty::IntervalType AddUncertainty::addUncertainty(ValueType const& vt, double additiveUncertainty, - double minimalValue) { +typename AddUncertainty::IntervalType AddUncertainty::addUncertainty(ValueType const& vt, ValueType additiveUncertainty, + ValueType minimalValue) { if (utility::isOne(vt)) { return IntervalType(storm::utility::one(), storm::utility::one()); } - ValueType const center = vt; - ValueType const uncertainty = storm::utility::convertNumber(additiveUncertainty); - ValueType const minVal = storm::utility::convertNumber(minimalValue); - STORM_LOG_THROW(center >= minVal, storm::exceptions::InvalidArgumentException, "Transition probability is smaller than minimal value"); - ValueType const lowerBound = storm::utility::max(center - uncertainty, minVal); - ValueType const upperBound = storm::utility::min(center + uncertainty, storm::utility::one() - minVal); + STORM_LOG_THROW(vt >= minimalValue, storm::exceptions::InvalidArgumentException, "Transition probability is smaller than minimal value"); + ValueType const lowerBound = storm::utility::max(vt - additiveUncertainty, minimalValue); + ValueType const upperBound = storm::utility::min(vt + additiveUncertainty, storm::utility::one() - minimalValue); STORM_LOG_ASSERT(storm::utility::isPositive(lowerBound), "Lower bound must be strictly above zero."); STORM_LOG_ASSERT(upperBound < storm::utility::one(), "Upper bound must be strictly below one."); return IntervalType(lowerBound, upperBound); diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index d3421dc7a2..6a7170fa60 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -22,13 +22,13 @@ template class AddUncertainty { public: using IntervalType = std::conditional_t, storm::RationalInterval, storm::Interval>; - + static_assert(std::is_same_v>, "Expected ValueType to match the interval base type."); AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(double additiveUncertainty, double minimalValue = 0.0001, - uint64_t maxSuccessors = 10000000); + std::shared_ptr> transform(ValueType additiveUncertainty, ValueType minimalValue = 0.0001, + std::optional maxSuccessors = {}); private: - IntervalType addUncertainty(ValueType const& vt, double additiveUncertainty, double minimalValue); + IntervalType addUncertainty(ValueType const& vt, ValueType additiveUncertainty, ValueType minimalValue); std::shared_ptr> origModel; }; diff --git a/src/storm/utility/NumberTraits.h b/src/storm/utility/NumberTraits.h index 408471dfa6..23cb9a6036 100644 --- a/src/storm/utility/NumberTraits.h +++ b/src/storm/utility/NumberTraits.h @@ -43,13 +43,13 @@ struct NumberTraits { template<> struct NumberTraits { - static const bool SupportsExponential = false; + static const bool SupportsExponential = true; static const bool IsExact = false; }; template<> struct NumberTraits { - static const bool SupportsExponential = false; + static const bool SupportsExponential = true; static const bool IsExact = true; }; diff --git a/src/test/storm/transformer/AddUncertaintyTest.cpp b/src/test/storm/transformer/AddUncertaintyTest.cpp index 300b788d9b..d35b4d38ee 100644 --- a/src/test/storm/transformer/AddUncertaintyTest.cpp +++ b/src/test/storm/transformer/AddUncertaintyTest.cpp @@ -49,7 +49,7 @@ TEST(AddUncertaintyTransformerTest, BrpTestRational) { auto model = storm::api::buildSparseModel(program, formulas); auto transformer = storm::transformer::AddUncertainty(model); - auto uncertainModel = transformer.transform(0.01); + auto uncertainModel = transformer.transform(storm::RationalNumber("1/100")); EXPECT_EQ(uncertainModel->getNumberOfStates(), model->getNumberOfStates()); EXPECT_EQ(uncertainModel->getNumberOfTransitions(), model->getNumberOfTransitions()); EXPECT_TRUE(uncertainModel->hasUncertainty()); @@ -65,7 +65,7 @@ TEST(AddUncertaintyTransformerTest, Coin22TestRational) { auto model = storm::api::buildSparseModel(program, formulas); auto transformer = storm::transformer::AddUncertainty(model); - auto uncertainModel = transformer.transform(0.01); + auto uncertainModel = transformer.transform(storm::RationalNumber("1/100")); EXPECT_EQ(uncertainModel->getNumberOfStates(), model->getNumberOfStates()); EXPECT_EQ(uncertainModel->getNumberOfTransitions(), model->getNumberOfTransitions()); EXPECT_TRUE(uncertainModel->hasUncertainty()); From 1b80a97cd95ef5b2c2ba531555c149f78321ab66 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 14:12:51 +0100 Subject: [PATCH 20/27] Fix logic in AddUncertainty transformer to handle maxSuccessors condition correctly --- src/storm/transformer/AddUncertainty.cpp | 2 +- src/storm/transformer/AddUncertainty.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storm/transformer/AddUncertainty.cpp b/src/storm/transformer/AddUncertainty.cpp index a9600f0f7b..e750f34089 100644 --- a/src/storm/transformer/AddUncertainty.cpp +++ b/src/storm/transformer/AddUncertainty.cpp @@ -26,7 +26,7 @@ std::shared_ptr: origModel->getTransitionMatrix().getNonzeroEntryCount(), true, false); // Build transition matrix (without row grouping) for (uint64_t rowIndex = 0; rowIndex < origModel->getTransitionMatrix().getRowCount(); ++rowIndex) { - if (maxSuccessors.has_value() && origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors.value()) { + if (!maxSuccessors.has_value() || origModel->getTransitionMatrix().getRowEntryCount(rowIndex) <= maxSuccessors.value()) { for (auto const& entry : origModel->getTransitionMatrix().getRow(rowIndex)) { newMatrixBuilder.addNextValue(rowIndex, entry.getColumn(), addUncertainty(entry.getValue(), additiveUncertainty, minimalTransitionProbability)); } diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index 6a7170fa60..ad1ff5abc2 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -23,6 +23,7 @@ class AddUncertainty { public: using IntervalType = std::conditional_t, storm::RationalInterval, storm::Interval>; static_assert(std::is_same_v>, "Expected ValueType to match the interval base type."); + AddUncertainty(std::shared_ptr> const& originalModel); std::shared_ptr> transform(ValueType additiveUncertainty, ValueType minimalValue = 0.0001, std::optional maxSuccessors = {}); From 82a0bfb6d3c7ebbb68d7e889cdb82c4ffeb98b57 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 15:17:28 +0100 Subject: [PATCH 21/27] Fix default value of argument not convertable to rational numbers for cln --- src/storm/transformer/AddUncertainty.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storm/transformer/AddUncertainty.h b/src/storm/transformer/AddUncertainty.h index ad1ff5abc2..1ff2d35995 100644 --- a/src/storm/transformer/AddUncertainty.h +++ b/src/storm/transformer/AddUncertainty.h @@ -5,6 +5,7 @@ #include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberForward.h" #include "storm/models/sparse/Model.h" +#include "storm/utility/constants.h" namespace storm::transformer { @@ -25,7 +26,8 @@ class AddUncertainty { static_assert(std::is_same_v>, "Expected ValueType to match the interval base type."); AddUncertainty(std::shared_ptr> const& originalModel); - std::shared_ptr> transform(ValueType additiveUncertainty, ValueType minimalValue = 0.0001, + std::shared_ptr> transform(ValueType additiveUncertainty, + ValueType minimalValue = storm::utility::convertNumber(0.0001), std::optional maxSuccessors = {}); private: From 4580bd1f79bc605e58af166c2550ba9a88bd6126 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 15:45:00 +0100 Subject: [PATCH 22/27] Fix conversion error in robust model checking test --- .../prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 84216e7928..6c6eb17ff1 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -226,7 +226,7 @@ void makeUncertainAndCheck(std::string const& path, std::string const& formulaSt EXPECT_LE(certainValue, maxValue); } -void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, double amountOfUncertainty) { +void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, storm::RationalNumber amountOfUncertainty) { storm::prism::Program program = storm::api::parseProgram(path); program = storm::utility::prism::preprocess(program, ""); std::vector> formulas = @@ -328,6 +328,6 @@ TEST(RobustRationalMDPModelCheckingTest, AddUncertaintyCoin22max) { #ifndef STORM_HAVE_Z3 GTEST_SKIP() << "Z3 not available."; #endif - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.1); - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", 0.2); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", storm::RationalNumber("1/10")); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/mdp/coin2-2.nm", "Pmax=? [F \"all_coins_equal_1\"]", storm::RationalNumber("1/5")); } From c8ae01235e0b42aba7d2b371c6a7dca6846e8f56 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 16:40:06 +0100 Subject: [PATCH 23/27] Update makeUncertainAndCheckRational to use storm::RationalNumber for uncertainty parameter --- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index 156c529f56..d132bdca1d 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -249,7 +249,7 @@ void checkPrismModelForQuantitativeResultRational(std::string const& path, std:: EXPECT_EQ(min, getQuantitativeResultAtInitialState(dtmc, resultMin)); } -void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, double amountOfUncertainty) { +void makeUncertainAndCheckRational(std::string const& path, std::string const& formulaString, storm::RationalNumber amountOfUncertainty) { storm::prism::Program program = storm::api::parseProgram(path); program = storm::utility::prism::preprocess(program, ""); std::vector> formulas = @@ -434,6 +434,6 @@ TEST(RobustRationalDtmcModelCheckerTest, AddUncertaintyBrpMax) { #ifndef STORM_HAVE_Z3 GTEST_SKIP() << "Z3 not available."; #endif - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", 0.01); - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", 0.05); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("0.01")); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("0.05")); } From db5ae16a9d30630644a949fd54e7800505a1b482 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 19 Mar 2026 18:00:38 +0100 Subject: [PATCH 24/27] Fix test --- .../prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp index d132bdca1d..9c2b0f4f7b 100644 --- a/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/dtmc/RobustDtmcPrctlModelCheckerTest.cpp @@ -434,6 +434,6 @@ TEST(RobustRationalDtmcModelCheckerTest, AddUncertaintyBrpMax) { #ifndef STORM_HAVE_Z3 GTEST_SKIP() << "Z3 not available."; #endif - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("0.01")); - makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("0.05")); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("1/10")); + makeUncertainAndCheckRational(STORM_TEST_RESOURCES_DIR "/dtmc/brp-16-2.pm", "P=? [ F \"target\"]", storm::RationalNumber("1/20")); } From d2618bd7ed2e113fe77d63bfc539bea0ab33867d Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 24 Mar 2026 14:32:29 +0100 Subject: [PATCH 25/27] Use IntervalBaseType in SparseDtmcEliminationModelChecker and correct error messages about intervals in SparseMdpPrctlHelper. --- src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp | 4 ++-- .../reachability/SparseDtmcEliminationModelChecker.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index cb205d7cae..c610ffe7ff 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -1062,7 +1062,7 @@ std::vector SparseMdpPrctlHelper::compute // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support double interval rewards with rational interval models."); } else { return computeReachabilityRewardsHelper( env, std::move(goal), transitionMatrix, backwardTransitions, @@ -1097,7 +1097,7 @@ std::vector SparseMdpPrctlHelper::compute // Only compute the result if the reward model is not empty. STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); if constexpr (std::is_same_v) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support interval rewards with rational interval models."); + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support rational interval rewards with double interval models."); } else { return computeReachabilityRewardsHelper( env, std::move(goal), transitionMatrix, backwardTransitions, diff --git a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index f02feee29b..8b70af8ea4 100644 --- a/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/storm/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -1,5 +1,6 @@ #pragma once +#include "storm/adapters/IntervalForward.h" #include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "storm/models/sparse/Dtmc.h" #include "storm/solver/stateelimination/StatePriorityQueue.h" @@ -27,7 +28,7 @@ class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker typedef typename SparseDtmcModelType::RewardModelType RewardModelType; typedef typename storm::storage::FlexibleSparseMatrix::row_type FlexibleRowType; typedef typename FlexibleRowType::iterator FlexibleRowIterator; - using SolutionType = typename std::conditional, double, ValueType>::type; + using SolutionType = storm::IntervalBaseType; /*! * Creates an elimination-based model checker for the given model. From 8222dcfd1bbba58b3601946fd23eaea0b2840ab6 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Tue, 24 Mar 2026 16:00:03 +0100 Subject: [PATCH 26/27] Remove unused IntervalForward includes, interval setting, and adjust optimization direction in ViOperatorMultiplier --- .../results/ExplicitQualitativeCheckResult.cpp | 1 - .../modelchecker/results/ExplicitQualitativeCheckResult.h | 1 + src/storm/settings/modules/GeneralSettings.cpp | 6 ------ src/storm/settings/modules/GeneralSettings.h | 8 -------- src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp | 1 - src/storm/solver/helper/ValueIterationOperator.cpp | 1 - src/storm/solver/helper/ValueIterationOperator.h | 1 - src/storm/solver/multiplier/ViOperatorMultiplier.cpp | 8 ++++---- 8 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp index 76d86175b0..50b9a9e16c 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.cpp @@ -3,7 +3,6 @@ #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" -#include "storm/adapters/IntervalForward.h" #include "storm/adapters/JsonAdapter.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/exceptions/InvalidOperationException.h" diff --git a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h index 95db1271bb..9fb3228f0d 100644 --- a/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h +++ b/src/storm/modelchecker/results/ExplicitQualitativeCheckResult.h @@ -4,6 +4,7 @@ #include #include +#include "storm/adapters/IntervalForward.h" #include "storm/adapters/JsonForward.h" #include "storm/modelchecker/results/QualitativeCheckResult.h" #include "storm/models/sparse/StateLabeling.h" diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp index 8b440ee61f..d2efd632e8 100644 --- a/src/storm/settings/modules/GeneralSettings.cpp +++ b/src/storm/settings/modules/GeneralSettings.cpp @@ -32,7 +32,6 @@ const std::string GeneralSettings::bisimulationOptionShortName = "bisim"; const std::string GeneralSettings::parametricOptionName = "parametric"; const std::string GeneralSettings::exactOptionName = "exact"; const std::string GeneralSettings::soundOptionName = "sound"; -const std::string GeneralSettings::intervalOptionName = "interval"; GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { this->addOption( @@ -86,7 +85,6 @@ GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { .build()) .build()); this->addOption(storm::settings::OptionBuilder(moduleName, soundOptionName, false, "Sets whether to force sound model checking.").build()); - this->addOption(storm::settings::OptionBuilder(moduleName, intervalOptionName, false, "Sets whether to enable interval model checking.").build()); } bool GeneralSettings::isHelpSet() const { @@ -154,10 +152,6 @@ bool GeneralSettings::isSoundSet() const { return this->getOption(soundOptionName).getHasOptionBeenSet(); } -bool GeneralSettings::isIntervalSet() const { - return this->getOption(intervalOptionName).getHasOptionBeenSet(); -} - void GeneralSettings::finalize() { // Intentionally left empty. } diff --git a/src/storm/settings/modules/GeneralSettings.h b/src/storm/settings/modules/GeneralSettings.h index 2e2e12620f..1723583b14 100644 --- a/src/storm/settings/modules/GeneralSettings.h +++ b/src/storm/settings/modules/GeneralSettings.h @@ -123,13 +123,6 @@ class GeneralSettings : public ModuleSettings { */ bool isSoundSet() const; - /*! - * Retrieves whether the option enabling interval models is set. - * - * @return True if the option was set - */ - bool isIntervalSet() const; - bool check() const override; void finalize() override; @@ -156,7 +149,6 @@ class GeneralSettings : public ModuleSettings { static const std::string parametricOptionName; static const std::string exactOptionName; static const std::string soundOptionName; - static const std::string intervalOptionName; }; } // namespace modules diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 32040e68ec..0ce268ac03 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -4,7 +4,6 @@ #include #include "storm/adapters/IntervalAdapter.h" -#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/environment/solver/MinMaxSolverEnvironment.h" #include "storm/environment/solver/OviSolverEnvironment.h" diff --git a/src/storm/solver/helper/ValueIterationOperator.cpp b/src/storm/solver/helper/ValueIterationOperator.cpp index 4f352705e3..bd8a856f53 100644 --- a/src/storm/solver/helper/ValueIterationOperator.cpp +++ b/src/storm/solver/helper/ValueIterationOperator.cpp @@ -3,7 +3,6 @@ #include #include "storm/adapters/IntervalAdapter.h" -#include "storm/adapters/IntervalForward.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/storage/BitVector.h" #include "storm/storage/SparseMatrix.h" diff --git a/src/storm/solver/helper/ValueIterationOperator.h b/src/storm/solver/helper/ValueIterationOperator.h index a3172ad40e..257f6c95fe 100644 --- a/src/storm/solver/helper/ValueIterationOperator.h +++ b/src/storm/solver/helper/ValueIterationOperator.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index fc85ce4cd1..39b5ca17da 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -241,18 +241,18 @@ void ViOperatorMultiplier::multiply if (storm::solver::minimize(dir)) { if (choices) { detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend, OptimizationDirection::Maximize); + apply(backend, OptimizationDirection::Minimize); } else { detail::MultiplierBackend backend; - apply(backend, OptimizationDirection::Maximize); + apply(backend, OptimizationDirection::Minimize); } } else { if (choices) { detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend, OptimizationDirection::Minimize); + apply(backend, OptimizationDirection::Maximize); } else { detail::MultiplierBackend backend; - apply(backend, OptimizationDirection::Minimize); + apply(backend, OptimizationDirection::Maximize); } } } From e30a4eadc65b7336cfd7165f77c433b21920091c Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 1 Apr 2026 13:35:17 +0200 Subject: [PATCH 27/27] add uncertainty resolution mode to multipliers and enable next properties for interval models --- resources/examples/testfiles/imdp/tiny-03.drn | 4 +- .../SparseMarkovAutomatonCslModelChecker.cpp | 3 +- ...ndeterministicStepBoundedHorizonHelper.cpp | 6 +- .../infinitehorizon/internal/LraViHelper.cpp | 2 +- .../prctl/SparseMdpPrctlModelChecker.cpp | 3 +- .../prctl/helper/SparseMdpPrctlHelper.cpp | 27 ++++----- .../prctl/helper/SparseMdpPrctlHelper.h | 2 + .../IterativeMinMaxLinearEquationSolver.cpp | 2 +- src/storm/solver/StandardGameSolver.cpp | 2 +- src/storm/solver/multiplier/Multiplier.cpp | 13 ++-- src/storm/solver/multiplier/Multiplier.h | 13 +++- .../solver/multiplier/NativeMultiplier.cpp | 7 ++- .../solver/multiplier/NativeMultiplier.h | 1 + .../multiplier/ViOperatorMultiplier.cpp | 59 +++++++++++-------- .../solver/multiplier/ViOperatorMultiplier.h | 1 + .../mdp/RobustMdpPrctlModelCheckerTest.cpp | 12 ++-- src/test/storm/solver/MultiplierTest.cpp | 2 + 17 files changed, 95 insertions(+), 64 deletions(-) diff --git a/resources/examples/testfiles/imdp/tiny-03.drn b/resources/examples/testfiles/imdp/tiny-03.drn index 46767f506c..01c8fd5858 100644 --- a/resources/examples/testfiles/imdp/tiny-03.drn +++ b/resources/examples/testfiles/imdp/tiny-03.drn @@ -14,8 +14,8 @@ state 0 init 1 : [0.4, 0.9] 2 : [0.5, 0.8] action 1 - 1 : [0.4, 0.9] - 2 : [0.5, 0.8] + 1 : [0.3, 0.7] + 2 : [0.4, 0.8] state 1 target action 0 1 : [1, 1] diff --git a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index e4e5f820b1..6e15e9e9be 100644 --- a/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -105,7 +105,8 @@ std::unique_ptr SparseMarkovAutomatonCslModelChecker subResultPointer = this->check(env, pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( - env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); + env, checkTask.getOptimizationDirection(), checkTask.getUncertaintyResolutionMode(), this->getModel().getTransitionMatrix(), + subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp index 9eedacca02..b4a53af606 100644 --- a/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp +++ b/src/storm/modelchecker/helper/finitehorizon/SparseNondeterministicStepBoundedHorizonHelper.cpp @@ -85,9 +85,9 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper().create(env, submatrix); if (lowerBound == 0) { - multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound); + multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound, goal.getUncertaintyResolutionMode()); } else { - multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1); + multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, upperBound - lowerBound + 1, goal.getUncertaintyResolutionMode()); storm::storage::SparseMatrix submatrix; if constexpr (storm::IsIntervalType) { @@ -98,7 +98,7 @@ std::vector SparseNondeterministicStepBoundedHorizonHelper().create(env, submatrix); b = std::vector(b.size(), storm::utility::zero()); - multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, lowerBound - 1); + multiplier->repeatedMultiplyAndReduce(env, goal.direction(), subresult, &b, lowerBound - 1, goal.getUncertaintyResolutionMode()); } // Set the values of the resulting vector accordingly. storm::utility::vector::setVectorValues(result, maybeStates, subresult); diff --git a/src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp b/src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp index 80d87e91bd..3c241c4688 100644 --- a/src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp +++ b/src/storm/modelchecker/helper/infinitehorizon/internal/LraViHelper.cpp @@ -373,7 +373,7 @@ void LraViHelper::performIterationSte } else { // Also keep track of the choices made. std::vector tsChoices(_TsTransitions.getRowGroupCount()); - _TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew(), &tsChoices); + _TsMultiplier->multiplyAndReduce(env, *dir, xOld(), &_TsChoiceValues, xNew(), UncertaintyResolutionMode::Unset, &tsChoices); // Note that nondeterminism within the timed states means that there can not be instant states (We either have MDPs or MAs) // Hence, in this branch we don't have to care for choices at instant states. STORM_LOG_ASSERT(!_hasInstantStates, "Nondeterministic timed states are only supported if there are no instant states."); diff --git a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index a17ca029dc..54f0fb436c 100644 --- a/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/storm/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -162,7 +162,8 @@ std::unique_ptr SparseMdpPrctlModelChecker::com std::unique_ptr subResultPointer = this->check(env, pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->template asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities( - env, checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); + env, checkTask.getOptimizationDirection(), checkTask.getUncertaintyResolutionMode(), this->getModel().getTransitionMatrix(), + subResult.getTruthValuesVector()); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index c610ffe7ff..7e10f08ed4 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -131,20 +131,16 @@ std::map SparseMdpPrctlHelper< template std::vector SparseMdpPrctlHelper::computeNextProbabilities( - Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, - storm::storage::BitVector const& nextStates) { - if constexpr (storm::IsIntervalType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models."); - } else { - // Create the vector with which to multiply and initialize it correctly. - std::vector result(transitionMatrix.getRowGroupCount()); - storm::utility::vector::setVectorValues(result, nextStates, storm::utility::one()); + Environment const& env, OptimizationDirection dir, UncertaintyResolutionMode uncertaintyResolutionMode, + storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates) { + // Create the vector with which to multiply and initialize it correctly. + std::vector result(transitionMatrix.getRowGroupCount()); + storm::utility::vector::setVectorValues(result, nextStates, storm::utility::one()); - auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); - multiplier->multiplyAndReduce(env, dir, result, nullptr, result); + auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); + multiplier->multiplyAndReduce(env, dir, result, nullptr, result, uncertaintyResolutionMode); - return result; - } + return result; } template @@ -843,7 +839,7 @@ std::vector SparseMdpPrctlHelper::compute std::vector result(rewardModel.getStateRewardVector()); auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); - multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, nullptr, stepCount); + multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, nullptr, stepCount, goal.getUncertaintyResolutionMode()); return result; } @@ -867,7 +863,7 @@ std::vector SparseMdpPrctlHelper::compute std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); - multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, &totalRewardVector, stepBound); + multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, &totalRewardVector, stepBound, goal.getUncertaintyResolutionMode()); return result; } @@ -989,7 +985,8 @@ std::vector SparseMdpPrctlHelper::compute std::vector result(transitionMatrix.getRowGroupCount(), storm::utility::zero()); auto multiplier = storm::solver::MultiplierFactory().create(env, transitionMatrix); - multiplier->repeatedMultiplyAndReduceWithFactor(env, goal.direction(), result, &totalRewardVector, stepBound, discountFactor); + multiplier->repeatedMultiplyAndReduceWithFactor(env, goal.direction(), result, &totalRewardVector, stepBound, discountFactor, + goal.getUncertaintyResolutionMode()); return result; } diff --git a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h index cbcc545b4d..12f2ebbc18 100644 --- a/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.h @@ -7,6 +7,7 @@ #include "storm/modelchecker/prctl/helper/MDPModelCheckingHelperReturnType.h" #include "storm/modelchecker/prctl/helper/rewardbounded/MultiDimensionalRewardUnfolding.h" #include "storm/solver/SolveGoal.h" +#include "storm/solver/UncertaintyResolutionMode.h" #include "storm/storage/MaximalEndComponent.h" #include "storm/storage/SparseMatrix.h" @@ -38,6 +39,7 @@ class SparseMdpPrctlHelper { storm::storage::BitVector const& initialStates); static std::vector computeNextProbabilities(Environment const& env, OptimizationDirection dir, + UncertaintyResolutionMode uncertaintyResolutionMode, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& nextStates); diff --git a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp index 0ce268ac03..3819591a75 100644 --- a/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp +++ b/src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp @@ -63,7 +63,7 @@ MinMaxMethod IterativeMinMaxLinearEquationSolver::getMe "different method."); method = MinMaxMethod::PolicyIteration; } else { - // STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); + STORM_LOG_WARN("The selected solution method " << toString(method) << " does not guarantee exact results."); } } else if (env.solver().isForceSoundness() && method != MinMaxMethod::SoundValueIteration && method != MinMaxMethod::IntervalIteration && method != MinMaxMethod::PolicyIteration && method != MinMaxMethod::RationalSearch && method != MinMaxMethod::OptimisticValueIteration && diff --git a/src/storm/solver/StandardGameSolver.cpp b/src/storm/solver/StandardGameSolver.cpp index 0d9fc4337d..079bf2f0c4 100644 --- a/src/storm/solver/StandardGameSolver.cpp +++ b/src/storm/solver/StandardGameSolver.cpp @@ -427,7 +427,7 @@ void StandardGameSolver::multiplyAndReduce(Environment const& env, Op storm::solver::Multiplier const& multiplier, std::vector& player2ReducedResult, std::vector& player1ReducedResult, std::vector* player1SchedulerChoices, std::vector* player2SchedulerChoices) const { - multiplier.multiplyAndReduce(env, player2Dir, x, b, player2ReducedResult, player2SchedulerChoices); + multiplier.multiplyAndReduce(env, player2Dir, x, b, player2ReducedResult, UncertaintyResolutionMode::Unset, player2SchedulerChoices); if (this->player1RepresentedByMatrix()) { // Player 1 represented by matrix. diff --git a/src/storm/solver/multiplier/Multiplier.cpp b/src/storm/solver/multiplier/Multiplier.cpp index 7b30a6afca..45acc9d578 100644 --- a/src/storm/solver/multiplier/Multiplier.cpp +++ b/src/storm/solver/multiplier/Multiplier.cpp @@ -31,8 +31,9 @@ void Multiplier::clearCache() const { template void Multiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, std::vector& result, + UncertaintyResolutionMode const& uncertaintyResolutionMode, std::vector* choices) const { - multiplyAndReduce(env, dir, this->matrix.getRowGroupIndices(), x, b, result, choices); + multiplyAndReduce(env, dir, this->matrix.getRowGroupIndices(), x, b, result, uncertaintyResolutionMode, choices); } template @@ -60,13 +61,14 @@ void Multiplier::repeatedMultiply(Environment const& en template void Multiplier::repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n) const { + std::vector const* b, uint64_t n, + UncertaintyResolutionMode const& uncertaintyResolutionMode) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); - multiplyAndReduce(env, dir, x, b, x); + multiplyAndReduce(env, dir, x, b, x, uncertaintyResolutionMode); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); break; @@ -77,14 +79,15 @@ void Multiplier::repeatedMultiplyAndReduce(Environment template void Multiplier::repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, uint64_t n, - SolutionType factor) const { + SolutionType factor, + UncertaintyResolutionMode const& uncertaintyResolutionMode) const { storm::utility::ProgressMeasurement progress("multiplications"); progress.setMaxCount(n); progress.startNewMeasurement(0); for (uint64_t i = 0; i < n; ++i) { progress.updateProgress(i); std::transform(x.begin(), x.end(), x.begin(), [factor](SolutionType& c) { return c * factor; }); - multiplyAndReduce(env, dir, x, b, x); + multiplyAndReduce(env, dir, x, b, x, uncertaintyResolutionMode); if (storm::utility::resources::isTerminate()) { STORM_LOG_WARN("Aborting after " << i << " of " << n << " multiplications"); break; diff --git a/src/storm/solver/multiplier/Multiplier.h b/src/storm/solver/multiplier/Multiplier.h index 3a8bccd009..b9c8e6a244 100644 --- a/src/storm/solver/multiplier/Multiplier.h +++ b/src/storm/solver/multiplier/Multiplier.h @@ -5,6 +5,7 @@ #include "storm/solver/MultiplicationStyle.h" #include "storm/solver/OptimizationDirection.h" +#include "storm/solver/UncertaintyResolutionMode.h" namespace storm { @@ -65,12 +66,15 @@ class Multiplier { * to the number of rows of A. * @param result The target vector into which to write the multiplication result. Its length must be equal * to the number of rows of A. Can be the same as the x vector. + * @param uncertaintyResolutionMode The mode according to which to resolve uncertainty in the reduction step. * @param choices If given, the choices made in the reduction process are written to this vector. */ void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& x, std::vector const* b, - std::vector& result, std::vector* choices = nullptr) const; + std::vector& result, UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset, + std::vector* choices = nullptr) const; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, + UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset, std::vector* choices = nullptr) const = 0; /*! @@ -119,9 +123,10 @@ class Multiplier { * @param result The target vector into which to write the multiplication result. Its length must be equal * to the number of rows of A. * @param n The number of times to perform the multiplication. + * @param uncertaintyResolutionMode The mode according to which to resolve uncertainty in the reduction step. */ void repeatedMultiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector& x, std::vector const* b, - uint64_t n) const; + uint64_t n, UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset) const; /*! * Performs repeated matrix-vector multiplication x' = A*(factor * x) + b. Vector x is scaled by factor in each iteration. * @@ -149,10 +154,12 @@ class Multiplier { * @param result The target vector into which to write the multiplication result. Its length must be equal * to the number of rows of A. * @param n The number of times to perform the multiplication. + * @param uncertaintyResolutionMode The mode according to which to resolve uncertainty in the reduction step. * @param factor The scalar to multiply with in each iteration. */ void repeatedMultiplyAndReduceWithFactor(Environment const& env, OptimizationDirection const& dir, std::vector& x, - std::vector const* b, uint64_t n, SolutionType factor) const; + std::vector const* b, uint64_t n, SolutionType factor, + UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset) const; protected: std::vector& provideCachedVector(uint64_t size) const; diff --git a/src/storm/solver/multiplier/NativeMultiplier.cpp b/src/storm/solver/multiplier/NativeMultiplier.cpp index 876f7eea6e..50b41b559b 100644 --- a/src/storm/solver/multiplier/NativeMultiplier.cpp +++ b/src/storm/solver/multiplier/NativeMultiplier.cpp @@ -4,6 +4,8 @@ #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/environment/solver/MultiplierEnvironment.h" +#include "storm/exceptions/NotSupportedException.h" +#include "storm/solver/UncertaintyResolutionMode.h" #include "storm/storage/SparseMatrix.h" #include "storm/utility/macros.h" @@ -41,7 +43,10 @@ void NativeMultiplier::multiplyGaussSeidel(Environment const& env, st template void NativeMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, - std::vector* choices) const { + UncertaintyResolutionMode const& uncertaintyResolutionMode, std::vector* choices) const { + STORM_LOG_THROW(uncertaintyResolutionMode == UncertaintyResolutionMode::Unset, storm::exceptions::NotSupportedException, + "Uncertainty resolution modes other than 'Unset' are not supported by the native multiplier."); + std::vector* target = &result; if (&x == &result) { target = &this->provideCachedVector(x.size()); diff --git a/src/storm/solver/multiplier/NativeMultiplier.h b/src/storm/solver/multiplier/NativeMultiplier.h index ad722fe89c..fbecd2e861 100644 --- a/src/storm/solver/multiplier/NativeMultiplier.h +++ b/src/storm/solver/multiplier/NativeMultiplier.h @@ -23,6 +23,7 @@ class NativeMultiplier : public Multiplier { virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const override; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, + UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset, std::vector* choices = nullptr) const override; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices = nullptr, diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp index 39b5ca17da..59af83eb62 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.cpp +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.cpp @@ -3,6 +3,7 @@ #include "storm/adapters/IntervalAdapter.h" #include "storm/adapters/RationalNumberAdapter.h" #include "storm/exceptions/NotSupportedException.h" +#include "storm/solver/OptimizationDirection.h" #include "storm/solver/helper/ValueIterationOperator.h" #include "storm/storage/SparseMatrix.h" #include "storm/utility/Extremum.h" @@ -213,47 +214,57 @@ void ViOperatorMultiplier::multiply std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, + UncertaintyResolutionMode const& uncertaintyResolutionMode, std::vector* choices) const { if (&result == &x) { auto& tmpResult = this->provideCachedVector(x.size()); - multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, choices); + multiplyAndReduce(env, dir, rowGroupIndices, x, b, tmpResult, uncertaintyResolutionMode, choices); std::swap(result, tmpResult); return; } STORM_LOG_THROW(&rowGroupIndices == &this->matrix.getRowGroupIndices(), storm::exceptions::NotSupportedException, "The row group indices must be the same as the ones stored in the matrix of this multiplier"); auto const& viOp = initialize(); - auto apply = [&](BT& backend, OptimizationDirection od) { - if (od == OptimizationDirection::Minimize) { - if (b) { - viOp.template applyRobust(x, result, *b, backend); + + auto applyRobustDirection = [&](BT& backend, OffsetType const& offset) { + bool robustUncertainty = false; + if constexpr (storm::IsIntervalType) { + robustUncertainty = isUncertaintyResolvedRobust(uncertaintyResolutionMode, dir); + } + + if (robustUncertainty) { + viOp.template applyRobust(x, result, offset, backend); + } else { + viOp.template applyRobust(x, result, offset, backend); + } + }; + + auto applyBackend = [&](OffsetType const& offset) { + if (storm::solver::minimize(dir)) { + if (choices) { + detail::MultiplierBackend backend(*choices, + this->matrix.getRowGroupIndices()); + applyRobustDirection.template operator()(backend, offset); } else { - viOp.template applyRobust(x, result, storm::utility::zero(), backend); + detail::MultiplierBackend backend; + applyRobustDirection.template operator()(backend, offset); } } else { - if (b) { - viOp.template applyRobust(x, result, *b, backend); + if (choices) { + detail::MultiplierBackend backend(*choices, + this->matrix.getRowGroupIndices()); + applyRobustDirection.template operator()(backend, offset); } else { - viOp.template applyRobust(x, result, storm::utility::zero(), backend); + detail::MultiplierBackend backend; + applyRobustDirection.template operator()(backend, offset); } } }; - if (storm::solver::minimize(dir)) { - if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend, OptimizationDirection::Minimize); - } else { - detail::MultiplierBackend backend; - apply(backend, OptimizationDirection::Minimize); - } + + if (b) { + applyBackend(*b); } else { - if (choices) { - detail::MultiplierBackend backend(*choices, this->matrix.getRowGroupIndices()); - apply(backend, OptimizationDirection::Maximize); - } else { - detail::MultiplierBackend backend; - apply(backend, OptimizationDirection::Maximize); - } + applyBackend(storm::utility::zero()); } } diff --git a/src/storm/solver/multiplier/ViOperatorMultiplier.h b/src/storm/solver/multiplier/ViOperatorMultiplier.h index daeae609d3..983e02e573 100644 --- a/src/storm/solver/multiplier/ViOperatorMultiplier.h +++ b/src/storm/solver/multiplier/ViOperatorMultiplier.h @@ -26,6 +26,7 @@ class ViOperatorMultiplier : public Multiplier { bool backwards = true) const override; virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, + UncertaintyResolutionMode const& uncertaintyResolutionMode = UncertaintyResolutionMode::Unset, std::vector* choices = nullptr) const override; virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices = nullptr, diff --git a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp index 6c6eb17ff1..8756b7f1d2 100644 --- a/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/prctl/mdp/RobustMdpPrctlModelCheckerTest.cpp @@ -262,18 +262,18 @@ void makeUncertainAndCheckRational(std::string const& path, std::string const& f EXPECT_LE(certainValue, maxValue); } +// TODO: Add next properties + TEST(RobustMDPModelCheckingTest, Tiny01maxmin) { checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-01.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", 0.4, 0.5, 0.5, 0.4, false); } TEST(RobustMDPModelCheckingTest, Tiny03maxmin) { - checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", 0.4, 0.5, 0.5, 0.4, true); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", 0.4, 0.6, 0.5, 0.3, true); } TEST(RobustMDPModelCheckingTest, BoundedTiny03maxmin) { - checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.4, 0.4, 0.5, 0.5, true); - checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber("2/5"), - storm::RationalNumber("2/5"), storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), true); + checkModel(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", 0.4, 0.6, 0.5, 0.3, true); } TEST(RobustMDPModelCheckingTest, Tiny04maxmin) { @@ -297,12 +297,12 @@ TEST(RobustRationalMDPModelCheckingTest, Tiny01maxmin) { TEST(RobustRationalMDPModelCheckingTest, Tiny03maxmin) { checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F \"target\"];Pmin=? [ F \"target\"]", storm::RationalNumber("2/5"), - storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), storm::RationalNumber("2/5"), true); + storm::RationalNumber("3/5"), storm::RationalNumber("1/2"), storm::RationalNumber("3/10"), true); } TEST(RobustRationalMDPModelCheckingTest, BoundedTiny03maxmin) { checkModelRational(STORM_TEST_RESOURCES_DIR "/imdp/tiny-03.drn", "Pmax=? [ F<=3 \"target\"];Pmin=? [ F<=3 \"target\"]", storm::RationalNumber("2/5"), - storm::RationalNumber("2/5"), storm::RationalNumber("1/2"), storm::RationalNumber("1/2"), true); + storm::RationalNumber("3/5"), storm::RationalNumber("1/2"), storm::RationalNumber("3/10"), true); } TEST(RobustRationalMDPModelCheckingTest, Tiny04maxmin) { diff --git a/src/test/storm/solver/MultiplierTest.cpp b/src/test/storm/solver/MultiplierTest.cpp index 693ad44f05..1933065ce5 100644 --- a/src/test/storm/solver/MultiplierTest.cpp +++ b/src/test/storm/solver/MultiplierTest.cpp @@ -123,4 +123,6 @@ TYPED_TEST(MultiplierTest, repeatedMultiplyAndReduceTest) { EXPECT_NEAR(x[0], this->parseNumber("0.923808265834023387639"), this->precision()); } +// TODO: Write test using the uncertainty resolution mode when more modes than 'Unset' are supported by the native multiplier. + } // namespace \ No newline at end of file