73 changed files with 2519 additions and 680 deletions
-
23CMakeLists.txt
-
21src/modelchecker/csl/HybridCtmcCslModelChecker.cpp
-
3src/modelchecker/csl/HybridCtmcCslModelChecker.h
-
258src/modelchecker/csl/SparseCtmcCslModelChecker.cpp
-
17src/modelchecker/csl/SparseCtmcCslModelChecker.h
-
15src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp
-
1src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h
-
236src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp
-
8src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h
-
263src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.cpp
-
49src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h
-
5src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp
-
3src/modelchecker/propositional/SymbolicPropositionalModelChecker.h
-
63src/modelchecker/reachability/CollectConstraints.h
-
80src/modelchecker/reachability/DirectEncoding.h
-
14src/modelchecker/results/ExplicitQualitativeCheckResult.cpp
-
2src/modelchecker/results/ExplicitQualitativeCheckResult.h
-
1src/models/ModelType.cpp
-
2src/models/ModelType.h
-
4src/models/sparse/Ctmc.cpp
-
4src/models/sparse/Ctmc.h
-
4src/models/sparse/DeterministicModel.cpp
-
4src/models/sparse/DeterministicModel.h
-
52src/models/sparse/Dtmc.cpp
-
55src/models/sparse/Dtmc.h
-
4src/models/sparse/MarkovAutomaton.cpp
-
4src/models/sparse/MarkovAutomaton.h
-
12src/models/sparse/Mdp.cpp
-
6src/models/sparse/Mdp.h
-
8src/models/sparse/Model.cpp
-
11src/models/sparse/Model.h
-
4src/models/sparse/NondeterministicModel.cpp
-
4src/models/sparse/NondeterministicModel.h
-
41src/models/sparse/StochasticTwoPlayerGame.cpp
-
77src/models/sparse/StochasticTwoPlayerGame.h
-
42src/models/symbolic/StochasticTwoPlayerGame.cpp
-
88src/models/symbolic/StochasticTwoPlayerGame.h
-
35src/parser/ExpressionParser.cpp
-
2src/parser/ExpressionParser.h
-
7src/parser/FormulaParser.cpp
-
1src/parser/FormulaParser.h
-
36src/settings/modules/GmmxxEquationSolverSettings.cpp
-
34src/settings/modules/GmmxxEquationSolverSettings.h
-
19src/settings/modules/NativeEquationSolverSettings.cpp
-
18src/settings/modules/NativeEquationSolverSettings.h
-
20src/solver/GmmxxLinearEquationSolver.cpp
-
131src/solver/NativeLinearEquationSolver.cpp
-
5src/solver/NativeLinearEquationSolver.h
-
69src/solver/SymbolicGameSolver.cpp
-
97src/solver/SymbolicGameSolver.h
-
85src/solver/SymbolicLinearEquationSolver.cpp
-
104src/solver/SymbolicLinearEquationSolver.h
-
6src/solver/Z3SmtSolver.h
-
346src/storage/SparseMatrix.cpp
-
71src/storage/SparseMatrix.h
-
6src/storage/dd/CuddAdd.cpp
-
4src/storage/dd/CuddAdd.h
-
35src/storage/dd/CuddBdd.cpp
-
24src/storage/dd/CuddBdd.h
-
2src/storage/expressions/ExprtkExpressionEvaluator.cpp
-
5src/utility/cli.cpp
-
23src/utility/cli.h
-
2src/utility/graph.h
-
35src/utility/solver.cpp
-
26src/utility/solver.h
-
4src/utility/vector.h
-
28test/functional/modelchecker/GmmxxCtmcCslModelCheckerTest.cpp
-
145test/functional/modelchecker/GmmxxDtmcPrctlModelCheckerTest.cpp
-
33test/functional/modelchecker/GmmxxHybridCtmcCslModelCheckerTest.cpp
-
11test/functional/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp
-
172test/functional/modelchecker/SymbolicDtmcPrctlModelCheckerTest.cpp
-
64test/functional/solver/FullySymbolicGameSolverTest.cpp
-
6test/functional/storage/SparseMatrixTest.cpp
@ -0,0 +1,263 @@ |
|||
#include "src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.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> |
|||
SymbolicDtmcPrctlModelChecker<DdType, ValueType>::SymbolicDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model, std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, ValueType>>&& linearEquationSolverFactory) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(std::move(linearEquationSolverFactory)) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
SymbolicDtmcPrctlModelChecker<DdType, ValueType>::SymbolicDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(new storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, ValueType>()) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
bool SymbolicDtmcPrctlModelChecker<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> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeUntilProbabilitiesHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, 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 = storm::utility::graph::performProb01(model, transitionMatrix, 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()); |
|||
|
|||
// Finally cut away all columns targeting non-maybe states and convert the matrix into the matrix needed
|
|||
// for solving the equation system (i.e. compute (I-A)).
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; |
|||
|
|||
// Solve the equation system.
|
|||
std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<DdType, ValueType>> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> result = solver->solveEquationSystem(model.getManager().getConstant(0.5) * maybeStatesAdd, subvector); |
|||
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), statesWithProbability01.second.toAdd() + result)); |
|||
} 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> SymbolicDtmcPrctlModelChecker<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 this->computeUntilProbabilitiesHelper(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<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(), this->computeNextProbabilitiesHelper(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()))); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
storm::dd::Add<DdType> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeNextProbabilitiesHelper(storm::models::symbolic::Model<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> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
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(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeBoundedUntilProbabilitiesHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, 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 = storm::utility::graph::performProbGreater0(model, transitionMatrix.notZero(), phiStates, psiStates, stepBound); |
|||
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()); |
|||
|
|||
// Finally cut away all columns targeting non-maybe states.
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
|
|||
// Perform the matrix-vector multiplication.
|
|||
std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<DdType, ValueType>> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> result = solver->performMatrixVectorMultiplication(model.getManager().getAddZero(), &subvector, stepBound); |
|||
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), psiStates.toAdd() + result)); |
|||
} 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> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); |
|||
return this->computeCumulativeRewardsHelper(this->getModel(), this->getModel().getTransitionMatrix(), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeCumulativeRewardsHelper(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, 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()); |
|||
} |
|||
|
|||
// Perform the matrix-vector multiplication.
|
|||
std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<DdType, ValueType>> solver = linearEquationSolverFactory.create(transitionMatrix, model.getReachableStates(), model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> result = solver->performMatrixVectorMultiplication(model.getManager().getAddZero(), &totalRewardVector, stepBound); |
|||
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), result)); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, bool qualitative, boost::optional<storm::logic::OptimalityType> const& optimalityType) { |
|||
STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); |
|||
return this->computeInstantaneousRewardsHelper(this->getModel(), this->getModel().getTransitionMatrix(), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeInstantaneousRewardsHelper(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, 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."); |
|||
|
|||
// Perform the matrix-vector multiplication.
|
|||
std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<DdType, ValueType>> solver = linearEquationSolverFactory.create(transitionMatrix, model.getReachableStates(), model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> result = solver->performMatrixVectorMultiplication(model.getStateRewardVector(), nullptr, stepBound); |
|||
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), result)); |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
std::unique_ptr<CheckResult> SymbolicDtmcPrctlModelChecker<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>(); |
|||
return this->computeReachabilityRewardsHelper(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> SymbolicDtmcPrctlModelChecker<DdType, ValueType>::computeReachabilityRewardsHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, 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::utility::graph::performProb1(model, transitionMatrix.notZero(), 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()); |
|||
} |
|||
|
|||
// Finally cut away all columns targeting non-maybe states and convert the matrix into the matrix needed
|
|||
// for solving the equation system (i.e. compute (I-A)).
|
|||
submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); |
|||
submatrix = (model.getRowColumnIdentity() * maybeStatesAdd) - submatrix; |
|||
|
|||
// Solve the equation system.
|
|||
std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<DdType, ValueType>> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getRowColumnMetaVariablePairs()); |
|||
storm::dd::Add<DdType> result = solver->solveEquationSystem(model.getManager().getConstant(0.5) * maybeStatesAdd, subvector); |
|||
|
|||
return std::unique_ptr<CheckResult>(new storm::modelchecker::SymbolicQuantitativeCheckResult<DdType>(model.getReachableStates(), infinityStates.toAdd() * model.getManager().getConstant(storm::utility::infinity<ValueType>()) + result)); |
|||
} 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::Dtmc<DdType> const& SymbolicDtmcPrctlModelChecker<DdType, ValueType>::getModel() const { |
|||
return this->template getModelAs<storm::models::symbolic::Dtmc<DdType>>(); |
|||
} |
|||
|
|||
template class SymbolicDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double>; |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
#ifndef STORM_MODELCHECKER_SYMBOLICDTMCPRCTLMODELCHECKER_H_ |
|||
#define STORM_MODELCHECKER_SYMBOLICDTMCPRCTLMODELCHECKER_H_ |
|||
|
|||
#include "src/modelchecker/propositional/SymbolicPropositionalModelChecker.h" |
|||
#include "src/models/symbolic/Dtmc.h" |
|||
#include "src/utility/solver.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
class SymbolicCtmcCslModelChecker; |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
class SymbolicDtmcPrctlModelChecker : public SymbolicPropositionalModelChecker<DdType> { |
|||
public: |
|||
friend class SymbolicCtmcCslModelChecker<DdType, ValueType>; |
|||
|
|||
explicit SymbolicDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model); |
|||
explicit SymbolicDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model, std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, 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::Dtmc<DdType> const& getModel() const override; |
|||
|
|||
private: |
|||
// The methods that perform the actual checking. |
|||
static std::unique_ptr<CheckResult> computeBoundedUntilProbabilitiesHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, ValueType> const& linearEquationSolverFactory); |
|||
static storm::dd::Add<DdType> computeNextProbabilitiesHelper(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Bdd<DdType> const& nextStates); |
|||
static std::unique_ptr<CheckResult> computeUntilProbabilitiesHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeCumulativeRewardsHelper(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeInstantaneousRewardsHelper(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, uint_fast64_t stepBound, storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, ValueType> const& linearEquationSolverFactory); |
|||
static std::unique_ptr<CheckResult> computeReachabilityRewardsHelper(storm::models::symbolic::Model<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::SymbolicLinearEquationSolverFactory<DdType, ValueType> const& linearEquationSolverFactory, bool qualitative); |
|||
|
|||
// An object that is used for retrieving linear equation solvers. |
|||
std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<DdType, ValueType>> linearEquationSolverFactory; |
|||
}; |
|||
|
|||
} // namespace modelchecker |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_MODELCHECKER_SYMBOLICDTMCPRCTLMODELCHECKER_H_ */ |
@ -1,63 +0,0 @@ |
|||
/** |
|||
* @file: CollectConstraints.h |
|||
* @author: Sebastian Junges |
|||
* |
|||
* @since October 8, 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
#include "src/models/Dtmc.h" |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace reachability { |
|||
template<typename ValueType> |
|||
class CollectConstraints |
|||
{ |
|||
private: |
|||
std::unordered_set<carl::Constraint<ValueType>> wellformedConstraintSet; |
|||
std::unordered_set<carl::Constraint<ValueType>> graphPreservingConstraintSet; |
|||
storm::utility::ConstantsComparator<ValueType> comparator; |
|||
|
|||
public: |
|||
std::unordered_set<carl::Constraint<ValueType>> const& wellformedConstraints() const { |
|||
return this->wellformedConstraintSet; |
|||
} |
|||
|
|||
std::unordered_set<carl::Constraint<ValueType>> const& graphPreservingConstraints() const { |
|||
return this->graphPreservingConstraintSet; |
|||
} |
|||
|
|||
void process(storm::models::Dtmc<ValueType> const& dtmc) |
|||
{ |
|||
for(uint_fast64_t state = 0; state < dtmc.getNumberOfStates(); ++state) |
|||
{ |
|||
ValueType sum; |
|||
assert(comparator.isZero(sum)); |
|||
for(auto const& transition : dtmc.getRows(state)) |
|||
{ |
|||
sum += transition.getValue(); |
|||
if(!transition.getValue().isConstant()) |
|||
{ |
|||
wellformedConstraintSet.emplace(transition.getValue() - 1, storm::CompareRelation::LEQ); |
|||
wellformedConstraintSet.emplace(transition.getValue(), storm::CompareRelation::GEQ); |
|||
graphPreservingConstraintSet.emplace(transition.getValue(), storm::CompareRelation::GT); |
|||
} |
|||
} |
|||
assert(!comparator.isConstant(sum) || comparator.isOne(sum)); |
|||
if(!sum.isConstant()) { |
|||
wellformedConstraintSet.emplace(sum - 1, storm::CompareRelation::EQ); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
void operator()(storm::models::Dtmc<ValueType> const& dtmc) |
|||
{ |
|||
process(dtmc); |
|||
} |
|||
|
|||
}; |
|||
} |
|||
} |
|||
} |
@ -1,80 +0,0 @@ |
|||
/** |
|||
* @file: DirectEncoding.h |
|||
* @author: Sebastian Junges |
|||
* |
|||
* @since April 8, 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#ifdef STORM_HAVE_CARL |
|||
#include <carl/io/WriteTosmt2Stream.h> |
|||
|
|||
namespace storm |
|||
{ |
|||
namespace modelchecker |
|||
{ |
|||
namespace reachability |
|||
{ |
|||
class DirectEncoding |
|||
{ |
|||
public: |
|||
template<typename T> |
|||
std::string encodeAsSmt2(storm::storage::SparseMatrix<T> const& transitionMatrix, std::vector<T> const& oneStepProbabilities, std::set<carl::Variable> const& parameters, storm::storage::BitVector const& initialStates, typename T::CoeffType const& threshold, bool lessequal = false) { |
|||
|
|||
carl::io::WriteTosmt2Stream smt2; |
|||
uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); |
|||
carl::VariablePool& vpool = carl::VariablePool::getInstance(); |
|||
std::vector<carl::Variable> stateVars; |
|||
for (carl::Variable const& p : parameters) { |
|||
smt2 << ("parameter_bound_" + vpool.getName(p)); |
|||
smt2 << carl::io::smt2node::AND; |
|||
smt2 << carl::Constraint<Polynomial::PolyType>(Polynomial::PolyType(p), carl::CompareRelation::GT); |
|||
smt2 << carl::Constraint<Polynomial::PolyType>(Polynomial::PolyType(p) - Polynomial::PolyType(1), carl::CompareRelation::LT); |
|||
smt2 << carl::io::smt2node::CLOSENODE; |
|||
} |
|||
|
|||
for (uint_fast64_t state = 0; state < numberOfStates; ++state) { |
|||
carl::Variable stateVar = vpool.getFreshVariable("s_" + std::to_string(state)); |
|||
stateVars.push_back(stateVar); |
|||
smt2 << ("state_bound_" + std::to_string(state)); |
|||
smt2 << carl::io::smt2node::AND; |
|||
smt2 << carl::Constraint<Polynomial::PolyType>(Polynomial::PolyType(stateVar), carl::CompareRelation::GT); |
|||
smt2 << carl::Constraint<Polynomial::PolyType>(Polynomial::PolyType(stateVar) - Polynomial::PolyType(1), carl::CompareRelation::LT); |
|||
smt2 << carl::io::smt2node::CLOSENODE; |
|||
} |
|||
|
|||
smt2.setAutomaticLineBreaks(true); |
|||
Polynomial::PolyType initStateReachSum; |
|||
for (uint_fast64_t state = 0; state < numberOfStates; ++state) { |
|||
T reachpropPol; |
|||
for (auto const& transition : transitionMatrix.getRow(state)) { |
|||
// reachpropPol += transition.getValue() * stateVars[transition.getColumn()]; |
|||
} |
|||
reachpropPol += oneStepProbabilities[state]; |
|||
smt2 << ("transition_" + std::to_string(state)); |
|||
// smt2 << carl::Constraint<Polynomial::PolyType>(reachpropPol - stateVars[state], carl::CompareRelation::EQ); |
|||
} |
|||
|
|||
smt2 << ("reachability"); |
|||
|
|||
carl::CompareRelation thresholdRelation = lessequal ? carl::CompareRelation::LEQ : carl::CompareRelation::GEQ; |
|||
smt2 << carl::io::smt2node::OR; |
|||
for (uint_fast64_t state : initialStates) { |
|||
smt2 << carl::Constraint<Polynomial::PolyType>(Polynomial::PolyType(stateVars[state]) - threshold, thresholdRelation); |
|||
} |
|||
smt2 << carl::io::smt2node::CLOSENODE; |
|||
|
|||
smt2 << carl::io::smt2flag::CHECKSAT; |
|||
smt2 << carl::io::smt2flag::MODEL; |
|||
smt2 << carl::io::smt2flag::UNSAT_CORE; |
|||
std::stringstream strm; |
|||
strm << smt2; |
|||
return strm.str(); |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,41 @@ |
|||
#include "src/models/sparse/StochasticTwoPlayerGame.h"
|
|||
|
|||
#include "src/adapters/CarlAdapter.h"
|
|||
|
|||
namespace storm { |
|||
namespace models { |
|||
namespace sparse { |
|||
|
|||
template <typename ValueType> |
|||
StochasticTwoPlayerGame<ValueType>::StochasticTwoPlayerGame(storm::storage::SparseMatrix<storm::storage::sparse::state_type> const& player1Matrix, |
|||
storm::storage::SparseMatrix<ValueType> const& player2Matrix, |
|||
storm::models::sparse::StateLabeling const& stateLabeling, |
|||
boost::optional<std::vector<ValueType>> const& optionalStateRewardVector, |
|||
boost::optional<std::vector<LabelSet>> const& optionalPlayer1ChoiceLabeling, |
|||
boost::optional<std::vector<LabelSet>> const& optionalPlayer2ChoiceLabeling) |
|||
: NondeterministicModel<ValueType>(storm::models::ModelType::S2pg, player2Matrix, stateLabeling, optionalStateRewardVector, boost::optional<storm::storage::SparseMatrix<ValueType>>(), optionalPlayer2ChoiceLabeling), player1Matrix(player1Matrix), player1Labels(optionalPlayer1ChoiceLabeling) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
|
|||
template <typename ValueType> |
|||
StochasticTwoPlayerGame<ValueType>::StochasticTwoPlayerGame(storm::storage::SparseMatrix<storm::storage::sparse::state_type>&& player1Matrix, |
|||
storm::storage::SparseMatrix<ValueType>&& player2Matrix, |
|||
storm::models::sparse::StateLabeling&& stateLabeling, |
|||
boost::optional<std::vector<ValueType>>&& optionalStateRewardVector, |
|||
boost::optional<std::vector<LabelSet>>&& optionalPlayer1ChoiceLabeling, |
|||
boost::optional<std::vector<LabelSet>>&& optionalPlayer2ChoiceLabeling) |
|||
: NondeterministicModel<ValueType>(storm::models::ModelType::S2pg, std::move(player2Matrix), std::move(stateLabeling), std::move(optionalStateRewardVector), boost::optional<storm::storage::SparseMatrix<ValueType>>(), std::move(optionalPlayer2ChoiceLabeling)), player1Matrix(std::move(player1Matrix)), player1Labels(std::move(optionalPlayer1ChoiceLabeling)) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template class StochasticTwoPlayerGame<double>; |
|||
template class StochasticTwoPlayerGame<float>; |
|||
|
|||
#ifdef STORM_HAVE_CARL
|
|||
template class StochasticTwoPlayerGame<storm::RationalFunction>; |
|||
#endif
|
|||
|
|||
} // namespace sparse
|
|||
} // namespace models
|
|||
} // namespace storm
|
@ -0,0 +1,77 @@ |
|||
#ifndef STORM_MODELS_SPARSE_STOCHASTICTWOPLAYERGAME_H_ |
|||
#define STORM_MODELS_SPARSE_STOCHASTICTWOPLAYERGAME_H_ |
|||
|
|||
#include "src/models/sparse/NondeterministicModel.h" |
|||
#include "src/utility/OsDetection.h" |
|||
|
|||
namespace storm { |
|||
namespace models { |
|||
namespace sparse { |
|||
|
|||
/*! |
|||
* This class represents a (discrete-time) stochastic two-player game. |
|||
*/ |
|||
template <typename ValueType> |
|||
class StochasticTwoPlayerGame : public NondeterministicModel<ValueType> { |
|||
public: |
|||
/*! |
|||
* Constructs a model from the given data. |
|||
* |
|||
* @param player1Matrix The matrix representing the choices of player 1. |
|||
* @param player2Matrix The matrix representing the choices of player 2. |
|||
* @param stateLabeling The labeling of the states. |
|||
* @param optionalStateRewardVector The reward values associated with the states. |
|||
* @param optionalPlayer1ChoiceLabeling A vector that represents the labels associated with the choices of each player 1 state. |
|||
* @param optionalPlayer2ChoiceLabeling A vector that represents the labels associated with the choices of each player 2 state. |
|||
*/ |
|||
StochasticTwoPlayerGame(storm::storage::SparseMatrix<storm::storage::sparse::state_type> const& player1Matrix, |
|||
storm::storage::SparseMatrix<ValueType> const& player2Matrix, |
|||
storm::models::sparse::StateLabeling const& stateLabeling, |
|||
boost::optional<std::vector<ValueType>> const& optionalStateRewardVector = boost::optional<std::vector<ValueType>>(), |
|||
boost::optional<std::vector<LabelSet>> const& optionalPlayer1ChoiceLabeling = boost::optional<std::vector<LabelSet>>(), |
|||
boost::optional<std::vector<LabelSet>> const& optionalPlayer2ChoiceLabeling = boost::optional<std::vector<LabelSet>>()); |
|||
|
|||
/*! |
|||
* Constructs a model by moving the given data. |
|||
* |
|||
* @param player1Matrix The matrix representing the choices of player 1. |
|||
* @param player2Matrix The matrix representing the choices of player 2. |
|||
* @param stateLabeling The labeling of the states. |
|||
* @param optionalStateRewardVector The reward values associated with the states. |
|||
* @param optionalPlayer1ChoiceLabeling A vector that represents the labels associated with the choices of each player 1 state. |
|||
* @param optionalPlayer2ChoiceLabeling A vector that represents the labels associated with the choices of each player 2 state. |
|||
*/ |
|||
StochasticTwoPlayerGame(storm::storage::SparseMatrix<storm::storage::sparse::state_type>&& player1Matrix, |
|||
storm::storage::SparseMatrix<ValueType>&& player2Matrix, |
|||
storm::models::sparse::StateLabeling&& stateLabeling, |
|||
boost::optional<std::vector<ValueType>>&& optionalStateRewardVector = boost::optional<std::vector<ValueType>>(), |
|||
boost::optional<std::vector<LabelSet>>&& optionalPlayer1ChoiceLabeling = boost::optional<std::vector<LabelSet>>(), |
|||
boost::optional<std::vector<LabelSet>>&& optionalPlayer2ChoiceLabeling = boost::optional<std::vector<LabelSet>>()); |
|||
|
|||
StochasticTwoPlayerGame(StochasticTwoPlayerGame const& other) = default; |
|||
StochasticTwoPlayerGame& operator=(StochasticTwoPlayerGame const& other) = default; |
|||
|
|||
#ifndef WINDOWS |
|||
StochasticTwoPlayerGame(StochasticTwoPlayerGame&& other) = default; |
|||
StochasticTwoPlayerGame& operator=(StochasticTwoPlayerGame&& other) = default; |
|||
#endif |
|||
|
|||
private: |
|||
// A matrix that stores the player 1 choices. This matrix contains a row group for each player 1 node. Every |
|||
// row group contains a row for each choice in that player 1 node. Each such row contains exactly one |
|||
// (non-zero) entry at a column that indicates the player 2 node this choice leads to (which is essentially |
|||
// the index of a row group in the matrix for player 2). |
|||
storm::storage::SparseMatrix<storm::storage::sparse::state_type> player1Matrix; |
|||
|
|||
// An (optional) vector of labels attached to the choices of player 1. Each row of the matrix can be equipped |
|||
// with a set of labels to tag certain choices. |
|||
boost::optional<std::vector<LabelSet>> player1Labels; |
|||
|
|||
// The matrix and labels for player 2 are stored in the superclass. |
|||
}; |
|||
|
|||
} // namespace sparse |
|||
} // namespace models |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_MODELS_SPARSE_STOCHASTICTWOPLAYERGAME_H_ */ |
@ -0,0 +1,42 @@ |
|||
#include "src/models/symbolic/StochasticTwoPlayerGame.h"
|
|||
|
|||
namespace storm { |
|||
namespace models { |
|||
namespace symbolic { |
|||
|
|||
template<storm::dd::DdType Type> |
|||
StochasticTwoPlayerGame<Type>::StochasticTwoPlayerGame(std::shared_ptr<storm::dd::DdManager<Type>> manager, |
|||
storm::dd::Bdd<Type> reachableStates, |
|||
storm::dd::Bdd<Type> initialStates, |
|||
storm::dd::Add<Type> transitionMatrix, |
|||
std::set<storm::expressions::Variable> const& rowVariables, |
|||
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter, |
|||
std::set<storm::expressions::Variable> const& columnVariables, |
|||
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter, |
|||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, |
|||
std::set<storm::expressions::Variable> const& player1Variables, |
|||
std::set<storm::expressions::Variable> const& player2Variables, |
|||
std::set<storm::expressions::Variable> const& nondeterminismVariables, |
|||
std::map<std::string, storm::expressions::Expression> labelToExpressionMap, |
|||
boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector, |
|||
boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix) |
|||
: NondeterministicModel<Type>(storm::models::ModelType::S2pg, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, nondeterminismVariables, labelToExpressionMap, optionalStateRewardVector, optionalTransitionRewardMatrix), player1Variables(player1Variables), player2Variables(player2Variables) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType Type> |
|||
std::set<storm::expressions::Variable> const& StochasticTwoPlayerGame<Type>::getPlayer1Variables() const { |
|||
return player1Variables; |
|||
} |
|||
|
|||
template<storm::dd::DdType Type> |
|||
std::set<storm::expressions::Variable> const& StochasticTwoPlayerGame<Type>::getPlayer2Variables() const { |
|||
return player2Variables; |
|||
} |
|||
|
|||
// Explicitly instantiate the template class.
|
|||
template class StochasticTwoPlayerGame<storm::dd::DdType::CUDD>; |
|||
|
|||
} // namespace symbolic
|
|||
} // namespace models
|
|||
} // namespace storm
|
@ -0,0 +1,88 @@ |
|||
#ifndef STORM_MODELS_SYMBOLIC_STOCHASTICTWOPLAYERGAME_H_ |
|||
#define STORM_MODELS_SYMBOLIC_STOCHASTICTWOPLAYERGAME_H_ |
|||
|
|||
#include "src/models/symbolic/NondeterministicModel.h" |
|||
#include "src/utility/OsDetection.h" |
|||
|
|||
namespace storm { |
|||
namespace models { |
|||
namespace symbolic { |
|||
|
|||
/*! |
|||
* This class represents a discrete-time stochastic two-player game. |
|||
*/ |
|||
template<storm::dd::DdType Type> |
|||
class StochasticTwoPlayerGame : public NondeterministicModel<Type> { |
|||
public: |
|||
StochasticTwoPlayerGame(StochasticTwoPlayerGame<Type> const& other) = default; |
|||
StochasticTwoPlayerGame& operator=(StochasticTwoPlayerGame<Type> const& other) = default; |
|||
|
|||
#ifndef WINDOWS |
|||
StochasticTwoPlayerGame(StochasticTwoPlayerGame<Type>&& other) = default; |
|||
StochasticTwoPlayerGame& operator=(StochasticTwoPlayerGame<Type>&& other) = default; |
|||
#endif |
|||
|
|||
/*! |
|||
* Constructs a model from the given data. |
|||
* |
|||
* @param manager The manager responsible for the decision diagrams. |
|||
* @param reachableStates A DD representing the reachable states. |
|||
* @param initialStates A DD representing the initial states of the model. |
|||
* @param transitionMatrix The matrix representing the transitions in the model. |
|||
* @param rowVariables The set of row meta variables used in the DDs. |
|||
* @param rowExpressionAdapter An object that can be used to translate expressions in terms of the row |
|||
* meta variables. |
|||
* @param columVariables The set of column meta variables used in the DDs. |
|||
* @param columnExpressionAdapter An object that can be used to translate expressions in terms of the |
|||
* column meta variables. |
|||
* @param rowColumnMetaVariablePairs All pairs of row/column meta variables. |
|||
* @param player1Variables The meta variables used to encode the nondeterministic choices of player 1. |
|||
* @param player2Variables The meta variables used to encode the nondeterministic choices of player 2. |
|||
* @param allNondeterminismVariables The meta variables used to encode the nondeterminism in the model. |
|||
* @param labelToExpressionMap A mapping from label names to their defining expressions. |
|||
* @param optionalStateRewardVector The reward values associated with the states. |
|||
* @param optionalTransitionRewardMatrix The reward values associated with the transitions of the model. |
|||
*/ |
|||
StochasticTwoPlayerGame(std::shared_ptr<storm::dd::DdManager<Type>> manager, |
|||
storm::dd::Bdd<Type> reachableStates, |
|||
storm::dd::Bdd<Type> initialStates, |
|||
storm::dd::Add<Type> transitionMatrix, |
|||
std::set<storm::expressions::Variable> const& rowVariables, |
|||
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter, |
|||
std::set<storm::expressions::Variable> const& columnVariables, |
|||
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter, |
|||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, |
|||
std::set<storm::expressions::Variable> const& player1Variables, |
|||
std::set<storm::expressions::Variable> const& player2Variables, |
|||
std::set<storm::expressions::Variable> const& allNondeterminismVariables, |
|||
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(), |
|||
boost::optional<storm::dd::Add<Type>> const& optionalStateRewardVector = boost::optional<storm::dd::Dd<Type>>(), |
|||
boost::optional<storm::dd::Add<Type>> const& optionalTransitionRewardMatrix = boost::optional<storm::dd::Dd<Type>>()); |
|||
|
|||
/*! |
|||
* Retrieeves the set of meta variables used to encode the nondeterministic choices of player 1. |
|||
* |
|||
* @return The set of meta variables used to encode the nondeterministic choices of player 1. |
|||
*/ |
|||
std::set<storm::expressions::Variable> const& getPlayer1Variables() const; |
|||
|
|||
/*! |
|||
* Retrieeves the set of meta variables used to encode the nondeterministic choices of player 2. |
|||
* |
|||
* @return The set of meta variables used to encode the nondeterministic choices of player 2. |
|||
*/ |
|||
std::set<storm::expressions::Variable> const& getPlayer2Variables() const; |
|||
|
|||
private: |
|||
// The meta variables used to encode the nondeterministic choices of player 1. |
|||
std::set<storm::expressions::Variable> player1Variables; |
|||
|
|||
// The meta variables used to encode the nondeterministic choices of player 2. |
|||
std::set<storm::expressions::Variable> player2Variables; |
|||
}; |
|||
|
|||
} // namespace symbolic |
|||
} // namespace models |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_MODELS_SYMBOLIC_STOCHASTICTWOPLAYERGAME_H_ */ |
@ -0,0 +1,69 @@ |
|||
#include "src/solver/SymbolicGameSolver.h"
|
|||
|
|||
#include "src/storage/dd/CuddBdd.h"
|
|||
#include "src/storage/dd/CuddAdd.h"
|
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<storm::dd::DdType Type> |
|||
SymbolicGameSolver<Type>::SymbolicGameSolver(storm::dd::Add<Type> const& gameMatrix, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables) : gameMatrix(gameMatrix), allRows(allRows), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), player1Variables(player1Variables), player2Variables(player2Variables) { |
|||
// Get the settings object to customize solving.
|
|||
storm::settings::modules::NativeEquationSolverSettings const& settings = storm::settings::nativeEquationSolverSettings(); |
|||
storm::settings::modules::GeneralSettings const& generalSettings = storm::settings::generalSettings(); |
|||
|
|||
// Get appropriate settings.
|
|||
maximalNumberOfIterations = settings.getMaximalIterationCount(); |
|||
precision = settings.getPrecision(); |
|||
relative = settings.getConvergenceCriterion() == storm::settings::modules::NativeEquationSolverSettings::ConvergenceCriterion::Relative; |
|||
} |
|||
|
|||
template<storm::dd::DdType Type> |
|||
SymbolicGameSolver<Type>::SymbolicGameSolver(storm::dd::Add<Type> const& gameMatrix, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables, double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : gameMatrix(gameMatrix), allRows(allRows), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), player1Variables(player1Variables), player2Variables(player2Variables), precision(precision), maximalNumberOfIterations(maximalNumberOfIterations), relative(relative) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType Type> |
|||
storm::dd::Add<Type> SymbolicGameSolver<Type>::solveGame(bool player1Min, bool player2Min, storm::dd::Add<Type> const& x, storm::dd::Add<Type> const& b) const { |
|||
// Set up the environment.
|
|||
storm::dd::Add<Type> xCopy = x; |
|||
uint_fast64_t iterations = 0; |
|||
bool converged = false; |
|||
|
|||
while (!converged && iterations < maximalNumberOfIterations) { |
|||
// Compute tmp = A * x + b
|
|||
storm::dd::Add<Type> xCopyAsColumn = xCopy.swapVariables(this->rowColumnMetaVariablePairs); |
|||
storm::dd::Add<Type> tmp = this->gameMatrix.multiplyMatrix(xCopyAsColumn, this->columnMetaVariables); |
|||
tmp += b; |
|||
|
|||
// Now abstract from player 2 and player 1 variables.
|
|||
if (player2Min) { |
|||
tmp = tmp.minAbstract(this->player2Variables); |
|||
} else { |
|||
tmp = tmp.maxAbstract(this->player2Variables); |
|||
} |
|||
|
|||
if (player1Min) { |
|||
tmp = tmp.minAbstract(this->player1Variables); |
|||
} else { |
|||
tmp = tmp.maxAbstract(this->player1Variables); |
|||
} |
|||
|
|||
// Now check if the process already converged within our precision.
|
|||
converged = xCopy.equalModuloPrecision(tmp, precision, relative); |
|||
|
|||
// If the method did not converge yet, we prepare the x vector for the next iteration.
|
|||
if (!converged) { |
|||
xCopy = tmp; |
|||
} |
|||
|
|||
++iterations; |
|||
} |
|||
|
|||
return xCopy; |
|||
} |
|||
|
|||
template class SymbolicGameSolver<storm::dd::DdType::CUDD>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,97 @@ |
|||
#ifndef STORM_SOLVER_SYMBOLICGAMESOLVER_H_ |
|||
#define STORM_SOLVER_SYMBOLICGAMESOLVER_H_ |
|||
|
|||
#include "src/storage/expressions/Variable.h" |
|||
|
|||
#include "src/storage/dd/Bdd.h" |
|||
#include "src/storage/dd/Add.h" |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
/*! |
|||
* An interface that represents an abstract symbolic game solver. |
|||
*/ |
|||
template<storm::dd::DdType Type> |
|||
class SymbolicGameSolver { |
|||
public: |
|||
/*! |
|||
* Constructs a symbolic game solver with the given meta variable sets and pairs. |
|||
* |
|||
* @param gameMatrix The matrix defining the coefficients of the game. |
|||
* @param allRows A BDD characterizing all rows of the equation system. |
|||
* @param rowMetaVariables The meta variables used to encode the rows of the matrix. |
|||
* @param columnMetaVariables The meta variables used to encode the columns of the matrix. |
|||
* @param rowColumnMetaVariablePairs The pairs of row meta variables and the corresponding column meta |
|||
* variables. |
|||
* @param player1Variables The meta variables used to encode the player 1 choices. |
|||
* @param player2Variables The meta variables used to encode the player 2 choices. |
|||
*/ |
|||
SymbolicGameSolver(storm::dd::Add<Type> const& gameMatrix, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables); |
|||
|
|||
/*! |
|||
* Constructs a symbolic game solver with the given meta variable sets and pairs. |
|||
* |
|||
* @param gameMatrix The matrix defining the coefficients of the game. |
|||
* @param allRows A BDD characterizing all rows of the equation system. |
|||
* @param rowMetaVariables The meta variables used to encode the rows of the matrix. |
|||
* @param columnMetaVariables The meta variables used to encode the columns of the matrix. |
|||
* @param rowColumnMetaVariablePairs The pairs of row meta variables and the corresponding column meta |
|||
* variables. |
|||
* @param player1Variables The meta variables used to encode the player 1 choices. |
|||
* @param player2Variables The meta variables used to encode the player 2 choices. |
|||
* @param precision The precision to achieve. |
|||
* @param maximalNumberOfIterations The maximal number of iterations to perform when solving a linear |
|||
* equation system iteratively. |
|||
* @param relative Sets whether or not to use a relativ stopping criterion rather than an absolute one. |
|||
*/ |
|||
SymbolicGameSolver(storm::dd::Add<Type> const& gameMatrix, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables, double precision, uint_fast64_t maximalNumberOfIterations, bool relative); |
|||
|
|||
/*! |
|||
* Solves the equation system x = min/max(A*x + b) given by the parameters. Note that the matrix A has |
|||
* to be given upon construction time of the solver object. |
|||
* |
|||
* @param player1Min A flag indicating whether player 1 wants to minimize the result. |
|||
* @param player2Min A flag indicating whether player 1 wants to minimize the result. |
|||
* @param x The initial guess of the solution. |
|||
* @param b The vector to add after matrix-vector multiplication. |
|||
* @return The solution vector. |
|||
*/ |
|||
virtual storm::dd::Add<Type> solveGame(bool player1Min, bool player2Min, storm::dd::Add<Type> const& x, storm::dd::Add<Type> const& b) const; |
|||
|
|||
protected: |
|||
// The matrix defining the coefficients of the linear equation system. |
|||
storm::dd::Add<Type> const& gameMatrix; |
|||
|
|||
// A BDD characterizing all rows of the equation system. |
|||
storm::dd::Bdd<Type> const& allRows; |
|||
|
|||
// The row variables. |
|||
std::set<storm::expressions::Variable> rowMetaVariables; |
|||
|
|||
// The column variables. |
|||
std::set<storm::expressions::Variable> columnMetaVariables; |
|||
|
|||
// The pairs of meta variables used for renaming. |
|||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs; |
|||
|
|||
// The player 1 variables. |
|||
std::set<storm::expressions::Variable> player1Variables; |
|||
|
|||
// The player 2 variables. |
|||
std::set<storm::expressions::Variable> player2Variables; |
|||
|
|||
// The precision to achive. |
|||
double precision; |
|||
|
|||
// The maximal number of iterations to perform. |
|||
uint_fast64_t maximalNumberOfIterations; |
|||
|
|||
// A flag indicating whether a relative or an absolute stopping criterion is to be used. |
|||
bool relative; |
|||
}; |
|||
|
|||
} // namespace solver |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_SOLVER_SYMBOLICGAMESOLVER_H_ */ |
@ -0,0 +1,85 @@ |
|||
#include "src/solver/SymbolicLinearEquationSolver.h"
|
|||
|
|||
#include "src/storage/dd/CuddDdManager.h"
|
|||
#include "src/storage/dd/CuddAdd.h"
|
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
SymbolicLinearEquationSolver<DdType, ValueType>::SymbolicLinearEquationSolver(storm::dd::Add<DdType> const& A, storm::dd::Bdd<DdType> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : A(A), allRows(allRows), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs), precision(precision), maximalNumberOfIterations(maximalNumberOfIterations), relative(relative) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
SymbolicLinearEquationSolver<DdType, ValueType>::SymbolicLinearEquationSolver(storm::dd::Add<DdType> const& A, storm::dd::Bdd<DdType> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs) : A(A), allRows(allRows), rowMetaVariables(rowMetaVariables), columnMetaVariables(columnMetaVariables), rowColumnMetaVariablePairs(rowColumnMetaVariablePairs) { |
|||
// Get the settings object to customize solving.
|
|||
storm::settings::modules::NativeEquationSolverSettings const& settings = storm::settings::nativeEquationSolverSettings(); |
|||
storm::settings::modules::GeneralSettings const& generalSettings = storm::settings::generalSettings(); |
|||
|
|||
// Get appropriate settings.
|
|||
maximalNumberOfIterations = settings.getMaximalIterationCount(); |
|||
precision = settings.getPrecision(); |
|||
relative = settings.getConvergenceCriterion() == storm::settings::modules::NativeEquationSolverSettings::ConvergenceCriterion::Relative; |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
storm::dd::Add<DdType> SymbolicLinearEquationSolver<DdType, ValueType>::solveEquationSystem(storm::dd::Add<DdType> const& x, storm::dd::Add<DdType> const& b) const { |
|||
// Start by computing the Jacobi decomposition of the matrix A.
|
|||
storm::dd::Add<DdType> diagonal = x.getDdManager()->getAddOne(); |
|||
for (auto const& pair : rowColumnMetaVariablePairs) { |
|||
diagonal *= x.getDdManager()->getIdentity(pair.first).equals(x.getDdManager()->getIdentity(pair.second)); |
|||
diagonal *= x.getDdManager()->getRange(pair.first).toAdd() * x.getDdManager()->getRange(pair.second).toAdd(); |
|||
} |
|||
diagonal *= allRows.toAdd(); |
|||
|
|||
storm::dd::Add<DdType> lu = diagonal.ite(this->A.getDdManager()->getAddZero(), this->A); |
|||
storm::dd::Add<DdType> dinv = diagonal / (diagonal * this->A); |
|||
|
|||
// Set up additional environment variables.
|
|||
storm::dd::Add<DdType> xCopy = x; |
|||
uint_fast64_t iterationCount = 0; |
|||
bool converged = false; |
|||
|
|||
while (!converged && iterationCount < maximalNumberOfIterations) { |
|||
storm::dd::Add<DdType> xCopyAsColumn = xCopy.swapVariables(this->rowColumnMetaVariablePairs); |
|||
storm::dd::Add<DdType> tmp = lu.multiplyMatrix(xCopyAsColumn, this->columnMetaVariables); |
|||
tmp = b - tmp; |
|||
tmp = tmp.swapVariables(this->rowColumnMetaVariablePairs); |
|||
tmp = dinv.multiplyMatrix(tmp, this->columnMetaVariables); |
|||
|
|||
// Now check if the process already converged within our precision.
|
|||
converged = xCopy.equalModuloPrecision(tmp, precision, relative); |
|||
|
|||
// If the method did not converge yet, we prepare the x vector for the next iteration.
|
|||
if (!converged) { |
|||
xCopy = tmp; |
|||
} |
|||
|
|||
// Increase iteration count so we can abort if convergence is too slow.
|
|||
++iterationCount; |
|||
} |
|||
|
|||
return xCopy; |
|||
} |
|||
|
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
storm::dd::Add<DdType> SymbolicLinearEquationSolver<DdType, ValueType>::performMatrixVectorMultiplication(storm::dd::Add<DdType> const& x, storm::dd::Add<DdType> const* b, uint_fast64_t n) const { |
|||
storm::dd::Add<DdType> xCopy = x; |
|||
|
|||
// Perform matrix-vector multiplication while the bound is met.
|
|||
for (uint_fast64_t i = 0; i < n; ++i) { |
|||
xCopy = xCopy.swapVariables(this->rowColumnMetaVariablePairs); |
|||
xCopy = this->A.multiplyMatrix(xCopy, this->columnMetaVariables); |
|||
if (b != nullptr) { |
|||
xCopy += *b; |
|||
} |
|||
} |
|||
|
|||
return xCopy; |
|||
} |
|||
|
|||
template class SymbolicLinearEquationSolver<storm::dd::DdType::CUDD, double>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
#ifndef STORM_SOLVER_SYMBOLICLINEAREQUATIONSOLVER_H_ |
|||
#define STORM_SOLVER_SYMBOLICLINEAREQUATIONSOLVER_H_ |
|||
|
|||
#include <memory> |
|||
#include <set> |
|||
#include <boost/variant.hpp> |
|||
|
|||
#include "src/storage/expressions/Variable.h" |
|||
#include "src/storage/dd/Bdd.h" |
|||
#include "src/storage/dd/Add.h" |
|||
#include "src/storage/dd/Odd.h" |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
/*! |
|||
* An interface that represents an abstract symbolic linear equation solver. In addition to solving a system of |
|||
* linear equations, the functionality to repeatedly multiply a matrix with a given vector is provided. |
|||
*/ |
|||
template<storm::dd::DdType DdType, typename ValueType> |
|||
class SymbolicLinearEquationSolver { |
|||
public: |
|||
/*! |
|||
* Constructs a symbolic linear equation solver with the given meta variable sets and pairs. |
|||
* |
|||
* @param A The matrix defining the coefficients of the linear equation system. |
|||
* @param diagonal An ADD characterizing the elements on the diagonal of the matrix. |
|||
* @param allRows A BDD characterizing all rows of the equation system. |
|||
* @param rowMetaVariables The meta variables used to encode the rows of the matrix. |
|||
* @param columnMetaVariables The meta variables used to encode the columns of the matrix. |
|||
* @param rowColumnMetaVariablePairs The pairs of row meta variables and the corresponding column meta |
|||
* variables. |
|||
*/ |
|||
SymbolicLinearEquationSolver(storm::dd::Add<DdType> const& A, storm::dd::Bdd<DdType> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs); |
|||
|
|||
/*! |
|||
* Constructs a symbolic linear equation solver with the given meta variable sets and pairs. |
|||
* |
|||
* @param A The matrix defining the coefficients of the linear equation system. |
|||
* @param allRows A BDD characterizing all rows of the equation system. |
|||
* @param rowMetaVariables The meta variables used to encode the rows of the matrix. |
|||
* @param columnMetaVariables The meta variables used to encode the columns of the matrix. |
|||
* @param rowColumnMetaVariablePairs The pairs of row meta variables and the corresponding column meta |
|||
* variables. |
|||
* @param precision The precision to achieve. |
|||
* @param maximalNumberOfIterations The maximal number of iterations to perform when solving a linear |
|||
* equation system iteratively. |
|||
* @param relative Sets whether or not to use a relativ stopping criterion rather than an absolute one. |
|||
*/ |
|||
SymbolicLinearEquationSolver(storm::dd::Add<DdType> const& A, storm::dd::Bdd<DdType> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, double precision, uint_fast64_t maximalNumberOfIterations, bool relative); |
|||
|
|||
/*! |
|||
* Solves the equation system A*x = b. The matrix A is required to be square and have a unique solution. |
|||
* The solution of the set of linear equations will be written to the vector x. Note that the matrix A has |
|||
* to be given upon construction time of the solver object. |
|||
* |
|||
* @param x The solution vector that has to be computed. Its length must be equal to the number of rows of A. |
|||
* @param b The right-hand side of the equation system. Its length must be equal to the number of rows of A. |
|||
* @return The solution of the equation system. |
|||
*/ |
|||
virtual storm::dd::Add<DdType> solveEquationSystem(storm::dd::Add<DdType> const& x, storm::dd::Add<DdType> const& b) const; |
|||
|
|||
/*! |
|||
* Performs repeated matrix-vector multiplication, using x[0] = x and x[i + 1] = A*x[i] + b. After |
|||
* performing the necessary multiplications, the result is written to the input vector x. Note that the |
|||
* matrix A has to be given upon construction time of the solver object. |
|||
* |
|||
* @param x The initial vector with which to perform matrix-vector multiplication. Its length must be equal |
|||
* to the number of rows of A. |
|||
* @param b If non-null, this vector is added after each multiplication. If given, its length must be equal |
|||
* to the number of rows of A. |
|||
* @return The solution of the equation system. |
|||
*/ |
|||
virtual storm::dd::Add<DdType> performMatrixVectorMultiplication(storm::dd::Add<DdType> const& x, storm::dd::Add<DdType> const* b = nullptr, uint_fast64_t n = 1) const; |
|||
|
|||
protected: |
|||
// The matrix defining the coefficients of the linear equation system. |
|||
storm::dd::Add<DdType> const& A; |
|||
|
|||
// A BDD characterizing all rows of the equation system. |
|||
storm::dd::Bdd<DdType> const& allRows; |
|||
|
|||
// The row variables. |
|||
std::set<storm::expressions::Variable> rowMetaVariables; |
|||
|
|||
// The column variables. |
|||
std::set<storm::expressions::Variable> columnMetaVariables; |
|||
|
|||
// The pairs of meta variables used for renaming. |
|||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs; |
|||
|
|||
// The precision to achive. |
|||
double precision; |
|||
|
|||
// The maximal number of iterations to perform. |
|||
uint_fast64_t maximalNumberOfIterations; |
|||
|
|||
// A flag indicating whether a relative or an absolute stopping criterion is to be used. |
|||
bool relative; |
|||
}; |
|||
|
|||
} // namespace solver |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_SOLVER_SYMBOLICLINEAREQUATIONSOLVER_H_ */ |
@ -0,0 +1,172 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/logic/Formulas.h"
|
|||
#include "src/utility/solver.h"
|
|||
#include "src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.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(SymbolicDtmcPrctlModelCheckerTest, 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.
|
|||
#ifdef WINDOWS
|
|||
storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
#else
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
#endif
|
|||
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::SymbolicDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>>(new storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, 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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0/6.0, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult4 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(3.6666622161865234, quantitativeResult4.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(3.6666622161865234, quantitativeResult4.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(SymbolicDtmcPrctlModelCheckerTest, 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::SymbolicDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>>(new storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, 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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.33288236360191303, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.33288236360191303, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult2 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.15222081144084315, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.15222081144084315, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(0.3215392962289586, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.3215392962289586, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
|||
TEST(SymbolicDtmcPrctlModelCheckerTest, 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.
|
|||
#ifdef WINDOWS
|
|||
storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
#else
|
|||
typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options; |
|||
#endif
|
|||
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::SymbolicDtmcPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*dtmc, std::unique_ptr<storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>>(new storm::utility::solver::SymbolicLinearEquationSolverFactory<storm::dd::DdType::CUDD, 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::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0, quantitativeResult1.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, 20); |
|||
|
|||
result = checker.check(*boundedUntilFormula); |
|||
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(0.99999989760000074, quantitativeResult2.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(0.99999989760000074, quantitativeResult2.getMax(), storm::settings::nativeEquationSolverSettings().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::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>(); |
|||
|
|||
EXPECT_NEAR(1.0416666666666643, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
EXPECT_NEAR(1.0416666666666643, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
|||
|
@ -0,0 +1,64 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/storage/dd/CuddDdManager.h"
|
|||
|
|||
#include "src/utility/solver.h"
|
|||
|
|||
TEST(FullySymbolicGameSolverTest, Solve) { |
|||
// Create some variables.
|
|||
std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>()); |
|||
std::pair<storm::expressions::Variable, storm::expressions::Variable> state = manager->addMetaVariable("x", 1, 4); |
|||
std::pair<storm::expressions::Variable, storm::expressions::Variable> pl1 = manager->addMetaVariable("a", 0, 1); |
|||
std::pair<storm::expressions::Variable, storm::expressions::Variable> pl2 = manager->addMetaVariable("b", 0, 1); |
|||
|
|||
storm::dd::Bdd<storm::dd::DdType::CUDD> allRows = manager->getBddZero(); |
|||
std::set<storm::expressions::Variable> rowMetaVariables({state.first}); |
|||
std::set<storm::expressions::Variable> columnMetaVariables({state.second}); |
|||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> rowColumnMetaVariablePairs = {state}; |
|||
std::set<storm::expressions::Variable> player1Variables({pl1.first}); |
|||
std::set<storm::expressions::Variable> player2Variables({pl2.first}); |
|||
|
|||
// Construct simple game.
|
|||
storm::dd::Add<storm::dd::DdType::CUDD> matrix = manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 2).toAdd() * manager->getEncoding(pl1.first, 0).toAdd() * manager->getEncoding(pl2.first, 0).toAdd() * manager->getConstant(0.6); |
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 1).toAdd() * manager->getEncoding(pl1.first, 0).toAdd() * manager->getEncoding(pl2.first, 0).toAdd() * manager->getConstant(0.4); |
|||
|
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 2).toAdd() * manager->getEncoding(pl1.first, 0).toAdd() * manager->getEncoding(pl2.first, 1).toAdd() * manager->getConstant(0.2); |
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 3).toAdd() * manager->getEncoding(pl1.first, 0).toAdd() * manager->getEncoding(pl2.first, 1).toAdd() * manager->getConstant(0.8); |
|||
|
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 3).toAdd() * manager->getEncoding(pl1.first, 1).toAdd() * manager->getEncoding(pl2.first, 0).toAdd() * manager->getConstant(0.5); |
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 4).toAdd() * manager->getEncoding(pl1.first, 1).toAdd() * manager->getEncoding(pl2.first, 0).toAdd() * manager->getConstant(0.5); |
|||
|
|||
matrix += manager->getEncoding(state.first, 1).toAdd() * manager->getEncoding(state.second, 1).toAdd() * manager->getEncoding(pl1.first, 1).toAdd() * manager->getEncoding(pl2.first, 1).toAdd() * manager->getConstant(1); |
|||
|
|||
std::unique_ptr<storm::utility::solver::SymbolicGameSolverFactory<storm::dd::DdType::CUDD>> solverFactory(new storm::utility::solver::SymbolicGameSolverFactory<storm::dd::DdType::CUDD>()); |
|||
std::unique_ptr<storm::solver::SymbolicGameSolver<storm::dd::DdType::CUDD>> solver = solverFactory->create(matrix, allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs, player1Variables,player2Variables); |
|||
|
|||
// Create solution and target state vector.
|
|||
storm::dd::Add<storm::dd::DdType::CUDD> x = manager->getAddZero(); |
|||
storm::dd::Add<storm::dd::DdType::CUDD> b = manager->getEncoding(state.first, 2).toAdd() + manager->getEncoding(state.first, 4).toAdd(); |
|||
|
|||
// Now solve the game with different strategies for the players.
|
|||
storm::dd::Add<storm::dd::DdType::CUDD> result = solver->solveGame(true, true, x, b); |
|||
result *= manager->getEncoding(state.first, 1).toAdd(); |
|||
result = result.sumAbstract({state.first}); |
|||
EXPECT_NEAR(0, result.getValue(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
x = manager->getAddZero(); |
|||
result = solver->solveGame(true, false, x, b); |
|||
result *= manager->getEncoding(state.first, 1).toAdd(); |
|||
result = result.sumAbstract({state.first}); |
|||
EXPECT_NEAR(0.5, result.getValue(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
x = manager->getAddZero(); |
|||
result = solver->solveGame(false, true, x, b); |
|||
result *= manager->getEncoding(state.first, 1).toAdd(); |
|||
result = result.sumAbstract({state.first}); |
|||
EXPECT_NEAR(0.2, result.getValue(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
|
|||
x = manager->getAddZero(); |
|||
result = solver->solveGame(false, false, x, b); |
|||
result *= manager->getEncoding(state.first, 1).toAdd(); |
|||
result = result.sumAbstract({state.first}); |
|||
EXPECT_NEAR(0.99999892625817599, result.getValue(), storm::settings::nativeEquationSolverSettings().getPrecision()); |
|||
} |
Reference in new issue
xxxxxxxxxx