diff --git a/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp index 327103bcc..a8742c1eb 100644 --- a/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/HybridDtmcPrctlHelper.cpp @@ -14,11 +14,15 @@ #include "storm/models/symbolic/StandardRewardModel.h" +#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h" #include "storm/modelchecker/results/SymbolicQualitativeCheckResult.h" #include "storm/modelchecker/results/SymbolicQuantitativeCheckResult.h" #include "storm/modelchecker/results/HybridQuantitativeCheckResult.h" #include "storm/exceptions/InvalidPropertyException.h" +#include "storm/exceptions/NotSupportedException.h" +#include "storm/exceptions/UncheckedRequirementException.h" + namespace storm { namespace modelchecker { @@ -194,6 +198,19 @@ namespace storm { return std::unique_ptr(new HybridQuantitativeCheckResult(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().template getAddZero(), model.getReachableStates(), odd, x)); } + // This function computes an upper bound on the reachability rewards (see Baier et al, CAV'17). + template + inline std::vector computeUpperRewardBounds(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) { + DsMpiDtmcUpperRewardBoundsComputer dsmpi(transitionMatrix, rewards, oneStepTargetProbabilities); + std::vector bounds = dsmpi.computeUpperBounds(); + return bounds; + } + + template<> + inline std::vector computeUpperRewardBounds(storm::storage::SparseMatrix const& transitionMatrix, std::vector const& rewards, std::vector const& oneStepTargetProbabilities) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Computing upper reward bounds is not supported for rational functions."); + } + template std::unique_ptr HybridDtmcPrctlHelper::computeReachabilityRewards(Environment const& env, storm::models::symbolic::Model const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { @@ -228,6 +245,19 @@ namespace storm { // Then compute the state reward vector to use in the computation. storm::dd::Add subvector = rewardModel.getTotalRewardVector(maybeStatesAdd, submatrix, model.getColumnVariables()); + // Check the requirements of a linear equation solver + auto req = linearEquationSolverFactory.getRequirements(env); + req.clearLowerBounds(); + boost::optional> oneStepTargetProbs; + if (req.requiresUpperBounds()) { + storm::dd::Add targetStatesAsColumn = targetStates.template toAdd(); + targetStatesAsColumn = targetStatesAsColumn.swapVariables(model.getRowColumnMetaVariablePairs()); + oneStepTargetProbs = submatrix * targetStatesAsColumn; + oneStepTargetProbs = oneStepTargetProbs->sumAbstract(model.getColumnVariables()); + req.clearUpperBounds(); + } + STORM_LOG_THROW(req.empty(), storm::exceptions::UncheckedRequirementException, "At least one requirement of the linear equation solver could not be matched."); + // Check whether we need to create an equation system. bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; @@ -245,9 +275,18 @@ namespace storm { storm::storage::SparseMatrix explicitSubmatrix = submatrix.toMatrix(odd, odd); std::vector b = subvector.toVector(odd); + // Create the upper bounds vector if one was requested + boost::optional> upperBounds; + if (oneStepTargetProbs) { + upperBounds = computeUpperRewardBounds(explicitSubmatrix, b, oneStepTargetProbs->toVector(odd)); + } + // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(env, std::move(explicitSubmatrix)); solver->setLowerBound(storm::utility::zero()); + if (upperBounds) { + solver->setUpperBounds(std::move(upperBounds.get())); + } solver->solveEquations(env, x, b); // Return a hybrid check result that stores the numerical values explicitly.