Browse Source
Merge branch 'master' of https://sselab.de/lab9/private/git/storm
Merge branch 'master' of https://sselab.de/lab9/private/git/storm
Former-commit-id: 82835c1f72
main
39 changed files with 2663 additions and 154 deletions
-
6examples/ctmc/tandem/tandem.sm
-
8src/builder/DdPrismModelBuilder.cpp
-
29src/builder/ExplicitPrismModelBuilder.cpp
-
364src/modelchecker/csl/HybridCtmcCslModelChecker.cpp
-
65src/modelchecker/csl/HybridCtmcCslModelChecker.h
-
106src/modelchecker/csl/SparseCtmcCslModelChecker.cpp
-
9src/modelchecker/csl/SparseCtmcCslModelChecker.h
-
17src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp
-
7src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h
-
330src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp
-
44src/modelchecker/prctl/HybridMdpPrctlModelChecker.h
-
2src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp
-
13src/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp
-
2src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp
-
13src/modelchecker/results/HybridQuantitativeCheckResult.cpp
-
2src/modelchecker/results/HybridQuantitativeCheckResult.h
-
7src/models/symbolic/Ctmc.cpp
-
10src/models/symbolic/Ctmc.h
-
10src/models/symbolic/Model.cpp
-
14src/models/symbolic/Model.h
-
6src/settings/Argument.h
-
277src/storage/dd/CuddAdd.cpp
-
115src/storage/dd/CuddAdd.h
-
16src/storage/dd/CuddOdd.cpp
-
24src/storage/dd/CuddOdd.h
-
15src/storage/prism/Program.cpp
-
49src/utility/cli.h
-
2src/utility/graph.h
-
88test/functional/builder/leader4.nm
-
28test/functional/modelchecker/GmmxxCtmcCslModelCheckerTest.cpp
-
279test/functional/modelchecker/GmmxxHybridCtmcCslModelCheckerTest.cpp
-
190test/functional/modelchecker/GmmxxHybridMdpPrctlModelCheckerTest.cpp
-
32test/functional/modelchecker/NativeCtmcCslModelCheckerTest.cpp
-
0test/functional/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp
-
279test/functional/modelchecker/NativeHybridCtmcCslModelCheckerTest.cpp
-
165test/functional/modelchecker/NativeHybridDtmcPrctlModelCheckerTest.cpp
-
190test/functional/modelchecker/NativeHybridMdpPrctlModelCheckerTest.cpp
-
0test/functional/modelchecker/NativeMdpPrctlModelCheckerTest.cpp
-
4test/functional/storage/CuddDdTest.cpp
@ -0,0 +1,364 @@ |
|||
#include "src/modelchecker/csl/HybridCtmcCslModelChecker.h"
|
|||
#include "src/modelchecker/csl/SparseCtmcCslModelChecker.h"
|
|||
#include "src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h"
|
|||
|
|||
#include "src/storage/dd/CuddOdd.h"
|
|||
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/utility/graph.h"
|
|||
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h"
|
|||
|
|||
#include "src/exceptions/InvalidStateException.h"
|
|||
#include "src/exceptions/InvalidPropertyException.h"
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(new storm::utility::solver::LinearEquationSolverFactory<ValueType>()) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(std::move(linearEquationSolverFactory)) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
bool HybridCtmcCslModelChecker<DdType, ValueType>::canHandle(storm::logic::Formula const& formula) const { |
|||
return formula.isCslStateFormula() || formula.isCslPathFormula() || formula.isRewardPathFormula(); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
storm::dd::Add<DdType> HybridCtmcCslModelChecker<DdType, ValueType>::computeProbabilityMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector) { |
|||
return rateMatrix / exitRateVector; |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.getLeftSubformula()); |
|||
std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.getRightSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
SymbolicQualitativeCheckResult<DdType> const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
|
|||
return HybridDtmcPrctlModelChecker<DdType, ValueType>::computeUntilProbabilitiesHelper(this->getModel(), this->computeProbabilityMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
std::unique_ptr<CheckResult> subResultPointer = this->check(pathFormula.getSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& subResult = subResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), HybridDtmcPrctlModelChecker<DdType, ValueType>::computeNextProbabilitiesHelper(this->getModel(), this->computeProbabilityMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()), subResult.getTruthValuesVector()))); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
storm::models::symbolic::Ctmc<DdType> const& HybridCtmcCslModelChecker<DdType, ValueType>::getModel() const { |
|||
return this->template getModelAs<storm::models::symbolic::Ctmc<DdType>>(); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
storm::dd::Add<DdType> HybridCtmcCslModelChecker<DdType, ValueType>::computeUniformizedMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate) { |
|||
STORM_LOG_DEBUG("Computing uniformized matrix using uniformization rate " << uniformizationRate << "."); |
|||
STORM_LOG_DEBUG("Keeping " << maybeStates.getNonZeroCount() << " rows."); |
|||
|
|||
// Cut all non-maybe rows/columns from the transition matrix.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = transitionMatrix * maybeStates.toAdd() * maybeStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd(); |
|||
|
|||
// Now perform the uniformization.
|
|||
uniformizedMatrix = uniformizedMatrix / model.getManager().getConstant(uniformizationRate); |
|||
storm::dd::Add<DdType> diagonal = model.getRowColumnIdentity() * maybeStates.toAdd(); |
|||
storm::dd::Add<DdType> diagonalOffset = diagonal; |
|||
diagonalOffset -= diagonal * (exitRateVector / model.getManager().getConstant(uniformizationRate)); |
|||
uniformizedMatrix += diagonalOffset; |
|||
|
|||
return uniformizedMatrix; |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
std::unique_ptr<CheckResult> subResultPointer = this->check(rewardPathFormula.getSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& subResult = subResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
|
|||
boost::optional<storm::dd::Add<DdType>> modifiedStateRewardVector; |
|||
if (this->getModel().hasStateRewards()) { |
|||
modifiedStateRewardVector = this->getModel().getStateRewardVector() / this->getModel().getExitRateVector(); |
|||
} |
|||
|
|||
return HybridDtmcPrctlModelChecker<DdType, ValueType>::computeReachabilityRewardsHelper(this->getModel(), this->computeProbabilityMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()), modifiedStateRewardVector, this->getModel().getOptionalTransitionRewardMatrix(), subResult.getTruthValuesVector(), *linearEquationSolverFactory, qualitative); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.getLeftSubformula()); |
|||
std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.getRightSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
SymbolicQualitativeCheckResult<DdType> const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
double lowerBound = 0; |
|||
double upperBound = 0; |
|||
if (!pathFormula.hasDiscreteTimeBound()) { |
|||
std::pair<double, double> const& intervalBounds = pathFormula.getIntervalBounds(); |
|||
lowerBound = intervalBounds.first; |
|||
upperBound = intervalBounds.second; |
|||
} else { |
|||
upperBound = pathFormula.getDiscreteTimeBound(); |
|||
} |
|||
|
|||
return this->computeBoundedUntilProbabilitiesHelper(leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), qualitative, lowerBound, upperBound); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeBoundedUntilProbabilitiesHelper(storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, storm::dd::Add<DdType> const& exitRates, bool qualitative, double lowerBound, double upperBound) const { |
|||
// If the time bounds are [0, inf], we rather call untimed reachability.
|
|||
storm::utility::ConstantsComparator<ValueType> comparator; |
|||
if (comparator.isZero(lowerBound) && comparator.isInfinity(upperBound)) { |
|||
return HybridDtmcPrctlModelChecker<DdType, ValueType>::computeUntilProbabilitiesHelper(this->getModel(), this->computeProbabilityMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()), phiStates, psiStates, qualitative, *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
// From this point on, we know that we have to solve a more complicated problem [t, t'] with either t != 0
|
|||
// or t' != inf.
|
|||
|
|||
// If we identify the states that have probability 0 of reaching the target states, we can exclude them from the
|
|||
// further computations.
|
|||
storm::dd::Bdd<DdType> statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(this->getModel(), this->getModel().getTransitionMatrix().notZero(), phiStates, psiStates); |
|||
STORM_LOG_INFO("Found " << statesWithProbabilityGreater0.getNonZeroCount() << " states with probability greater 0."); |
|||
storm::dd::Bdd<DdType> statesWithProbabilityGreater0NonPsi = statesWithProbabilityGreater0 && !psiStates; |
|||
STORM_LOG_INFO("Found " << statesWithProbabilityGreater0NonPsi.getNonZeroCount() << " 'maybe' states."); |
|||
|
|||
if (!statesWithProbabilityGreater0NonPsi.isZero()) { |
|||
if (comparator.isZero(upperBound)) { |
|||
// In this case, the interval is of the form [0, 0].
|
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), psiStates.toAdd())); |
|||
} else { |
|||
if (comparator.isZero(lowerBound)) { |
|||
// In this case, the interval is of the form [0, t].
|
|||
// Note that this excludes [0, inf] since this is untimed reachability and we considered this case earlier.
|
|||
|
|||
// Find the maximal rate of all 'maybe' states to take it as the uniformization rate.
|
|||
ValueType uniformizationRate = 1.02 * (statesWithProbabilityGreater0NonPsi.toAdd() * exitRates).getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
// Compute the uniformized matrix.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), exitRates, statesWithProbabilityGreater0NonPsi, uniformizationRate); |
|||
|
|||
// Compute the vector that is to be added as a compensation for removing the absorbing states.
|
|||
storm::dd::Add<DdType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * this->getModel().getTransitionMatrix() * psiStates.swapVariables(this->getModel().getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(this->getModel().getColumnVariables()) / this->getModel().getManager().getConstant(uniformizationRate); |
|||
|
|||
// Create an ODD for the translation to an explicit representation.
|
|||
storm::dd::Odd<DdType> odd(statesWithProbabilityGreater0NonPsi); |
|||
|
|||
// Convert the symbolic parts to their explicit representation.
|
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
std::vector<ValueType> explicitB = b.template toVector<ValueType>(odd); |
|||
|
|||
// Finally compute the transient probabilities.
|
|||
std::vector<ValueType> values(statesWithProbabilityGreater0NonPsi.getNonZeroCount(), storm::utility::zero<ValueType>()); |
|||
std::vector<ValueType> subresult = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, &explicitB, upperBound, uniformizationRate, values, *this->linearEquationSolverFactory); |
|||
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), |
|||
(psiStates || !statesWithProbabilityGreater0) && this->getModel().getReachableStates(), |
|||
psiStates.toAdd(), |
|||
statesWithProbabilityGreater0NonPsi, |
|||
odd, subresult)); |
|||
} else if (comparator.isInfinity(upperBound)) { |
|||
// In this case, the interval is of the form [t, inf] with t != 0.
|
|||
|
|||
// Start by computing the (unbounded) reachability probabilities of reaching psi states while
|
|||
// staying in phi states.
|
|||
std::unique_ptr<CheckResult> unboundedResult = HybridDtmcPrctlModelChecker<DdType, ValueType>::computeUntilProbabilitiesHelper(this->getModel(), this->computeProbabilityMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()), phiStates, psiStates, qualitative, *this->linearEquationSolverFactory); |
|||
|
|||
// Compute the set of relevant states.
|
|||
storm::dd::Bdd<DdType> relevantStates = statesWithProbabilityGreater0 && phiStates; |
|||
|
|||
// Filter the unbounded result such that it only contains values for the relevant states.
|
|||
unboundedResult->filter(SymbolicQualitativeCheckResult<DdType>(this->getModel().getReachableStates(), relevantStates)); |
|||
|
|||
// Build an ODD for the relevant states.
|
|||
storm::dd::Odd<DdType> odd(relevantStates); |
|||
|
|||
std::vector<ValueType> result; |
|||
if (unboundedResult->isHybridQuantitativeCheckResult()) { |
|||
std::unique_ptr<CheckResult> explicitUnboundedResult = unboundedResult->asHybridQuantitativeCheckResult<DdType>().toExplicitQuantitativeCheckResult(); |
|||
result = std::move(explicitUnboundedResult->asExplicitQuantitativeCheckResult<ValueType>().getValueVector()); |
|||
} else { |
|||
STORM_LOG_THROW(unboundedResult->isSymbolicQuantitativeCheckResult(), storm::exceptions::InvalidStateException, "Expected check result of different type."); |
|||
result = unboundedResult->asSymbolicQuantitativeCheckResult<DdType>().getValueVector().template toVector<ValueType>(odd); |
|||
} |
|||
|
|||
// Determine the uniformization rate for the transient probability computation.
|
|||
ValueType uniformizationRate = 1.02 * (relevantStates.toAdd() * exitRates).getMax(); |
|||
|
|||
// Compute the uniformized matrix.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), exitRates, relevantStates, uniformizationRate); |
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
|
|||
// Compute the transient probabilities.
|
|||
result = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, lowerBound, uniformizationRate, result, *this->linearEquationSolverFactory); |
|||
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), !relevantStates && this->getModel().getReachableStates(), this->getModel().getManager().getAddZero(), relevantStates, odd, result)); |
|||
} else { |
|||
// In this case, the interval is of the form [t, t'] with t != 0 and t' != inf.
|
|||
|
|||
if (lowerBound != upperBound) { |
|||
// In this case, the interval is of the form [t, t'] with t != 0, t' != inf and t != t'.
|
|||
|
|||
// Find the maximal rate of all 'maybe' states to take it as the uniformization rate.
|
|||
ValueType uniformizationRate = 1.02 * (statesWithProbabilityGreater0NonPsi.toAdd() * exitRates).getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
// Compute the (first) uniformized matrix.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), exitRates, statesWithProbabilityGreater0NonPsi, uniformizationRate); |
|||
|
|||
// Create the one-step vector.
|
|||
storm::dd::Add<DdType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * this->getModel().getTransitionMatrix() * psiStates.swapVariables(this->getModel().getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(this->getModel().getColumnVariables()) / this->getModel().getManager().getConstant(uniformizationRate); |
|||
|
|||
// Build an ODD for the relevant states and translate the symbolic parts to their explicit representation.
|
|||
storm::dd::Odd<DdType> odd = storm::dd::Odd<DdType>(statesWithProbabilityGreater0NonPsi); |
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
std::vector<ValueType> explicitB = b.template toVector<ValueType>(odd); |
|||
|
|||
// Compute the transient probabilities.
|
|||
std::vector<ValueType> values(statesWithProbabilityGreater0NonPsi.getNonZeroCount(), storm::utility::zero<ValueType>()); |
|||
std::vector<ValueType> subResult = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, &explicitB, upperBound - lowerBound, uniformizationRate, values, *this->linearEquationSolverFactory); |
|||
|
|||
// Transform the explicit result to a hybrid check result, so we can easily convert it to
|
|||
// a symbolic qualitative format.
|
|||
HybridQuantitativeCheckResult<DdType> hybridResult(this->getModel().getReachableStates(), psiStates || (!statesWithProbabilityGreater0 && this->getModel().getReachableStates()), |
|||
psiStates.toAdd(), statesWithProbabilityGreater0NonPsi, odd, subResult); |
|||
|
|||
// Compute the set of relevant states.
|
|||
storm::dd::Bdd<DdType> relevantStates = statesWithProbabilityGreater0 && phiStates; |
|||
|
|||
// Filter the unbounded result such that it only contains values for the relevant states.
|
|||
hybridResult.filter(SymbolicQualitativeCheckResult<DdType>(this->getModel().getReachableStates(), relevantStates)); |
|||
|
|||
// Build an ODD for the relevant states.
|
|||
odd = storm::dd::Odd<DdType>(relevantStates); |
|||
|
|||
std::unique_ptr<CheckResult> explicitResult = hybridResult.toExplicitQuantitativeCheckResult(); |
|||
std::vector<ValueType> newSubresult = std::move(explicitResult->asExplicitQuantitativeCheckResult<ValueType>().getValueVector()); |
|||
|
|||
// Then compute the transient probabilities of being in such a state after t time units. For this,
|
|||
// we must re-uniformize the CTMC, so we need to compute the second uniformized matrix.
|
|||
uniformizationRate = 1.02 * (relevantStates.toAdd() * exitRates).getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
// If the lower and upper bounds coincide, we have only determined the relevant states at this
|
|||
// point, but we still need to construct the starting vector.
|
|||
if (lowerBound == upperBound) { |
|||
odd = storm::dd::Odd<DdType>(relevantStates); |
|||
newSubresult = psiStates.toAdd().template toVector<ValueType>(odd); |
|||
} |
|||
|
|||
// Finally, we compute the second set of transient probabilities.
|
|||
uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), exitRates, relevantStates, uniformizationRate); |
|||
explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
|
|||
newSubresult = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, lowerBound, uniformizationRate, newSubresult, *this->linearEquationSolverFactory); |
|||
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), !relevantStates && this->getModel().getReachableStates(), this->getModel().getManager().getAddZero(), relevantStates, odd, newSubresult)); |
|||
} else { |
|||
// In this case, the interval is of the form [t, t] with t != 0, t != inf.
|
|||
|
|||
// Build an ODD for the relevant states.
|
|||
storm::dd::Odd<DdType> odd = storm::dd::Odd<DdType>(statesWithProbabilityGreater0); |
|||
|
|||
std::vector<ValueType> newSubresult = psiStates.toAdd().template toVector<ValueType>(odd); |
|||
|
|||
// Then compute the transient probabilities of being in such a state after t time units. For this,
|
|||
// we must re-uniformize the CTMC, so we need to compute the second uniformized matrix.
|
|||
ValueType uniformizationRate = 1.02 * (statesWithProbabilityGreater0.toAdd() * exitRates).getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
// Finally, we compute the second set of transient probabilities.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), exitRates, statesWithProbabilityGreater0, uniformizationRate); |
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
|
|||
newSubresult = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, lowerBound, uniformizationRate, newSubresult, *this->linearEquationSolverFactory); |
|||
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), !statesWithProbabilityGreater0 && this->getModel().getReachableStates(), this->getModel().getManager().getAddZero(), statesWithProbabilityGreater0, odd, newSubresult)); |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), psiStates.toAdd())); |
|||
} |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
return this->computeInstantaneousRewardsHelper(rewardPathFormula.getContinuousTimeBound()); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeInstantaneousRewardsHelper(double timeBound) const { |
|||
// Only compute the result if the model has a state-based reward this->getModel().
|
|||
STORM_LOG_THROW(this->getModel().hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); |
|||
|
|||
// Create ODD for the translation.
|
|||
storm::dd::Odd<DdType> odd(this->getModel().getReachableStates()); |
|||
|
|||
// Initialize result to state rewards of the this->getModel().
|
|||
std::vector<ValueType> result = this->getModel().getStateRewardVector().template toVector<ValueType>(odd); |
|||
|
|||
// If the time-bound is not zero, we need to perform a transient analysis.
|
|||
if (timeBound > 0) { |
|||
ValueType uniformizationRate = 1.02 * this->getModel().getExitRateVector().getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), this->getModel().getReachableStates(), uniformizationRate); |
|||
|
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
result = SparseCtmcCslModelChecker<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, timeBound, uniformizationRate, result, *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), this->getModel().getManager().getBddZero(), this->getModel().getManager().getAddZero(), this->getModel().getReachableStates(), odd, result)); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
return this->computeCumulativeRewardsHelper(rewardPathFormula.getContinuousTimeBound()); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
std::unique_ptr<CheckResult> HybridCtmcCslModelChecker<DdType, ValueType>::computeCumulativeRewardsHelper(double timeBound) const { |
|||
// Only compute the result if the model has a state-based reward this->getModel().
|
|||
STORM_LOG_THROW(this->getModel().hasStateRewards() || this->getModel().hasTransitionRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); |
|||
|
|||
// If the time bound is zero, the result is the constant zero vector.
|
|||
if (timeBound == 0) { |
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), this->getModel().getManager().getAddZero())); |
|||
} |
|||
|
|||
// Otherwise, we need to perform some computations.
|
|||
|
|||
// Start with the uniformization.
|
|||
ValueType uniformizationRate = 1.02 * this->getModel().getExitRateVector().getMax(); |
|||
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive."); |
|||
|
|||
// Create ODD for the translation.
|
|||
storm::dd::Odd<DdType> odd(this->getModel().getReachableStates()); |
|||
|
|||
// Compute the uniformized matrix.
|
|||
storm::dd::Add<DdType> uniformizedMatrix = this->computeUniformizedMatrix(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), this->getModel().getReachableStates(), uniformizationRate); |
|||
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd); |
|||
|
|||
// Then compute the state reward vector to use in the computation.
|
|||
storm::dd::Add<DdType> totalRewardVector = this->getModel().hasStateRewards() ? this->getModel().getStateRewardVector() : this->getModel().getManager().getAddZero(); |
|||
if (this->getModel().hasTransitionRewards()) { |
|||
totalRewardVector += (this->getModel().getTransitionMatrix() * this->getModel().getTransitionRewardMatrix()).sumAbstract(this->getModel().getColumnVariables()); |
|||
} |
|||
std::vector<ValueType> explicitTotalRewardVector = totalRewardVector.template toVector<ValueType>(odd); |
|||
|
|||
// Finally, compute the transient probabilities.
|
|||
std::vector<ValueType> result = SparseCtmcCslModelChecker<ValueType>::template computeTransientProbabilities<true>(explicitUniformizedMatrix, nullptr, timeBound, uniformizationRate, explicitTotalRewardVector, *this->linearEquationSolverFactory); |
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), this->getModel().getManager().getBddZero(), this->getModel().getManager().getAddZero(), this->getModel().getReachableStates(), odd, result)); |
|||
} |
|||
|
|||
// Explicitly instantiate the model checker.
|
|||
template class HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double>; |
|||
|
|||
} // namespace modelchecker
|
|||
} // namespace storm
|
@ -0,0 +1,65 @@ |
|||
#ifndef STORM_MODELCHECKER_HYBRIDCTMCCSLMODELCHECKER_H_ |
|||
#define STORM_MODELCHECKER_HYBRIDCTMCCSLMODELCHECKER_H_ |
|||
|
|||
#include "src/modelchecker/propositional/SymbolicPropositionalModelChecker.h" |
|||
#include "src/models/symbolic/Ctmc.h" |
|||
#include "src/utility/solver.h" |
|||
#include "src/solver/LinearEquationSolver.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
|
|||
template<storm::dd::DdType DdType, class ValueType> |
|||
class HybridCtmcCslModelChecker : public SymbolicPropositionalModelChecker<DdType> { |
|||
public: |
|||
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model); |
|||
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory); |
|||
|
|||
// The implemented methods of the AbstractModelChecker interface. |
|||
virtual bool canHandle(storm::logic::Formula const& formula) const override; |
|||
virtual std::unique_ptr<CheckResult> computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
|
|||
protected: |
|||
storm::models::symbolic::Ctmc<DdType> const& getModel() const override; |
|||
|
|||
private: |
|||
/*! |
|||
* Converts the given rate-matrix into a time-abstract probability matrix. |
|||
* |
|||
* @param model The symbolic model. |
|||
* @param rateMatrix The rate matrix. |
|||
* @param exitRateVector The exit rate vector of the model. |
|||
* @return The probability matrix. |
|||
*/ |
|||
static storm::dd::Add<DdType> computeProbabilityMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector); |
|||
|
|||
/*! |
|||
* Computes the matrix representing the transitions of the uniformized CTMC. |
|||
* |
|||
* @param model The symbolic model. |
|||
* @param transitionMatrix The matrix to uniformize. |
|||
* @param exitRateVector The exit rate vector. |
|||
* @param maybeStates The states that need to be considered. |
|||
* @param uniformizationRate The rate to be used for uniformization. |
|||
* @return The uniformized matrix. |
|||
*/ |
|||
static storm::dd::Add<DdType> computeUniformizedMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate); |
|||
|
|||
// The methods that perform the actual checking. |
|||
std::unique_ptr<CheckResult> computeBoundedUntilProbabilitiesHelper(storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, storm::dd::Add<DdType> const& exitRates, bool qualitative, double lowerBound, double upperBound) const; |
|||
std::unique_ptr<CheckResult> computeInstantaneousRewardsHelper(double timeBound) const; |
|||
std::unique_ptr<CheckResult> computeCumulativeRewardsHelper(double timeBound) const; |
|||
|
|||
// An object that is used for solving linear equations and performing matrix-vector multiplication. |
|||
std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>> linearEquationSolverFactory; |
|||
}; |
|||
|
|||
} // namespace modelchecker |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_MODELCHECKER_HYBRIDCTMCCSLMODELCHECKER_H_ */ |
@ -0,0 +1,330 @@ |
|||
#include "src/modelchecker/prctl/HybridMdpPrctlModelChecker.h"
|
|||
|
|||
#include "src/storage/dd/CuddOdd.h"
|
|||
|
|||
#include "src/utility/macros.h"
|
|||
#include "src/utility/graph.h"
|
|||
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
|
|||
#include "src/exceptions/InvalidStateException.h"
|
|||
#include "src/exceptions/InvalidPropertyException.h"
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
HybridMdpPrctlModelChecker<DdType, ValueType>::HybridMdpPrctlModelChecker(storm::models::symbolic::Mdp<DdType> const& model, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(std::move(linearEquationSolverFactory)) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
HybridMdpPrctlModelChecker<DdType, ValueType>::HybridMdpPrctlModelChecker(storm::models::symbolic::Mdp<DdType> const& model) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(new storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType>()) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
bool HybridMdpPrctlModelChecker<DdType, ValueType>::canHandle(storm::logic::Formula const& formula) const { |
|||
return formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula(); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeUntilProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) { |
|||
// We need to identify the states which have to be taken out of the matrix, i.e. all states that have
|
|||
// probability 0 and 1 of satisfying the until-formula.
|
|||
std::pair<storm::dd::Bdd<DdType>, storm::dd::Bdd<DdType>> statesWithProbability01; |
|||
if (minimize) { |
|||
statesWithProbability01 = storm::utility::graph::performProb01Min(model, phiStates, psiStates); |
|||
} else { |
|||
statesWithProbability01 = storm::utility::graph::performProb01Max(model, phiStates, psiStates); |
|||
} |
|||
storm::dd::Bdd<DdType> maybeStates = !statesWithProbability01.first && !statesWithProbability01.second && model.getReachableStates(); |
|||
|
|||
// Perform some logging.
|
|||
STORM_LOG_INFO("Found " << statesWithProbability01.first.getNonZeroCount() << " 'no' states."); |
|||
STORM_LOG_INFO("Found " << statesWithProbability01.second.getNonZeroCount() << " 'yes' states."); |
|||
STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); |
|||
|
|||
// Check whether we need to compute exact probabilities for some states.
|
|||
if (qualitative) { |
|||
// Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1.
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), statesWithProbability01.second.toAdd() + maybeStates.toAdd() * model.getManager().getConstant(0.5))); |
|||
} else { |
|||
// If there are maybe states, we need to solve an equation system.
|
|||
if (!maybeStates.isZero()) { |
|||
// Create the ODD for the translation between symbolic and explicit storage.
|
|||
storm::dd::Odd<DdType> odd(maybeStates); |
|||
|
|||
// Create the matrix and the vector for the equation system.
|
|||
storm::dd::Add<DdType> maybeStatesAdd = maybeStates.toAdd(); |
|||
|
|||
// Start by cutting away all rows that do not belong to maybe states. Note that this leaves columns targeting
|
|||
// non-maybe states in the matrix.
|
|||
storm::dd::Add<DdType> submatrix = transitionMatrix * maybeStatesAdd; |
|||
|
|||
// Then compute the vector that contains the one-step probabilities to a state with probability 1 for all
|
|||
// maybe states.
|
|||
storm::dd::Add<DdType> prob1StatesAsColumn = statesWithProbability01.second.toAdd(); |
|||
prob1StatesAsColumn = prob1StatesAsColumn.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> subvector = submatrix * prob1StatesAsColumn; |
|||
subvector = subvector.sumAbstract(model.getColumnVariables()); |
|||
|
|||
// Before cutting the non-maybe columns, we need to compute the sizes of the row groups.
|
|||
std::vector<uint_fast64_t> rowGroupSizes = submatrix.notZero().existsAbstract(model.getColumnVariables()).toAdd().sumAbstract(model.getNondeterminismVariables()).template toVector<uint_fast64_t>(odd); |
|||
|
|||
// Finally cut away all columns targeting non-maybe states.
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
|
|||
// Create the solution vector.
|
|||
std::vector<ValueType> x(maybeStates.getNonZeroCount(), ValueType(0.5)); |
|||
|
|||
// Translate the symbolic matrix/vector to their explicit representations and solve the equation system.
|
|||
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> explicitRepresentation = submatrix.toMatrixVector(subvector, std::move(rowGroupSizes), model.getNondeterminismVariables(), odd, odd); |
|||
|
|||
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(explicitRepresentation.first); |
|||
solver->solveEquationSystem(minimize, x, explicitRepresentation.second); |
|||
|
|||
// Return a hybrid check result that stores the numerical values explicitly.
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::HybridQuantitativeCheckResult<DdType>(model.getReachableStates(), model.getReachableStates() && !maybeStates, statesWithProbability01.second.toAdd(), maybeStates, odd, x)); |
|||
} else { |
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), statesWithProbability01.second.toAdd())); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.getLeftSubformula()); |
|||
std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.getRightSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
SymbolicQualitativeCheckResult<DdType> const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
return this->computeUntilProbabilitiesHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
std::unique_ptr<CheckResult> subResultPointer = this->check(pathFormula.getSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& subResult = subResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(this->getModel().getReachableStates(), this->computeNextProbabilitiesHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()))); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
storm::dd::Add<DdType> HybridMdpPrctlModelChecker<DdType, ValueType>::computeNextProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& nextStates) { |
|||
storm::dd::Add<DdType> result = transitionMatrix * nextStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd(); |
|||
return result.sumAbstract(model.getColumnVariables()); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); |
|||
std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.getLeftSubformula()); |
|||
std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.getRightSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
SymbolicQualitativeCheckResult<DdType> const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
return this->computeBoundedUntilProbabilitiesHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeBoundedUntilProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) { |
|||
// We need to identify the states which have to be taken out of the matrix, i.e. all states that have
|
|||
// probability 0 or 1 of satisfying the until-formula.
|
|||
storm::dd::Bdd<DdType> statesWithProbabilityGreater0; |
|||
if (minimize) { |
|||
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0A(model, transitionMatrix.notZero(), phiStates, psiStates); |
|||
} else { |
|||
statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0E(model, transitionMatrix.notZero(), phiStates, psiStates); |
|||
} |
|||
storm::dd::Bdd<DdType> maybeStates = statesWithProbabilityGreater0 && !psiStates && model.getReachableStates(); |
|||
|
|||
// If there are maybe states, we need to perform matrix-vector multiplications.
|
|||
if (!maybeStates.isZero()) { |
|||
// Create the ODD for the translation between symbolic and explicit storage.
|
|||
storm::dd::Odd<DdType> odd(maybeStates); |
|||
|
|||
// Create the matrix and the vector for the equation system.
|
|||
storm::dd::Add<DdType> maybeStatesAdd = maybeStates.toAdd(); |
|||
|
|||
// Start by cutting away all rows that do not belong to maybe states. Note that this leaves columns targeting
|
|||
// non-maybe states in the matrix.
|
|||
storm::dd::Add<DdType> submatrix = transitionMatrix * maybeStatesAdd; |
|||
|
|||
// Then compute the vector that contains the one-step probabilities to a state with probability 1 for all
|
|||
// maybe states.
|
|||
storm::dd::Add<DdType> prob1StatesAsColumn = psiStates.toAdd().swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> subvector = (submatrix * prob1StatesAsColumn).sumAbstract(model.getColumnVariables()); |
|||
|
|||
// Before cutting the non-maybe columns, we need to compute the sizes of the row groups.
|
|||
std::vector<uint_fast64_t> rowGroupSizes = submatrix.notZero().existsAbstract(model.getColumnVariables()).toAdd().sumAbstract(model.getNondeterminismVariables()).template toVector<uint_fast64_t>(odd); |
|||
|
|||
// Finally cut away all columns targeting non-maybe states.
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
|
|||
// Create the solution vector.
|
|||
std::vector<ValueType> x(maybeStates.getNonZeroCount(), storm::utility::zero<ValueType>()); |
|||
|
|||
// Translate the symbolic matrix/vector to their explicit representations.
|
|||
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> explicitRepresentation = submatrix.toMatrixVector(subvector, std::move(rowGroupSizes), model.getNondeterminismVariables(), odd, odd); |
|||
|
|||
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(explicitRepresentation.first); |
|||
solver->performMatrixVectorMultiplication(minimize, x, &explicitRepresentation.second, stepBound); |
|||
|
|||
// Return a hybrid check result that stores the numerical values explicitly.
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::HybridQuantitativeCheckResult<DdType>(model.getReachableStates(), model.getReachableStates() && !maybeStates, psiStates.toAdd(), maybeStates, odd, x)); |
|||
} else { |
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), psiStates.toAdd())); |
|||
} |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); |
|||
return this->computeCumulativeRewardsHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeCumulativeRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) { |
|||
// Only compute the result if the model has at least one reward this->getModel().
|
|||
STORM_LOG_THROW(model.hasStateRewards() || model.hasTransitionRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); |
|||
|
|||
// Compute the reward vector to add in each step based on the available reward models.
|
|||
storm::dd::Add<DdType> totalRewardVector = model.hasStateRewards() ? model.getStateRewardVector() : model.getManager().getAddZero(); |
|||
if (model.hasTransitionRewards()) { |
|||
totalRewardVector += (transitionMatrix * model.getTransitionRewardMatrix()).sumAbstract(model.getColumnVariables()); |
|||
} |
|||
|
|||
// Create the ODD for the translation between symbolic and explicit storage.
|
|||
storm::dd::Odd<DdType> odd(model.getReachableStates()); |
|||
|
|||
// Create the solution vector.
|
|||
std::vector<ValueType> x(model.getNumberOfStates(), storm::utility::zero<ValueType>()); |
|||
|
|||
// Translate the symbolic matrix/vector to their explicit representations.
|
|||
storm::storage::SparseMatrix<ValueType> explicitMatrix = transitionMatrix.toMatrix(model.getNondeterminismVariables(), odd, odd); |
|||
std::vector<ValueType> b = totalRewardVector.template toVector<ValueType>(model.getNondeterminismVariables(), odd, explicitMatrix.getRowGroupIndices()); |
|||
|
|||
// Perform the matrix-vector multiplication.
|
|||
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(explicitMatrix); |
|||
solver->performMatrixVectorMultiplication(minimize, x, &b, stepBound); |
|||
|
|||
// Return a hybrid check result that stores the numerical values explicitly.
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().getAddZero(), model.getReachableStates(), odd, x)); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); |
|||
return this->computeInstantaneousRewardsHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeInstantaneousRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) { |
|||
// Only compute the result if the model has at least one reward this->getModel().
|
|||
STORM_LOG_THROW(model.hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); |
|||
|
|||
// Create the ODD for the translation between symbolic and explicit storage.
|
|||
storm::dd::Odd<DdType> odd(model.getReachableStates()); |
|||
|
|||
// Translate the symbolic matrix to its explicit representations.
|
|||
storm::storage::SparseMatrix<ValueType> explicitMatrix = transitionMatrix.toMatrix(model.getNondeterminismVariables(), odd, odd); |
|||
|
|||
// Create the solution vector (and initialize it to the state rewards of the model).
|
|||
std::vector<ValueType> x = model.getStateRewardVector().template toVector<ValueType>(model.getNondeterminismVariables(), odd, explicitMatrix.getRowGroupIndices()); |
|||
|
|||
// Perform the matrix-vector multiplication.
|
|||
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(explicitMatrix); |
|||
solver->performMatrixVectorMultiplication(minimize, x, nullptr, stepBound); |
|||
|
|||
// Return a hybrid check result that stores the numerical values explicitly.
|
|||
return std::unique_ptr<CheckResult>(new HybridQuantitativeCheckResult<DdType>(model.getReachableStates(), model.getManager().getBddZero(), model.getManager().getAddZero(), model.getReachableStates(), odd, x)); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); |
|||
std::unique_ptr<CheckResult> subResultPointer = this->check(rewardPathFormula.getSubformula()); |
|||
SymbolicQualitativeCheckResult<DdType> const& subResult = subResultPointer->asSymbolicQualitativeCheckResult<DdType>(); |
|||
return this->computeReachabilityRewardsHelper(optimalityType.get() == storm::logic::OptimalityType::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getOptionalStateRewardVector(), this->getModel().getOptionalTransitionRewardMatrix(), subResult.getTruthValuesVector(), *this->linearEquationSolverFactory, qualitative); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> HybridMdpPrctlModelChecker<DdType, ValueType>::computeReachabilityRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, boost::optional<storm::dd::Add<DdType>> const& stateRewardVector, boost::optional<storm::dd::Add<DdType>> const& transitionRewardMatrix, storm::dd::Bdd<DdType> const& targetStates, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory, bool qualitative) { |
|||
|
|||
// Only compute the result if there is at least one reward model.
|
|||
STORM_LOG_THROW(stateRewardVector || transitionRewardMatrix, storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); |
|||
|
|||
// Determine which states have a reward of infinity by definition.
|
|||
storm::dd::Bdd<DdType> infinityStates; |
|||
storm::dd::Bdd<DdType> transitionMatrixBdd = transitionMatrix.notZero(); |
|||
if (minimize) { |
|||
infinityStates = storm::utility::graph::performProb1A(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0A(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); |
|||
} else { |
|||
infinityStates = storm::utility::graph::performProb1E(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0E(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); |
|||
} |
|||
infinityStates = !infinityStates && model.getReachableStates(); |
|||
storm::dd::Bdd<DdType> maybeStates = (!targetStates && !infinityStates) && model.getReachableStates(); |
|||
STORM_LOG_INFO("Found " << infinityStates.getNonZeroCount() << " 'infinity' states."); |
|||
STORM_LOG_INFO("Found " << targetStates.getNonZeroCount() << " 'target' states."); |
|||
STORM_LOG_INFO("Found " << maybeStates.getNonZeroCount() << " 'maybe' states."); |
|||
|
|||
// Check whether we need to compute exact rewards for some states.
|
|||
if (qualitative) { |
|||
// Set the values for all maybe-states to 1 to indicate that their reward values
|
|||
// are neither 0 nor infinity.
|
|||
return std::unique_ptr<CheckResult>(new SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), infinityStates.toAdd() * model.getManager().getConstant(storm::utility::infinity<ValueType>()) + maybeStates.toAdd() * model.getManager().getConstant(storm::utility::one<ValueType>()))); |
|||
} else { |
|||
// If there are maybe states, we need to solve an equation system.
|
|||
if (!maybeStates.isZero()) { |
|||
// Create the ODD for the translation between symbolic and explicit storage.
|
|||
storm::dd::Odd<DdType> odd(maybeStates); |
|||
|
|||
// Create the matrix and the vector for the equation system.
|
|||
storm::dd::Add<DdType> maybeStatesAdd = maybeStates.toAdd(); |
|||
|
|||
// Start by cutting away all rows that do not belong to maybe states. Note that this leaves columns targeting
|
|||
// non-maybe states in the matrix.
|
|||
storm::dd::Add<DdType> submatrix = transitionMatrix * maybeStatesAdd; |
|||
|
|||
// Then compute the state reward vector to use in the computation.
|
|||
storm::dd::Add<DdType> subvector = stateRewardVector ? maybeStatesAdd * stateRewardVector.get() : model.getManager().getAddZero(); |
|||
if (transitionRewardMatrix) { |
|||
subvector += (submatrix * transitionRewardMatrix.get()).sumAbstract(model.getColumnVariables()); |
|||
} |
|||
|
|||
// Before cutting the non-maybe columns, we need to compute the sizes of the row groups.
|
|||
std::vector<uint_fast64_t> rowGroupSizes = submatrix.notZero().existsAbstract(model.getColumnVariables()).toAdd().sumAbstract(model.getNondeterminismVariables()).template toVector<uint_fast64_t>(odd); |
|||
|
|||
// Finally cut away all columns targeting non-maybe states.
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
|
|||
// Create the solution vector.
|
|||
std::vector<ValueType> x(maybeStates.getNonZeroCount(), ValueType(0.5)); |
|||
|
|||
// Translate the symbolic matrix/vector to their explicit representations.
|
|||
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> explicitRepresentation = submatrix.toMatrixVector(subvector, std::move(rowGroupSizes), model.getNondeterminismVariables(), odd, odd); |
|||
|
|||
// Now solve the resulting equation system.
|
|||
std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(explicitRepresentation.first); |
|||
solver->solveEquationSystem(minimize, x, explicitRepresentation.second); |
|||
|
|||
// Return a hybrid check result that stores the numerical values explicitly.
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::HybridQuantitativeCheckResult<DdType>(model.getReachableStates(), model.getReachableStates() && !maybeStates, infinityStates.toAdd() * model.getManager().getConstant(storm::utility::infinity<ValueType>()), maybeStates, odd, x)); |
|||
} else { |
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), infinityStates.toAdd() * model.getManager().getConstant(storm::utility::infinity<ValueType>()))); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
storm::models::symbolic::Mdp<DdType> const& HybridMdpPrctlModelChecker<DdType, ValueType>::getModel() const { |
|||
return this->template getModelAs<storm::models::symbolic::Mdp<DdType>>(); |
|||
} |
|||
|
|||
template class HybridMdpPrctlModelChecker<storm::dd::DdType::CUDD, double>; |
|||
} |
|||
} |
@ -0,0 +1,44 @@ |
|||
#ifndef STORM_MODELCHECKER_HYBRIDMDPPRCTLMODELCHECKER_H_ |
|||
#define STORM_MODELCHECKER_HYBRIDMDPPRCTLMODELCHECKER_H_ |
|||
|
|||
#include "src/modelchecker/propositional/SymbolicPropositionalModelChecker.h" |
|||
#include "src/models/symbolic/Mdp.h" |
|||
#include "src/utility/solver.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
class HybridMdpPrctlModelChecker : public SymbolicPropositionalModelChecker<DdType> { |
|||
public: |
|||
explicit HybridMdpPrctlModelChecker(storm::models::symbolic::Mdp<DdType> const& model); |
|||
explicit HybridMdpPrctlModelChecker(storm::models::symbolic::Mdp<DdType> const& model, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory); |
|||
|
|||
// The implemented methods of the AbstractModelChecker interface. |
|||
virtual bool canHandle(storm::logic::Formula const& formula) const override; |
|||
virtual std::unique_ptr<CheckResult> computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
virtual std::unique_ptr<CheckResult> computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, bool qualitative = false, boost::optional<storm::logic::OptimalityType> const& optimalityType = boost::optional<storm::logic::OptimalityType>()) override; |
|||
|
|||
protected: |
|||
storm::models::symbolic::Mdp<DdType> const& getModel() const override; |
|||
|
|||
private: |
|||
// The methods that perform the actual checking. |
|||
static std::unique_ptr<CheckResult> computeBoundedUntilProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory); |
|||
static storm::dd::Add<DdType> computeNextProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& nextStates); |
|||
static std::unique_ptr<CheckResult> computeUntilProbabilitiesHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeCumulativeRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeInstantaneousRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeReachabilityRewardsHelper(bool minimize, storm::models::symbolic::NondeterministicModel<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, boost::optional<storm::dd::Add<DdType>> const& stateRewardVector, boost::optional<storm::dd::Add<DdType>> const& transitionRewardMatrix, storm::dd::Bdd<DdType> const& targetStates, storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory, bool qualitative); |
|||
|
|||
// An object that is used for retrieving linear equation solvers. |
|||
std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<ValueType>> linearEquationSolverFactory; |
|||
}; |
|||
|
|||
} // namespace modelchecker |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_MODELCHECKER_HYBRIDMDPPRCTLMODELCHECKER_H_ */ |
@ -0,0 +1,88 @@ |
|||
// asynchronous leader election |
|||
// 4 processes |
|||
// gxn/dxp 29/01/01 |
|||
|
|||
mdp |
|||
|
|||
const int N = 4; // number of processes |
|||
|
|||
module process1 |
|||
|
|||
// COUNTER |
|||
c1 : [0..N-1]; |
|||
|
|||
// STATES |
|||
s1 : [0..4]; |
|||
// 0 make choice |
|||
// 1 have not received neighbours choice |
|||
// 2 active |
|||
// 3 inactive |
|||
// 4 leader |
|||
|
|||
// PREFERENCE |
|||
p1 : [0..1]; |
|||
|
|||
// VARIABLES FOR SENDING AND RECEIVING |
|||
receive1 : [0..2]; |
|||
// not received anything |
|||
// received choice |
|||
// received counter |
|||
sent1 : [0..2]; |
|||
// not send anything |
|||
// sent choice |
|||
// sent counter |
|||
|
|||
// pick value |
|||
[] (s1=0) -> 0.5 : (s1'=1) & (p1'=0) + 0.5 : (s1'=1) & (p1'=1); |
|||
|
|||
// send preference |
|||
[p12] (s1=1) & (sent1=0) -> (sent1'=1); |
|||
// receive preference |
|||
// stay active |
|||
[p41] (s1=1) & (receive1=0) & !( (p1=0) & (p4=1) ) -> (s1'=2) & (receive1'=1); |
|||
// become inactive |
|||
[p41] (s1=1) & (receive1=0) & (p1=0) & (p4=1) -> (s1'=3) & (receive1'=1); |
|||
|
|||
// send preference (can now reset preference) |
|||
[p12] (s1=2) & (sent1=0) -> (sent1'=1) & (p1'=0); |
|||
// send counter (already sent preference) |
|||
// not received counter yet |
|||
[c12] (s1=2) & (sent1=1) & (receive1=1) -> (sent1'=2); |
|||
// received counter (pick again) |
|||
[c12] (s1=2) & (sent1=1) & (receive1=2) -> (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); |
|||
|
|||
// receive counter and not sent yet (note in this case do not pass it on as will send own counter) |
|||
[c41] (s1=2) & (receive1=1) & (sent1<2) -> (receive1'=2); |
|||
// receive counter and sent counter |
|||
// only active process (decide) |
|||
[c41] (s1=2) & (receive1=1) & (sent1=2) & (c4=N-1) -> (s1'=4) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); |
|||
// other active process (pick again) |
|||
[c41] (s1=2) & (receive1=1) & (sent1=2) & (c4<N-1) -> (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); |
|||
|
|||
// send preference (must have received preference) and can now reset |
|||
[p12] (s1=3) & (receive1>0) & (sent1=0) -> (sent1'=1) & (p1'=0); |
|||
// send counter (must have received counter first) and can now reset |
|||
[c12] (s1=3) & (receive1=2) & (sent1=1) -> (s1'=3) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); |
|||
|
|||
// receive preference |
|||
[p41] (s1=3) & (receive1=0) -> (p1'=p4) & (receive1'=1); |
|||
// receive counter |
|||
[c41] (s1=3) & (receive1=1) & (c4<N-1) -> (c1'=c4+1) & (receive1'=2); |
|||
|
|||
// done |
|||
[done] (s1=4) -> (s1'=s1); |
|||
// add loop for processes who are inactive |
|||
[done] (s1=3) -> (s1'=s1); |
|||
|
|||
endmodule |
|||
|
|||
module process2=process1[s1=s2,p1=p2,c1=c2,sent1=sent2,receive1=receive2,p12=p23,p41=p12,c12=c23,c41=c12,p4=p1,c4=c1] endmodule |
|||
module process3=process1[s1=s3,p1=p3,c1=c3,sent1=sent3,receive1=receive3,p12=p34,p41=p23,c12=c34,c41=c23,p4=p2,c4=c2] endmodule |
|||
module process4=process1[s1=s4,p1=p4,c1=c4,sent1=sent4,receive1=receive4,p12=p41,p41=p34,c12=c41,c41=c34,p4=p3,c4=c3] endmodule |
|||
|
|||
// reward - expected number of rounds (equals the number of times a process receives a counter) |
|||
rewards "rounds" |
|||
[c12] true : 1; |
|||
endrewards |
|||
|
|||
label "elected" = s1=4|s2=4|s3=4|s4=4; |
@ -0,0 +1,279 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
#include "src/settings/SettingMemento.h"
|
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/parser/FormulaParser.h"
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/builder/DdPrismModelBuilder.h"
|
|||
#include "src/storage/dd/DdType.h"
|
|||
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/csl/HybridCtmcCslModelChecker.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
|
|||
#include "src/settings/SettingsManager.h"
|
|||
|
|||
TEST(GmmxxHybridCtmcCslModelCheckerTest, Cluster) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/cluster2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "num_repairs"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=100 !\"minimum\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(5.5461254704419085E-5, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(5.5461254704419085E-5, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F[100,100] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(2.3397873548343415E-6, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(2.3397873548343415E-6, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F[100,2000] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.001105335651670241, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.001105335651670241, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ \"minimum\" U<=10 \"premium\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"minimum\" U[1,inf] \"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ \"minimum\" U[1,inf] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult6 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.9999999033633374, quantitativeCheckResult6.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.9999999033633374, quantitativeCheckResult6.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=100]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult7 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.8602815057967503, quantitativeCheckResult7.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.8602815057967503, quantitativeCheckResult7.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(GmmxxHybridCtmcCslModelCheckerTest, Embedded) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/embedded2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "up"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10000 \"down\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.0019216435246119591, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0019216435246119591, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_actuators\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(3.7079151806696567E-6, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(3.7079151806696567E-6, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_io\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.001556839327673734, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.001556839327673734, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_sensors\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(4.429620626755424E-5, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(4.429620626755424E-5, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=10000]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(2.7745274082080154, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(2.7745274082080154, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(GmmxxHybridCtmcCslModelCheckerTest, Polling) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/polling2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=?[ F<=10 \"target\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(GmmxxHybridCtmcCslModelCheckerTest, Fms) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// No properties to check at this point.
|
|||
} |
|||
|
|||
TEST(GmmxxHybridCtmcCslModelCheckerTest, Tandem) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/tandem5.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model with the customers reward structure.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "customers"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10 \"network_full\" ]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.015446370562428037, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.015446370562428037, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10 \"first_queue_full\" ]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.999999837225515, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.999999837225515, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [\"second_queue_full\" U<=1 !\"second_queue_full\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [I=10]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(5.679243850315877, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(5.679243850315877, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=10]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(55.44792186036232, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(55.44792186036232, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [F \"first_queue_full\"&\"second_queue_full\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult6 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(262.85103498583413, quantitativeCheckResult6.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(262.85103498583413, quantitativeCheckResult6.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
@ -0,0 +1,190 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/prctl/HybridMdpPrctlModelChecker.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/builder/DdPrismModelBuilder.h"
|
|||
#include "src/models/symbolic/Dtmc.h"
|
|||
#include "src/settings/SettingsManager.h"
|
|||
|
|||
TEST(GmmxxHybridMdpPrctlModelCheckerTest, Dice) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/two_dice.nm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "coinflips"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(169, model->getNumberOfStates()); |
|||
EXPECT_EQ(436, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxMinMaxLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("two"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
auto minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("three"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("four"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult6 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("done"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(labelFormula); |
|||
auto minRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Minimize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*minRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult7 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult7.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult7.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Maximize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*maxRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult8 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult8.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult8.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(GmmxxHybridMdpPrctlModelCheckerTest, AsynchronousLeader) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader4.nm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "rounds"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(3172, model->getNumberOfStates()); |
|||
EXPECT_EQ(7144, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxMinMaxLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
auto minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(true); |
|||
auto boundedUntilFormula = std::make_shared<storm::logic::BoundedUntilFormula>(trueFormula, labelFormula, 25); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, boundedUntilFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0625, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0625, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, boundedUntilFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0625, quantitativeResult4.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0625, quantitativeResult4.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(labelFormula); |
|||
auto minRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Minimize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*minRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(4.2856925589077264, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(4.2856925589077264, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Maximize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*maxRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult6 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(4.2856953906798676, quantitativeResult6.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(4.2856953906798676, quantitativeResult6.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
@ -0,0 +1,279 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
#include "src/settings/SettingMemento.h"
|
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/parser/FormulaParser.h"
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/builder/DdPrismModelBuilder.h"
|
|||
#include "src/storage/dd/DdType.h"
|
|||
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/csl/HybridCtmcCslModelChecker.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
|
|||
#include "src/settings/SettingsManager.h"
|
|||
|
|||
TEST(NativeHybridCtmcCslModelCheckerTest, Cluster) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/cluster2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "num_repairs"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=100 !\"minimum\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(5.5461254704419085E-5, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(5.5461254704419085E-5, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F[100,100] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(2.3397873548343415E-6, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(2.3397873548343415E-6, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F[100,2000] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.001105335651670241, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.001105335651670241, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ \"minimum\" U<=10 \"premium\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"minimum\" U[1,inf] \"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ \"minimum\" U[1,inf] !\"minimum\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult6 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.9999999033633374, quantitativeCheckResult6.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.9999999033633374, quantitativeCheckResult6.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=100]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult7 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.8602815057967503, quantitativeCheckResult7.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.8602815057967503, quantitativeCheckResult7.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridCtmcCslModelCheckerTest, Embedded) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/embedded2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "up"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10000 \"down\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.0019216435246119591, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0019216435246119591, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_actuators\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(3.7079151806696567E-6, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(3.7079151806696567E-6, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_io\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.001556839327673734, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.001556839327673734, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_sensors\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(4.429620626755424E-5, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(4.429620626755424E-5, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=10000]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(2.7745274082080154, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(2.7745274082080154, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridCtmcCslModelCheckerTest, Polling) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/polling2.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model.
|
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=?[ F<=10 \"target\"]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridCtmcCslModelCheckerTest, Fms) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// No properties to check at this point.
|
|||
} |
|||
|
|||
TEST(NativeHybridCtmcCslModelCheckerTest, Tandem) { |
|||
// Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
|
|||
std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true); |
|||
|
|||
// Parse the model description.
|
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/tandem5.sm"); |
|||
storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); |
|||
std::shared_ptr<storm::logic::Formula> formula(nullptr); |
|||
|
|||
// Build the model with the customers reward structure.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "customers"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType()); |
|||
std::shared_ptr<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>> ctmc = model->as<storm::models::symbolic::Ctmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
// Create model checker.
|
|||
storm::modelchecker::HybridCtmcCslModelChecker<storm::dd::DdType::CUDD, double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
// Start checking properties.
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10 \"network_full\" ]"); |
|||
std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult1 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.015446370562428037, quantitativeCheckResult1.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.015446370562428037, quantitativeCheckResult1.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [ F<=10 \"first_queue_full\" ]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult2 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(0.999999837225515, quantitativeCheckResult2.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(0.999999837225515, quantitativeCheckResult2.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("P=? [\"second_queue_full\" U<=1 !\"second_queue_full\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult3 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(1, quantitativeCheckResult3.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeCheckResult3.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [I=10]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult4 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(5.679243850315877, quantitativeCheckResult4.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(5.679243850315877, quantitativeCheckResult4.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [C<=10]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult5 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(55.44792186036232, quantitativeCheckResult5.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(55.44792186036232, quantitativeCheckResult5.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
|
|||
formula = formulaParser.parseFromString("R=? [F \"first_queue_full\"&\"second_queue_full\"]"); |
|||
checkResult = modelchecker.check(*formula); |
|||
|
|||
ASSERT_TRUE(checkResult->isHybridQuantitativeCheckResult()); |
|||
checkResult->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(ctmc->getReachableStates(), ctmc->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD> quantitativeCheckResult6 = checkResult->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
EXPECT_NEAR(262.78571505691389, quantitativeCheckResult6.getMin(), storm::settings::generalSettings().getPrecision()); |
|||
EXPECT_NEAR(262.78571505691389, quantitativeCheckResult6.getMax(), storm::settings::generalSettings().getPrecision()); |
|||
} |
@ -0,0 +1,165 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/builder/DdPrismModelBuilder.h"
|
|||
#include "src/models/symbolic/Dtmc.h"
|
|||
#include "src/settings/SettingsManager.h"
|
|||
|
|||
TEST(NativeHybridDtmcPrctlModelCheckerTest, Die) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/die.pm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "coin_flips"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(13, model->getNumberOfStates()); |
|||
EXPECT_EQ(20, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>> dtmc = model->as<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("one"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult1.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult1.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("two"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult2.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult2.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("three"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult3.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult3.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
auto done = std::make_shared<storm::logic::AtomicLabelFormula>("done"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(done); |
|||
|
|||
result = checker.check(*reachabilityRewardFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(3.6666646003723145, quantitativeResult4.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(3.6666646003723145, quantitativeResult4.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridDtmcPrctlModelCheckerTest, Crowds) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/crowds-5-5.pm"); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program); |
|||
EXPECT_EQ(8607, model->getNumberOfStates()); |
|||
EXPECT_EQ(15113, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>> dtmc = model->as<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("observe0Greater1"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.33288205191646525, quantitativeResult1.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.33288205191646525, quantitativeResult1.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("observeIGreater1"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.15222066094730619, quantitativeResult2.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.15222066094730619, quantitativeResult2.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("observeOnlyTrueSender"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.32153900158185761, quantitativeResult3.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.32153900158185761, quantitativeResult3.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridDtmcPrctlModelCheckerTest, SynchronousLeader) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader-3-5.pm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "num_rounds"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(273, model->getNumberOfStates()); |
|||
EXPECT_EQ(397, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Dtmc); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>> dtmc = model->as<storm::models::symbolic::Dtmc<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*eventuallyFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0, quantitativeResult1.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0, quantitativeResult1.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(true); |
|||
auto boundedUntilFormula = std::make_shared<storm::logic::BoundedUntilFormula>(trueFormula, labelFormula, 20); |
|||
|
|||
result = checker.check(*boundedUntilFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.99999989760000074, quantitativeResult2.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.99999989760000074, quantitativeResult2.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(labelFormula); |
|||
|
|||
result = checker.check(*reachabilityRewardFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0416666666666643, quantitativeResult3.getMin(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0416666666666643, quantitativeResult3.getMax(), storm::settings::gmmxxEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
@ -0,0 +1,190 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/prctl/HybridMdpPrctlModelChecker.h"
|
|||
#include "src/modelchecker/results/HybridQuantitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
|
|||
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
|
|||
#include "src/parser/PrismParser.h"
|
|||
#include "src/builder/DdPrismModelBuilder.h"
|
|||
#include "src/models/symbolic/Dtmc.h"
|
|||
#include "src/settings/SettingsManager.h"
|
|||
|
|||
TEST(NativeHybridMdpPrctlModelCheckerTest, Dice) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/two_dice.nm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "coinflips"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(169, model->getNumberOfStates()); |
|||
EXPECT_EQ(436, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::NativeMinMaxLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("two"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
auto minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("three"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("four"); |
|||
eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult6 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("done"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(labelFormula); |
|||
auto minRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Minimize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*minRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult7 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult7.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult7.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Maximize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*maxRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult8 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult8.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(7.3333283960819244, quantitativeResult8.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(NativeHybridMdpPrctlModelCheckerTest, AsynchronousLeader) { |
|||
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/leader4.nm"); |
|||
|
|||
// Build the die model with its reward model.
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
options.buildRewards = true; |
|||
options.rewardModelName = "rounds"; |
|||
std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::translateProgram(program, options); |
|||
EXPECT_EQ(3172, model->getNumberOfStates()); |
|||
EXPECT_EQ(7144, model->getNumberOfTransitions()); |
|||
|
|||
ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp); |
|||
|
|||
std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>(); |
|||
|
|||
storm::modelchecker::HybridMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::NativeMinMaxLinearEquationSolverFactory<double>())); |
|||
|
|||
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula); |
|||
auto minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, eventuallyFormula); |
|||
|
|||
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, eventuallyFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(true); |
|||
auto boundedUntilFormula = std::make_shared<storm::logic::BoundedUntilFormula>(trueFormula, labelFormula, 25); |
|||
minProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Minimize, boundedUntilFormula); |
|||
|
|||
result = checker.check(*minProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0625, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0625, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
maxProbabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(storm::logic::OptimalityType::Maximize, boundedUntilFormula); |
|||
|
|||
result = checker.check(*maxProbabilityOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.0625, quantitativeResult4.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.0625, quantitativeResult4.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("elected"); |
|||
auto reachabilityRewardFormula = std::make_shared<storm::logic::ReachabilityRewardFormula>(labelFormula); |
|||
auto minRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Minimize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*minRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(4.2856925589077264, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(4.2856925589077264, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
auto maxRewardOperatorFormula = std::make_shared<storm::logic::RewardOperatorFormula>(storm::logic::OptimalityType::Maximize, reachabilityRewardFormula); |
|||
|
|||
result = checker.check(*maxRewardOperatorFormula); |
|||
result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates())); |
|||
storm::modelchecker::HybridQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult6 = result->asHybridQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(4.2856953906798676, quantitativeResult6.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(4.2856953906798676, quantitativeResult6.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
Reference in new issue
xxxxxxxxxx