diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp index 119e3791d..150a9d86c 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.cpp @@ -6,6 +6,8 @@ #include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" +#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h" +#include "storm/modelchecker/prctl/helper/BaierUpperRewardBoundsComputer.h" #include "storm/models/sparse/Dtmc.h" #include "storm/models/sparse/StandardRewardModel.h" #include "storm/solver/StandardMinMaxLinearEquationSolver.h" @@ -17,6 +19,8 @@ #include "storm/exceptions/InvalidPropertyException.h" #include "storm/exceptions/NotSupportedException.h" #include "storm/exceptions/UnexpectedException.h" +#include "storm/exceptions/UncheckedRequirementException.h" + namespace storm { namespace modelchecker { @@ -27,7 +31,7 @@ namespace storm { } template - SparseDtmcParameterLiftingModelChecker::SparseDtmcParameterLiftingModelChecker(std::unique_ptr>&& solverFactory) : solverFactory(std::move(solverFactory)) { + SparseDtmcParameterLiftingModelChecker::SparseDtmcParameterLiftingModelChecker(std::unique_ptr>&& solverFactory) : solverFactory(std::move(solverFactory)), solvingRequiresUpperRewardBounds(false) { // Intentionally left empty } @@ -109,6 +113,8 @@ namespace storm { // We know some bounds for the results so set them lowerResultBound = storm::utility::zero(); upperResultBound = storm::utility::one(); + // No requirements for bounded formulas + solverFactory->setRequirementsChecked(true); } template @@ -139,6 +145,12 @@ namespace storm { // We know some bounds for the results so set them lowerResultBound = storm::utility::zero(); upperResultBound = storm::utility::one(); + + auto req = solverFactory->getRequirements(storm::solver::EquationSystemType::UntilProbabilities); + req.clearBounds(); + req.clearNoEndComponents(); // We never have end components within the maybestates (assuming graph-preserving instantiations). + STORM_LOG_THROW(req.empty(), storm::exceptions::UncheckedRequirementException, "Unchecked solver requirement."); + solverFactory->setRequirementsChecked(true); } template @@ -172,6 +184,17 @@ namespace storm { // We only know a lower bound for the result lowerResultBound = storm::utility::zero(); + + auto req = solverFactory->getRequirements(storm::solver::EquationSystemType::ReachabilityRewards); + req.clearNoEndComponents(); // We never have end components within the maybestates (assuming graph-preserving instantiations). + req.clearLowerBounds(); + if (req.requiresUpperBounds()) { + solvingRequiresUpperRewardBounds = true; + req.clearUpperBounds(); + } + STORM_LOG_THROW(req.empty(), storm::exceptions::UncheckedRequirementException, "Unchecked solver requirement."); + solverFactory->setRequirementsChecked(true); + } @@ -200,6 +223,9 @@ namespace storm { // We only know a lower bound for the result lowerResultBound = storm::utility::zero(); + + // No requirements for bounded reward formula + solverFactory->setRequirementsChecked(true); } template @@ -228,7 +254,23 @@ namespace storm { } auto solver = solverFactory->create(parameterLifter->getMatrix()); if (lowerResultBound) solver->setLowerBound(lowerResultBound.get()); - if (upperResultBound) solver->setUpperBound(upperResultBound.get()); + if (upperResultBound) { + solver->setUpperBound(upperResultBound.get()); + } else if (solvingRequiresUpperRewardBounds) { + // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17). + std::vector oneStepProbs; + oneStepProbs.reserve(parameterLifter->getMatrix().getRowCount()); + for (uint64_t row = 0; row < parameterLifter->getMatrix().getRowCount(); ++row) { + oneStepProbs.push_back(storm::utility::one() - parameterLifter->getMatrix().getRowSum(row)); + } + if (dirForParameters == storm::OptimizationDirection::Minimize) { + storm::modelchecker::helper::DsMpiMdpUpperRewardBoundsComputer dsmpi(parameterLifter->getMatrix(), parameterLifter->getVector(), oneStepProbs); + solver->setUpperBounds(dsmpi.computeUpperBounds()); + } else { + storm::modelchecker::helper::BaierUpperRewardBoundsComputer baier(parameterLifter->getMatrix(), parameterLifter->getVector(), oneStepProbs); + solver->setUpperBound(baier.computeUpperBound()); + } + } if (!stepBound) solver->setTrackScheduler(true); if (storm::solver::minimize(dirForParameters) && minSchedChoices && !stepBound) solver->setInitialScheduler(std::move(minSchedChoices.get())); if (storm::solver::maximize(dirForParameters) && maxSchedChoices && !stepBound) solver->setInitialScheduler(std::move(maxSchedChoices.get())); @@ -247,7 +289,7 @@ namespace storm { } // Invoke the solver - if(stepBound) { + if (stepBound) { assert(*stepBound > 0); x = std::vector(maybeStates.getNumberOfSetBits(), storm::utility::zero()); solver->repeatedMultiply(dirForParameters, x, ¶meterLifter->getVector(), *stepBound); diff --git a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h index d6f51032b..b4a8644b6 100644 --- a/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h +++ b/src/storm-pars/modelchecker/region/SparseDtmcParameterLiftingModelChecker.h @@ -12,7 +12,6 @@ #include "storm/solver/MinMaxLinearEquationSolver.h" #include "storm/logic/FragmentSpecification.h" - namespace storm { namespace modelchecker { @@ -49,12 +48,13 @@ namespace storm { storm::storage::BitVector maybeStates; std::vector resultsForNonMaybeStates; boost::optional stepBound; - + std::unique_ptr> instantiationChecker; - + std::unique_ptr> parameterLifter; std::unique_ptr> solverFactory; - + bool solvingRequiresUpperRewardBounds; + // Results from the most recent solver call. boost::optional> minSchedChoices, maxSchedChoices; std::vector x;