From a6514052da54792c72d3974b7c046164f9da77e9 Mon Sep 17 00:00:00 2001 From: dehnert Date: Sun, 4 Dec 2016 18:16:17 +0100 Subject: [PATCH] avoiding dijkstra for interpolation if most-probable path info is already available --- src/storm/abstraction/AbstractionInformation.cpp | 1 - src/storm/abstraction/MenuGameRefiner.cpp | 10 +++++++--- src/storm/abstraction/MenuGameRefiner.h | 1 + src/storm/abstraction/StateSetAbstractor.cpp | 1 + src/storm/abstraction/prism/CommandAbstractor.cpp | 3 +++ .../abstraction/GameBasedMdpModelChecker.cpp | 11 ++++++++++- 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/storm/abstraction/AbstractionInformation.cpp b/src/storm/abstraction/AbstractionInformation.cpp index 4bee18228..ee0878365 100644 --- a/src/storm/abstraction/AbstractionInformation.cpp +++ b/src/storm/abstraction/AbstractionInformation.cpp @@ -465,7 +465,6 @@ namespace storm { template std::tuple AbstractionInformation::decodeStatePlayer1ChoiceAndUpdate(storm::dd::Bdd const& stateChoiceAndUpdate) const { - stateChoiceAndUpdate.template toAdd().exportToDot("out.dot"); STORM_LOG_ASSERT(stateChoiceAndUpdate.getNonZeroCount() == 1, "Wrong number of non-zero entries."); storm::storage::BitVector statePredicates(this->getNumberOfPredicates()); diff --git a/src/storm/abstraction/MenuGameRefiner.cpp b/src/storm/abstraction/MenuGameRefiner.cpp index 6472b614d..0abca47e0 100644 --- a/src/storm/abstraction/MenuGameRefiner.cpp +++ b/src/storm/abstraction/MenuGameRefiner.cpp @@ -357,8 +357,6 @@ namespace storm { // Now construct all player 2 choices that actually exist and differ in the min and max case. constraint &= minPlayer2Strategy.exclusiveOr(maxPlayer2Strategy); - minPlayer2Strategy.exclusiveOr(maxPlayer2Strategy).template toAdd().exportToDot("pl2diff.dot"); - constraint.template toAdd().exportToDot("constraint.dot"); // Then restrict the pivot states by requiring existing and different player 2 choices. result.pivotStates &= ((minPlayer1Strategy || maxPlayer1Strategy) && constraint).existsAbstract(game.getNondeterminismVariables()); @@ -502,7 +500,12 @@ namespace storm { AbstractionInformation const& abstractionInformation = abstractor.get().getAbstractionInformation(); // Compute the most probable path from any initial state to the pivot state. - MostProbablePathsResult mostProbablePathsResult = getMostProbablePathSpanningTree(game, pivotStateResult.fromDirection == storm::OptimizationDirection::Minimize ? minPlayer1Strategy && minPlayer2Strategy : maxPlayer1Strategy && maxPlayer2Strategy); + MostProbablePathsResult mostProbablePathsResult; + if (!pivotStateResult.mostProbablePathsResult) { + mostProbablePathsResult = getMostProbablePathSpanningTree(game, pivotStateResult.fromDirection == storm::OptimizationDirection::Minimize ? minPlayer1Strategy && minPlayer2Strategy : maxPlayer1Strategy && maxPlayer2Strategy); + } else { + mostProbablePathsResult = pivotStateResult.mostProbablePathsResult.get(); + } // Create a new expression manager that we can use for the interpolation. std::shared_ptr interpolationManager = abstractionInformation.getExpressionManager().clone(); @@ -703,6 +706,7 @@ namespace storm { template void MenuGameRefiner::performRefinement(std::vector const& refinementCommands) const { for (auto const& command : refinementCommands) { + STORM_LOG_TRACE("Refining with " << command.getPredicates().size() << " predicates."); abstractor.get().refine(command); } diff --git a/src/storm/abstraction/MenuGameRefiner.h b/src/storm/abstraction/MenuGameRefiner.h index e23b03303..e79248509 100644 --- a/src/storm/abstraction/MenuGameRefiner.h +++ b/src/storm/abstraction/MenuGameRefiner.h @@ -49,6 +49,7 @@ namespace storm { template struct MostProbablePathsResult { + MostProbablePathsResult() = default; MostProbablePathsResult(storm::dd::Add const& maxProbabilities, storm::dd::Bdd const& spanningTree); storm::dd::Add maxProbabilities; diff --git a/src/storm/abstraction/StateSetAbstractor.cpp b/src/storm/abstraction/StateSetAbstractor.cpp index 456d89c5e..10c392cc5 100644 --- a/src/storm/abstraction/StateSetAbstractor.cpp +++ b/src/storm/abstraction/StateSetAbstractor.cpp @@ -80,6 +80,7 @@ namespace storm { void StateSetAbstractor::recomputeCachedBdd() { // Now check whether we need to recompute the cached BDD. std::set newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables); + // Since the number of relevant predicates is monotonic, we can simply check for the size here. STORM_LOG_ASSERT(newRelevantPredicateIndices.size() >= relevantPredicatesAndVariables.size(), "Illegal size of relevant predicates."); bool recomputeBdd = newRelevantPredicateIndices.size() > relevantPredicatesAndVariables.size(); diff --git a/src/storm/abstraction/prism/CommandAbstractor.cpp b/src/storm/abstraction/prism/CommandAbstractor.cpp index 9d21f1c86..729704a36 100644 --- a/src/storm/abstraction/prism/CommandAbstractor.cpp +++ b/src/storm/abstraction/prism/CommandAbstractor.cpp @@ -222,10 +222,13 @@ namespace storm { template storm::dd::Bdd CommandAbstractor::getSourceStateBdd(storm::solver::SmtSolver::ModelReference const& model) const { storm::dd::Bdd result = this->getAbstractionInformation().getDdManager().getBddOne(); +// std::cout << "new model ----------------" << std::endl; for (auto const& variableIndexPair : relevantPredicatesAndVariables.first) { if (model.getBooleanValue(variableIndexPair.first)) { +// std::cout << this->getAbstractionInformation().getPredicateByIndex(variableIndexPair.second) << " is true" << std::endl; result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second); } else { +// std::cout << this->getAbstractionInformation().getPredicateByIndex(variableIndexPair.second) << " is false" << std::endl; result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second); } } diff --git a/src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp b/src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp index 49b0af65f..2d80f80eb 100644 --- a/src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp +++ b/src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp @@ -294,8 +294,10 @@ namespace storm { STORM_LOG_TRACE("Starting iteration " << iterations << "."); // (1) build initial abstraction based on the the constraint expression (if not 'true') and the target state expression. + auto abstractionStart = std::chrono::high_resolution_clock::now(); storm::abstraction::MenuGame game = abstractor.abstract(); - STORM_LOG_DEBUG("Abstraction in iteration " << iterations << " has " << game.getNumberOfStates() << " (player 1) states and " << game.getNumberOfTransitions() << " transitions."); + auto abstractionEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Abstraction in iteration " << iterations << " has " << game.getNumberOfStates() << " (player 1) states and " << game.getNumberOfTransitions() << " transitions (computed in " << std::chrono::duration_cast(abstractionEnd - abstractionStart).count() << "ms)."); STORM_LOG_THROW(game.getInitialStates().getNonZeroCount(), storm::exceptions::InvalidModelException, "Cannot treat models with more than one (abstract) initial state."); // (2) Prepare transition matrix BDD and target state BDD for later use. @@ -340,9 +342,12 @@ namespace storm { } else { STORM_LOG_DEBUG("Obtained qualitative bounds [0, 1] on the actual value for the initial states."); + auto qualitativeRefinementStart = std::chrono::high_resolution_clock::now(); // If we get here, the initial states were all identified as prob0/1 states, but the value (0 or 1) // depends on whether player 2 is minimizing or maximizing. Therefore, we need to find a place to refine. qualitativeRefinement = refiner.refine(game, transitionMatrixBdd, qualitativeResult); + auto qualitativeRefinementEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Qualitative refinement completed in " << std::chrono::duration_cast(qualitativeRefinementEnd - qualitativeRefinementStart).count() << "ms."); } } @@ -389,9 +394,13 @@ namespace storm { STORM_LOG_ASSERT(quantitativeResult.min.player2Strategy.isZero() || quantitativeResult.min.player2Strategy.template toAdd().sumAbstract(game.getPlayer2Variables()).getMax() <= 1, "Player 2 strategy for min is illegal."); STORM_LOG_ASSERT(quantitativeResult.max.player2Strategy.isZero() || quantitativeResult.max.player2Strategy.template toAdd().sumAbstract(game.getPlayer2Variables()).getMax() <= 1, "Player 2 strategy for max is illegal."); + auto quantitativeRefinementStart = std::chrono::high_resolution_clock::now(); // (10) If we arrived at this point, it means that we have all qualitative and quantitative // information about the game, but we could not yet answer the query. In this case, we need to refine. refiner.refine(game, transitionMatrixBdd, quantitativeResult); + auto quantitativeRefinementEnd = std::chrono::high_resolution_clock::now(); + STORM_LOG_DEBUG("Quantitative refinement completed in " << std::chrono::duration_cast(quantitativeRefinementEnd - quantitativeRefinementStart).count() << "ms."); + } auto iterationEnd = std::chrono::high_resolution_clock::now(); STORM_LOG_DEBUG("Iteration " << iterations << " took " << std::chrono::duration_cast(iterationEnd - iterationStart).count() << "ms.");