|
|
@ -128,9 +128,13 @@ namespace storm { |
|
|
|
std::pair<std::unique_ptr<CheckResult>, std::unique_ptr<CheckResult>> bounds = computeBounds(*abstractModel); |
|
|
|
|
|
|
|
// Try to derive the final result from the obtained bounds.
|
|
|
|
if (bounds.first || bounds.second) { |
|
|
|
result = tryToObtainResultFromBounds(*abstractModel, bounds); |
|
|
|
} |
|
|
|
if (!result) { |
|
|
|
if (bounds.first && bounds.second) { |
|
|
|
printBoundsInformation(bounds); |
|
|
|
} |
|
|
|
|
|
|
|
auto refinementStart = std::chrono::high_resolution_clock::now(); |
|
|
|
this->refineAbstractModel(); |
|
|
@ -181,40 +185,11 @@ namespace storm { |
|
|
|
} else if (checkForResultAfterQuantitativeCheck(abstractModel, false, result.second->asQuantitativeCheckResult<ValueType>())) { |
|
|
|
result.first = nullptr; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// In this case, we construct the full results from the qualitative results.
|
|
|
|
result = createBoundsFromQualitativeResults(abstractModel, *lastQualitativeResults); |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
std::pair<std::unique_ptr<CheckResult>, std::unique_ptr<CheckResult>> AbstractAbstractionRefinementModelChecker<ModelType>::createBoundsFromQualitativeResults(storm::models::Model<ValueType> const& abstractModel, storm::abstraction::QualitativeResultMinMax const& qualitativeResults) { |
|
|
|
|
|
|
|
STORM_LOG_THROW(qualitativeResults.isSymbolic(), storm::exceptions::NotSupportedException, "Expected symbolic bounds."); |
|
|
|
|
|
|
|
return createBoundsFromQualitativeResults(*abstractModel.template as<storm::models::symbolic::Model<DdType, ValueType>>(), qualitativeResults.asSymbolicQualitativeResultMinMax<DdType>()); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
std::pair<std::unique_ptr<CheckResult>, std::unique_ptr<CheckResult>> AbstractAbstractionRefinementModelChecker<ModelType>::createBoundsFromQualitativeResults(storm::models::symbolic::Model<DdType, ValueType> const& abstractModel, storm::abstraction::SymbolicQualitativeResultMinMax<DdType> const& qualitativeResults) { |
|
|
|
|
|
|
|
std::unique_ptr<CheckResult> lowerBounds; |
|
|
|
std::unique_ptr<CheckResult> upperBounds; |
|
|
|
|
|
|
|
bool isRewardFormula = checkTask->getFormula().isEventuallyFormula() && checkTask->getFormula().asEventuallyFormula().getContext() == storm::logic::FormulaContext::Reward; |
|
|
|
if (isRewardFormula) { |
|
|
|
lowerBounds = std::make_unique<SymbolicQuantitativeCheckResult<DdType, ValueType>>(abstractModel.getReachableStates(), abstractModel.getInitialStates(), abstractModel.getInitialStates().ite(qualitativeResults.getProb1Min().getStates().ite(abstractModel.getManager().template getAddZero<ValueType>(), abstractModel.getManager().template getConstant<ValueType>(storm::utility::infinity<ValueType>())), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
upperBounds = std::make_unique<SymbolicQuantitativeCheckResult<DdType, ValueType>>(abstractModel.getReachableStates(), abstractModel.getInitialStates(), abstractModel.getInitialStates().ite(qualitativeResults.getProb1Max().getStates().ite(abstractModel.getManager().template getAddZero<ValueType>(), abstractModel.getManager().template getConstant<ValueType>(storm::utility::infinity<ValueType>())), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
} else { |
|
|
|
lowerBounds = std::make_unique<SymbolicQuantitativeCheckResult<DdType, ValueType>>(abstractModel.getReachableStates(), abstractModel.getInitialStates(), abstractModel.getInitialStates().ite(qualitativeResults.getProb1Min().getStates().template toAdd<ValueType>(), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
upperBounds = std::make_unique<SymbolicQuantitativeCheckResult<DdType, ValueType>>(abstractModel.getReachableStates(), abstractModel.getInitialStates(), abstractModel.getInitialStates().ite(qualitativeResults.getProb1Max().getStates().template toAdd<ValueType>(), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
} |
|
|
|
|
|
|
|
return std::make_pair<std::unique_ptr<CheckResult>, std::unique_ptr<CheckResult>>(std::move(lowerBounds), std::move(upperBounds)); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool AbstractAbstractionRefinementModelChecker<ModelType>::checkForResultAfterQuantitativeCheck(storm::models::Model<ValueType> const& abstractModel, bool lowerBounds, QuantitativeCheckResult<ValueType> const& quantitativeResult) { |
|
|
|
|
|
|
@ -242,7 +217,9 @@ namespace storm { |
|
|
|
} |
|
|
|
|
|
|
|
if (result) { |
|
|
|
STORM_LOG_TRACE("Check for result after quantiative check positive."); |
|
|
|
STORM_LOG_TRACE("Found result after quantiative check."); |
|
|
|
} else { |
|
|
|
STORM_LOG_TRACE("Did not find result after quantiative check."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -391,13 +368,24 @@ namespace storm { |
|
|
|
minStartValues = abstractModel.getManager().template getAddZero<ValueType>(); |
|
|
|
} |
|
|
|
|
|
|
|
uint64_t abstractionPlayer = this->getAbstractionPlayer(); |
|
|
|
if (isRewardFormula) { |
|
|
|
result.first = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeReachabilityRewards(storm::OptimizationDirection::Minimize, abstractModel, abstractModel.getTransitionMatrix(), abstractModel.getTransitionMatrix().notZero(), checkTask->isRewardModelSet() ? abstractModel.getRewardModel(checkTask->getRewardModel()) : abstractModel.getRewardModel(""), maybeMin, targetStates.getStates(), !qualitativeResults.getProb1Min().getStates() && abstractModel.getReachableStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), minStartValues); |
|
|
|
result.first = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeReachabilityRewards(abstractionPlayer == 1 ? storm::OptimizationDirection::Minimize : checkTask->getOptimizationDirection(), abstractModel, abstractModel.getTransitionMatrix(), abstractModel.getTransitionMatrix().notZero(), checkTask->isRewardModelSet() ? abstractModel.getRewardModel(checkTask->getRewardModel()) : abstractModel.getRewardModel(""), maybeMin, targetStates.getStates(), !qualitativeResults.getProb1Min().getStates() && abstractModel.getReachableStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), minStartValues); |
|
|
|
|
|
|
|
if (abstractionPlayer == 0) { |
|
|
|
result.second = result.first->clone(); |
|
|
|
} else { |
|
|
|
result.second = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeReachabilityRewards(storm::OptimizationDirection::Maximize, abstractModel, abstractModel.getTransitionMatrix(), abstractModel.getTransitionMatrix().notZero(), checkTask->isRewardModelSet() ? abstractModel.getRewardModel(checkTask->getRewardModel()) : abstractModel.getRewardModel(""), maybeMin, targetStates.getStates(), !qualitativeResults.getProb1Max().getStates() && abstractModel.getReachableStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), maybeMax.ite(result.first->asSymbolicQuantitativeCheckResult<DdType, ValueType>().getValueVector(), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
} |
|
|
|
} else { |
|
|
|
result.first = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeUntilProbabilities(abstractionPlayer == 1 ? storm::OptimizationDirection::Minimize : checkTask->getOptimizationDirection(), abstractModel, abstractModel.getTransitionMatrix(), maybeMin, qualitativeResults.getProb1Min().getStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), minStartValues); |
|
|
|
|
|
|
|
if (abstractionPlayer == 0) { |
|
|
|
result.second = result.first->clone(); |
|
|
|
} else { |
|
|
|
result.first = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeUntilProbabilities(storm::OptimizationDirection::Minimize, abstractModel, abstractModel.getTransitionMatrix(), maybeMin, qualitativeResults.getProb1Min().getStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), minStartValues); |
|
|
|
result.second = storm::modelchecker::helper::SymbolicMdpPrctlHelper<DdType, ValueType>::computeUntilProbabilities(storm::OptimizationDirection::Maximize, abstractModel, abstractModel.getTransitionMatrix(), maybeMax, qualitativeResults.getProb1Max().getStates(), storm::solver::GeneralSymbolicMinMaxLinearEquationSolverFactory<DdType, ValueType>(), maybeMax.ite(result.first->asSymbolicQuantitativeCheckResult<DdType, ValueType>().getValueVector(), abstractModel.getManager().template getAddZero<ValueType>())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
@ -510,38 +498,91 @@ namespace storm { |
|
|
|
auto start = std::chrono::high_resolution_clock::now(); |
|
|
|
bool isRewardFormula = checkTask->getFormula().isEventuallyFormula() && checkTask->getFormula().asEventuallyFormula().getContext() == storm::logic::FormulaContext::Reward; |
|
|
|
storm::dd::Bdd<DdType> transitionMatrixBdd = abstractModel.getTransitionMatrix().notZero(); |
|
|
|
uint64_t abstractionPlayer = this->getAbstractionPlayer(); |
|
|
|
if (this->getReuseQualitativeResults()) { |
|
|
|
if (isRewardFormula) { |
|
|
|
bool computedMin = false; |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Minimize) { |
|
|
|
auto states = storm::utility::graph::performProb1E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates(), lastQualitativeResults ? lastQualitativeResults->asSymbolicQualitativeResultMinMax<DdType>().getProb1Min().getStates() : storm::utility::graph::performProbGreater0E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Min = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
computedMin = true; |
|
|
|
} |
|
|
|
|
|
|
|
states = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Maximize) { |
|
|
|
auto states = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Max = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
if (!computedMin) { |
|
|
|
result->prob1Min = result->prob1Max; |
|
|
|
} |
|
|
|
} else { |
|
|
|
result->prob1Max = result->prob1Min; |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
bool computedMax = false; |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Maximize) { |
|
|
|
auto states = storm::utility::graph::performProb0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates()); |
|
|
|
result->prob0Max = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
states = storm::utility::graph::performProb1E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates(), lastQualitativeResults ? lastQualitativeResults->asSymbolicQualitativeResultMinMax<DdType>().getProb1Min().getStates() : storm::utility::graph::performProbGreater0E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Max = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
computedMax = true; |
|
|
|
} |
|
|
|
|
|
|
|
states = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, lastQualitativeResults ? lastQualitativeResults->asSymbolicQualitativeResultMinMax<DdType>().getProb1Min().getStates() : targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Minimize) { |
|
|
|
auto states = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, lastQualitativeResults ? lastQualitativeResults->asSymbolicQualitativeResultMinMax<DdType>().getProb1Min().getStates() : targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Min = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
|
|
|
|
states = storm::utility::graph::performProb0E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates()); |
|
|
|
result->prob0Min = storm::abstraction::QualitativeMdpResult<DdType>(states); |
|
|
|
|
|
|
|
if (!computedMax) { |
|
|
|
result->prob0Max = result->prob0Min; |
|
|
|
result->prob1Max = result->prob1Min; |
|
|
|
} |
|
|
|
} else { |
|
|
|
result->prob0Min = result->prob0Max; |
|
|
|
result->prob1Min = result->prob1Max; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (isRewardFormula) { |
|
|
|
bool computedMin = false; |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Minimize) { |
|
|
|
auto prob1 = storm::utility::graph::performProb1E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates(), storm::utility::graph::performProbGreater0E(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Min = storm::abstraction::QualitativeMdpResult<DdType>(prob1); |
|
|
|
prob1 = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
computedMin = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Maximize) { |
|
|
|
auto prob1 = storm::utility::graph::performProb1A(abstractModel, transitionMatrixBdd, targetStates.getStates(), storm::utility::graph::performProbGreater0A(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates())); |
|
|
|
result->prob1Max = storm::abstraction::QualitativeMdpResult<DdType>(prob1); |
|
|
|
if (!computedMin) { |
|
|
|
result->prob1Min = result->prob1Max; |
|
|
|
} |
|
|
|
} else { |
|
|
|
result->prob1Max = result->prob1Min; |
|
|
|
} |
|
|
|
} else { |
|
|
|
bool computedMin = false; |
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Minimize) { |
|
|
|
auto prob01 = storm::utility::graph::performProb01Min(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates()); |
|
|
|
result->prob0Min = storm::abstraction::QualitativeMdpResult<DdType>(prob01.first); |
|
|
|
result->prob1Min = storm::abstraction::QualitativeMdpResult<DdType>(prob01.second); |
|
|
|
prob01 = storm::utility::graph::performProb01Max(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates()); |
|
|
|
computedMin = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (abstractionPlayer == 1 || checkTask->getOptimizationDirection() == storm::OptimizationDirection::Maximize) { |
|
|
|
auto prob01 = storm::utility::graph::performProb01Max(abstractModel, transitionMatrixBdd, constraintStates.getStates(), targetStates.getStates()); |
|
|
|
result->prob0Max = storm::abstraction::QualitativeMdpResult<DdType>(prob01.first); |
|
|
|
result->prob1Max = storm::abstraction::QualitativeMdpResult<DdType>(prob01.second); |
|
|
|
if (!computedMin) { |
|
|
|
result->prob0Min = result->prob0Max; |
|
|
|
result->prob1Min = result->prob1Max; |
|
|
|
} |
|
|
|
} else { |
|
|
|
result->prob0Max = result->prob0Min; |
|
|
|
result->prob1Max = result->prob1Min; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
auto end = std::chrono::high_resolution_clock::now(); |
|
|
@ -690,7 +731,9 @@ namespace storm { |
|
|
|
} |
|
|
|
|
|
|
|
if (result) { |
|
|
|
STORM_LOG_TRACE("Check for result after qualitative check positive."); |
|
|
|
STORM_LOG_TRACE("Found result after qualitative check."); |
|
|
|
} else { |
|
|
|
STORM_LOG_TRACE("Did not find result after qualitative check."); |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
@ -710,6 +753,7 @@ namespace storm { |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (boundsAreSufficientlyClose(bounds)) { |
|
|
|
STORM_LOG_TRACE("Obtained bounds are sufficiently close."); |
|
|
|
result = getAverageOfBounds(bounds); |
|
|
|
} |
|
|
|
} |
|
|
|