diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 5d1b0a60d..89a2c9e03 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -156,7 +156,7 @@ namespace storm { } template - std::vector SparseCtmcCslModelChecker::computeTransientProbabilities(Environment const& env, CheckTask const& checkTask) { + std::vector SparseCtmcCslModelChecker::computeAllTransientProbabilities(Environment const& env, CheckTask const& checkTask) { storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported."); STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::NotImplementedException, "Computation needs upper limit for time bound."); diff --git a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.h b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.h index d0af959f4..d7f432f53 100644 --- a/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.h +++ b/src/storm/modelchecker/csl/SparseCtmcCslModelChecker.h @@ -35,7 +35,10 @@ namespace storm { virtual std::unique_ptr computeReachabilityRewards(Environment const& env, storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeTotalRewards(Environment const& env, storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; - std::vector computeTransientProbabilities(Environment const& env, CheckTask const& checkTask); + /*! + * Compute transient probabilities for all states. + */ + std::vector computeAllTransientProbabilities(Environment const& env, CheckTask const& checkTask); private: template::SupportsExponential, int>::type = 0> diff --git a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 9d4cca741..ed87a9e1a 100644 --- a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -210,8 +210,8 @@ namespace storm { } template - std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { - return SparseDtmcPrctlHelper::computeAllUntilProbabilities(env, std::move(goal), computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, initialStates, phiStates, psiStates); + std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { + return SparseDtmcPrctlHelper::computeAllUntilProbabilities(env, std::move(goal), computeProbabilityMatrix(rateMatrix, exitRateVector), initialStates, phiStates, psiStates); } template @@ -861,7 +861,7 @@ namespace storm { template std::vector SparseCtmcCslHelper::computeUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); - template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); template std::vector SparseCtmcCslHelper::computeNextProbabilities(Environment const& env, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates); @@ -892,8 +892,8 @@ namespace storm { template std::vector SparseCtmcCslHelper::computeUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); template std::vector SparseCtmcCslHelper::computeUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); - template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); - template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + template std::vector SparseCtmcCslHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); template std::vector SparseCtmcCslHelper::computeNextProbabilities(Environment const& env, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates); template std::vector SparseCtmcCslHelper::computeNextProbabilities(Environment const& env, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates); diff --git a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h index c988603e4..4fb01d5ff 100644 --- a/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -28,7 +28,7 @@ namespace storm { static std::vector computeUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); template - static std::vector computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + static std::vector computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); template static std::vector computeNextProbabilities(Environment const& env, storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates); diff --git a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp index a76da19b1..a03914c8c 100644 --- a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp +++ b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp @@ -257,38 +257,22 @@ namespace storm { } template - std::vector SparseDtmcPrctlHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { + std::vector SparseDtmcPrctlHelper::computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) { uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); std::vector result(numberOfStates, storm::utility::zero()); - // We need to identify the maybe states (states which have a probability for satisfying the until formula - // that is strictly between 0 and 1) and the states that satisfy the formula with probability 1. - //storm::storage::BitVector maybeStates, statesWithProbability1; + // All states are relevant storm::storage::BitVector relevantStates(numberOfStates, true); - // Get all states that have probability 0 and 1 of satisfying the until-formula. - //std::pair statesWithProbability01 = storm::utility::graph::performProb01(transitionMatrix, phiStates, initialStates); - //storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first); - //statesWithProbability1 = std::move(statesWithProbability01.second); - //maybeStates = ~(statesWithProbability0 | statesWithProbability1); - - //STORM_LOG_INFO("Preprocessing: " << statesWithProbability1.getNumberOfSetBits() << " states with probability 1, " << statesWithProbability0.getNumberOfSetBits() << " with probability 0 (" << maybeStates.getNumberOfSetBits() << " states remaining)."); - - // Set values of resulting vector that are known exactly. - //storm::utility::vector::setVectorValues(result, statesWithProbability0, storm::utility::zero()); - //storm::utility::vector::setVectorValues(result, statesWithProbability1, storm::utility::one()); - // Compute exact probabilities for some states. if (!relevantStates.empty()) { - // In this case we have to compute the probabilities. - // Check whether we need to convert the input to equation system format. storm::solver::GeneralLinearEquationSolverFactory linearEquationSolverFactory; bool convertToEquationSystem = linearEquationSolverFactory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::EquationSystem; - // We can eliminate the rows and columns from the original transition probability matrix. storm::storage::SparseMatrix submatrix(transitionMatrix); + submatrix.makeRowsAbsorbing(phiStates); submatrix.makeRowsAbsorbing(psiStates); //submatrix.deleteDiagonalEntries(psiStates); //storm::storage::BitVector failState(numberOfStates, false); @@ -307,8 +291,8 @@ namespace storm { // This is the initial guess for the iterative solvers. It should be safe as for all // 'maybe' states we know that the probability is strictly larger than 0. std::vector x = std::vector(relevantStates.getNumberOfSetBits(), storm::utility::convertNumber(0.5)); - //std::vector x = std::vector(relevantStates.getNumberOfSetBits(), storm::utility::zero()); + // Prepare the right-hand side of the equation system. std::vector b(relevantStates.getNumberOfSetBits(), storm::utility::zero()); // Set initial states size_t i = 0; @@ -320,10 +304,6 @@ namespace storm { ++i; } - // Prepare the right-hand side of the equation system. For entry i this corresponds to - // the accumulated probability of going from state i to some 'yes' state. - //std::vector b = transitionMatrix.getConstrainedRowSumVector(relevantStates, statesWithProbability1); - // Now solve the created system of linear equations. goal.restrictRelevantValues(relevantStates); std::unique_ptr> solver = storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix)); diff --git a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h index 60a026571..e22e4bfc4 100644 --- a/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h +++ b/src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h @@ -36,7 +36,7 @@ namespace storm { static std::vector computeUntilProbabilities(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, bool qualitative, ModelCheckerHint const& hint = ModelCheckerHint()); - static std::vector computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); + static std::vector computeAllUntilProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates); static std::vector computeGloballyProbabilities(Environment const& env, storm::solver::SolveGoal&& goal, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative); diff --git a/src/test/storm/modelchecker/DtmcPrctlModelCheckerTest.cpp b/src/test/storm/modelchecker/DtmcPrctlModelCheckerTest.cpp index ff0e4630d..6c5f08c86 100644 --- a/src/test/storm/modelchecker/DtmcPrctlModelCheckerTest.cpp +++ b/src/test/storm/modelchecker/DtmcPrctlModelCheckerTest.cpp @@ -17,6 +17,7 @@ #include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h" #include "storm/modelchecker/prctl/HybridDtmcPrctlModelChecker.h" #include "storm/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h" +#include "storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h" #include "storm/modelchecker/results/QuantitativeCheckResult.h" #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "storm/modelchecker/results/SymbolicQualitativeCheckResult.h" @@ -644,5 +645,57 @@ namespace { EXPECT_NEAR(this->parseNumber("25/24"), this->getQuantitativeResultAtInitialState(model, result), this->precision()); } + TEST(DtmcPrctlModelCheckerTest, AllUntilProbabilities) { + std::string formulasString = "P=? [F \"one\"]"; + formulasString += "; P=? [F \"two\"]"; + formulasString += "; P=? [F \"three\"]"; + + storm::prism::Program program = storm::api::parseProgram(STORM_TEST_RESOURCES_DIR "/dtmc/die.pm"); + auto formulas = storm::api::extractFormulasFromProperties(storm::api::parsePropertiesForPrismProgram(formulasString, program)); + std::vector> tasks; + for (auto const& f : formulas) { + tasks.emplace_back(*f); + } + auto model = storm::api::buildSparseModel(program, formulas)->template as>(); + EXPECT_EQ(13ul, model->getNumberOfStates()); + EXPECT_EQ(20ul, model->getNumberOfTransitions()); + + storm::storage::SparseMatrix matrix = model->getTransitionMatrix(); + storm::storage::BitVector initialStates(13); + initialStates.set(0); + storm::storage::BitVector phiStates(13); + storm::storage::BitVector psiStates(13); + psiStates.set(7); + psiStates.set(8); + psiStates.set(9); + psiStates.set(10); + psiStates.set(11); + psiStates.set(12); + storm::Environment env; + storm::solver::SolveGoal goal(*model, tasks[0]); + std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeAllUntilProbabilities(env, std::move(goal), matrix, initialStates, phiStates, psiStates); + + EXPECT_NEAR(1.0/6, result[7], 1e-6); + EXPECT_NEAR(1.0/6, result[8], 1e-6); + EXPECT_NEAR(1.0/6, result[9], 1e-6); + EXPECT_NEAR(1.0/6, result[10], 1e-6); + EXPECT_NEAR(1.0/6, result[11], 1e-6); + EXPECT_NEAR(1.0/6, result[12], 1e-6); + + phiStates.set(6); + psiStates.set(1); + result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeAllUntilProbabilities(env, std::move(goal), matrix, initialStates, phiStates, psiStates); + + EXPECT_NEAR(1, result[0], 1e-6); + EXPECT_NEAR(0.5, result[1], 1e-6); + EXPECT_NEAR(0.5, result[2], 1e-6); + EXPECT_NEAR(0.25, result[5], 1e-6); + EXPECT_NEAR(0, result[7], 1e-6); + EXPECT_NEAR(0, result[8], 1e-6); + EXPECT_NEAR(0, result[9], 1e-6); + EXPECT_NEAR(0.125, result[10], 1e-6); + EXPECT_NEAR(0.125, result[11], 1e-6); + EXPECT_NEAR(0, result[12], 1e-6); + } }