Browse Source

Merge remote-tracking branch 'remotes/origin/menu_games' into sylvanRationalFunctions

Former-commit-id: 6038e8bb98
tempestpy_adaptions
PBerger 8 years ago
parent
commit
a73221c24b
  1. 40
      src/abstraction/prism/AbstractProgram.cpp
  2. 95
      src/modelchecker/abstraction/GameBasedMdpModelChecker.cpp
  3. 18
      src/modelchecker/abstraction/GameBasedMdpModelChecker.h
  4. 20
      src/modelchecker/results/SymbolicQualitativeCheckResult.cpp
  5. 4
      src/modelchecker/results/SymbolicQualitativeCheckResult.h
  6. 5
      src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp
  7. 1
      src/modelchecker/results/SymbolicQuantitativeCheckResult.h
  8. 12
      src/utility/graph.h

40
src/abstraction/prism/AbstractProgram.cpp

@ -281,16 +281,46 @@ namespace storm {
index <<= 1;
if (stateValue.first.getBooleanValue(abstractionInformation.getPlayer2Variables()[player2VariableIndex])) {
index |= 1;
} }
}
}
out << stateName.str() << "_" << index;
out << " [ shape=\"point\", label=\"\" ];" << std::endl;
out << "\tpl2_" << stateName.str() << " -> " << "plp_" << stateName.str() << "_" << index << " [ label=\"" << index << "\" ];" << std::endl;
}
// for (auto stateValue : currentGame->getTransitionMatrix()) {
// std::stringstream stateName;
//
// }
for (auto stateValue : currentGame->getTransitionMatrix()) {
std::stringstream sourceStateName;
std::stringstream successorStateName;
for (auto const& var : currentGame->getRowVariables()) {
if (stateValue.first.getBooleanValue(var)) {
sourceStateName << "1";
} else {
sourceStateName << "0";
}
}
for (auto const& var : currentGame->getColumnVariables()) {
if (stateValue.first.getBooleanValue(var)) {
successorStateName << "1";
} else {
successorStateName << "0";
}
}
uint_fast64_t pl1Index = 0;
for (uint_fast64_t player1VariableIndex = 0; player1VariableIndex < abstractionInformation.getPlayer1VariableCount(); ++player1VariableIndex) {
pl1Index <<= 1;
if (stateValue.first.getBooleanValue(abstractionInformation.getPlayer1Variables()[player1VariableIndex])) {
pl1Index |= 1;
}
}
uint_fast64_t pl2Index = 0;
for (uint_fast64_t player2VariableIndex = 0; player2VariableIndex < currentGame->getPlayer2Variables().size(); ++player2VariableIndex) {
pl2Index <<= 1;
if (stateValue.first.getBooleanValue(abstractionInformation.getPlayer2Variables()[player2VariableIndex])) {
pl2Index |= 1;
}
}
out << "\tplp_" << sourceStateName.str() << "_" << pl1Index << "_" << pl2Index << " -> pl1_" << successorStateName.str() << " [ label=\"" << stateValue.second << "\"];" << std::endl;
}
out << "}" << std::endl;
}

95
src/modelchecker/abstraction/GameBasedMdpModelChecker.cpp

@ -1,14 +1,18 @@
#include "src/modelchecker/abstraction/GameBasedMdpModelChecker.h"
#include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
#include "src/models/symbolic/StandardRewardModel.h"
#include "src/storage/expressions/ExpressionManager.h"
#include "src/storage/dd/DdManager.h"
#include "src/abstraction/prism/PrismMenuGameAbstractor.h"
#include "src/logic/FragmentSpecification.h"
#include "src/utility/graph.h"
#include "src/utility/macros.h"
#include "src/exceptions/NotSupportedException.h"
@ -18,6 +22,13 @@
namespace storm {
namespace modelchecker {
namespace detail {
template<storm::dd::DdType DdType>
GameProb01Result<DdType>::GameProb01Result(storm::utility::graph::GameProb01Result<DdType> const& prob0Min, storm::utility::graph::GameProb01Result<DdType> const& prob1Min, storm::utility::graph::GameProb01Result<DdType> const& prob0Max, storm::utility::graph::GameProb01Result<DdType> const& prob1Max) : min(std::make_pair(prob0Min, prob1Min)), max(std::make_pair(prob0Max, prob1Max)) {
// Intentionally left empty.
}
}
template<storm::dd::DdType Type, typename ValueType>
GameBasedMdpModelChecker<Type, ValueType>::GameBasedMdpModelChecker(storm::prism::Program const& program, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : originalProgram(program), smtSolverFactory(smtSolverFactory) {
STORM_LOG_THROW(program.getModelType() == storm::prism::Program::ModelType::DTMC || program.getModelType() == storm::prism::Program::ModelType::MDP, storm::exceptions::NotSupportedException, "Currently only DTMCs/MDPs are supported by the game-based model checker.");
@ -54,10 +65,39 @@ namespace storm {
return performGameBasedAbstractionRefinement(checkTask.substituteFormula<storm::logic::Formula>(pathFormula), originalProgram.getManager().boolean(true), getExpression(pathFormula.getSubformula()));
}
template<typename ValueType>
bool getResultConsideringBound(ValueType const& value, storm::logic::Bound<ValueType> const& bound) {
if (storm::logic::isLowerBound(bound.comparisonType)) {
if (storm::logic::isStrict(bound.comparisonType)) {
return value > bound.threshold;
} else {
return value >= bound.threshold;
}
} else {
if (storm::logic::isStrict(bound.comparisonType)) {
return value < bound.threshold;
} else {
return value <= bound.threshold;
}
}
}
template<storm::dd::DdType Type, typename ValueType>
std::unique_ptr<CheckResult> getResultAfterQualitativeCheck(CheckTask<storm::logic::Formula> const& checkTask, storm::dd::DdManager<Type> const& ddManager, storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& initialStates, bool prob0) {
if (checkTask.isBoundSet()) {
bool result = getResultConsideringBound(prob0 ? storm::utility::zero<ValueType>() : storm::utility::one<ValueType>(), checkTask.getBound());
return std::make_unique<storm::modelchecker::SymbolicQualitativeCheckResult<Type>>(reachableStates, initialStates, result ? initialStates : ddManager.getBddZero());
} else {
return std::make_unique<storm::modelchecker::SymbolicQuantitativeCheckResult<Type>>(reachableStates, initialStates, prob0 ? ddManager.template getAddZero<ValueType>() : initialStates.template toAdd<ValueType>());
}
}
template<storm::dd::DdType Type, typename ValueType>
std::unique_ptr<CheckResult> GameBasedMdpModelChecker<Type, ValueType>::performGameBasedAbstractionRefinement(CheckTask<storm::logic::Formula> const& checkTask, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression) {
STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::InvalidPropertyException, "The game-based abstraction refinement model checker can only compute the result for the initial states.");
// Optimization: do not compute both bounds if not necessary (e.g. if bound given and exceeded, etc.)
// Set up initial predicates.
std::vector<storm::expressions::Expression> initialPredicates;
initialPredicates.push_back(targetStateExpression);
@ -72,13 +112,39 @@ namespace storm {
// 1. build initial abstraction based on the the constraint expression (if not 'true') and the target state expression.
storm::abstraction::MenuGame<Type, ValueType> game = abstractor.abstract();
abstractor.exportToDot("game.dot");
STORM_LOG_DEBUG("Initial abstraction has " << game.getNumberOfStates() << " (player 1) states and " << game.getNumberOfTransitions() << " transitions.");
// 2. compute all states with probability 0/1 wrt. to the two different player 2 goals (min/max).
detail::GameProb01Result<Type> prob01 = computeProb01States(player1Direction, game, constraintExpression, targetStateExpression);
// 3. compute the states for which we know the result/for which we know there is more work to be done.
storm::dd::Bdd<Type> maybeMin = !(prob01.min.first.states || prob01.min.second.states) && game.getReachableStates();
storm::dd::Bdd<Type> maybeMax = !(prob01.max.first.states || prob01.max.second.states) && game.getReachableStates();
// 4. if the initial states are not maybe states, then we can refine at this point.
storm::dd::Bdd<Type> initialMaybeStates = game.getInitialStates() && (maybeMin || maybeMax);
if (initialMaybeStates.isZero()) {
// In this case, we know the result for the initial states for both player 2 minimizing and maximizing.
// If the result is 0 independent of the player 2 strategy, then we know the final result and can return it.
storm::dd::Bdd<Type> tmp = game.getInitialStates() && prob01.min.first.states && prob01.max.first.states;
if (tmp == game.getInitialStates()) {
getResultAfterQualitativeCheck<Type, ValueType>(checkTask, game.getManager(), game.getReachableStates(), game.getInitialStates(), true);
}
// If the result is 1 independent of the player 2 strategy, then we know the final result and can return it.
tmp = game.getInitialStates() && prob01.min.second.states && prob01.max.second.states;
if (tmp == game.getInitialStates()) {
getResultAfterQualitativeCheck<Type, ValueType>(checkTask, game.getManager(), game.getReachableStates(), game.getInitialStates(), false);
}
// If we get here, the initial states were all identified as prob0/1 states, but the value (0 or 1)
// depends on whether player 2 is minimizing or maximizing. Therefore, we need to find a place to refine.
}
// 2. solve the game wrt. to min/max as given by checkTask and min/max for the abstraction player to obtain two bounds.
// Note that we have to deal with bottom states if not all guards were added in the beginning.
// Also note that it might be the case that not both bounds need to be computed if there is a bound given in checkTask.
computeProb01States(player1Direction, game, constraintExpression, targetStateExpression);
// std::unique_ptr<storm::utility::solver::SymbolicGameSolverFactory<Type, ValueType>> gameSolverFactory = std::make_unique<storm::utility::solver::SymbolicGameSolverFactory<Type, ValueType>>();
// gameSolverFactory->create(game.getTransitionMatrix(), game.getReachableStates());
@ -92,7 +158,7 @@ namespace storm {
}
template<storm::dd::DdType Type, typename ValueType>
void GameBasedMdpModelChecker<Type, ValueType>::computeProb01States(storm::OptimizationDirection player1Direction, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression) {
detail::GameProb01Result<Type> GameBasedMdpModelChecker<Type, ValueType>::computeProb01States(storm::OptimizationDirection player1Direction, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression) {
storm::dd::Bdd<Type> transitionMatrixBdd = game.getTransitionMatrix().toBdd();
storm::dd::Bdd<Type> bottomStatesBdd = game.getBottomStates();
@ -100,8 +166,6 @@ namespace storm {
if (player1Direction == storm::OptimizationDirection::Minimize) {
targetStates |= game.getBottomStates();
}
transitionMatrixBdd.template toAdd<ValueType>().exportToDot("transbdd.dot");
// Start by computing the states with probability 0/1 when player 2 minimizes.
storm::utility::graph::GameProb01Result<Type> prob0Min = storm::utility::graph::performProb0(game, transitionMatrixBdd, game.getStates(constraintExpression), targetStates, player1Direction, storm::OptimizationDirection::Minimize, true);
@ -111,21 +175,10 @@ namespace storm {
storm::utility::graph::GameProb01Result<Type> prob0Max = storm::utility::graph::performProb0(game, transitionMatrixBdd, game.getStates(constraintExpression), targetStates, player1Direction, storm::OptimizationDirection::Maximize, false);
storm::utility::graph::GameProb01Result<Type> prob1Max = storm::utility::graph::performProb1(game, transitionMatrixBdd, game.getStates(constraintExpression), targetStates, player1Direction, storm::OptimizationDirection::Maximize, true);
// STORM_LOG_ASSERT(prob0Min.hasPlayer1Strategy(), "Unable to proceed without strategy.");
STORM_LOG_ASSERT(prob0Min.hasPlayer2Strategy(), "Unable to proceed without strategy.");
STORM_LOG_ASSERT(prob1Max.hasPlayer1Strategy(), "Unable to proceed without strategy.");
STORM_LOG_ASSERT(prob1Max.hasPlayer2Strategy(), "Unable to proceed without strategy.");
// prob0Min.getPlayer1Strategy().template toAdd<ValueType>().exportToDot("prob0_min_pl1_strat.dot");
prob0Min.getPlayer2Strategy().template toAdd<ValueType>().exportToDot("prob0_min_pl2_strat.dot");
prob1Max.getPlayer1Strategy().template toAdd<ValueType>().exportToDot("prob1_max_pl1_strat.dot");
prob1Max.getPlayer2Strategy().template toAdd<ValueType>().exportToDot("prob1_max_pl2_strat.dot");
STORM_LOG_DEBUG("Min: " << prob0Min.states.getNonZeroCount() << " no states, " << prob1Min.states.getNonZeroCount() << " yes states.");
STORM_LOG_DEBUG("Max: " << prob0Max.states.getNonZeroCount() << " no states, " << prob1Max.states.getNonZeroCount() << " yes states.");
return detail::GameProb01Result<Type>(prob0Min, prob1Min, prob0Max, prob1Max);
}
template<storm::dd::DdType Type, typename ValueType>

18
src/modelchecker/abstraction/GameBasedMdpModelChecker.h

@ -3,12 +3,13 @@
#include "src/modelchecker/AbstractModelChecker.h"
#include "src/utility/solver.h"
#include "src/storage/prism/Program.h"
#include "src/storage/dd/DdType.h"
#include "src/utility/solver.h"
#include "src/utility/graph.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
@ -16,6 +17,17 @@ namespace storm {
}
namespace modelchecker {
namespace detail {
template<storm::dd::DdType Type>
struct GameProb01Result {
public:
GameProb01Result(storm::utility::graph::GameProb01Result<Type> const& prob0Min, storm::utility::graph::GameProb01Result<Type> const& prob1Min, storm::utility::graph::GameProb01Result<Type> const& prob0Max, storm::utility::graph::GameProb01Result<Type> const& prob1Max);
std::pair<storm::utility::graph::GameProb01Result<Type>, storm::utility::graph::GameProb01Result<Type>> min;
std::pair<storm::utility::graph::GameProb01Result<Type>, storm::utility::graph::GameProb01Result<Type>> max;
};
}
template<storm::dd::DdType Type, typename ValueType>
class GameBasedMdpModelChecker : public AbstractModelChecker {
public:
@ -38,7 +50,7 @@ namespace storm {
private:
std::unique_ptr<CheckResult> performGameBasedAbstractionRefinement(CheckTask<storm::logic::Formula> const& checkTask, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression);
void computeProb01States(storm::OptimizationDirection player1Direction, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression);
detail::GameProb01Result<Type> computeProb01States(storm::OptimizationDirection player1Direction, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression);
storm::expressions::Expression getExpression(storm::logic::Formula const& formula);

20
src/modelchecker/results/SymbolicQualitativeCheckResult.cpp

@ -6,7 +6,12 @@
namespace storm {
namespace modelchecker {
template <storm::dd::DdType Type>
SymbolicQualitativeCheckResult<Type>::SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& truthValues) : reachableStates(reachableStates), truthValues(truthValues) {
SymbolicQualitativeCheckResult<Type>::SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& truthValues) : reachableStates(reachableStates), states(reachableStates), truthValues(truthValues) {
// Intentionally left empty.
}
template <storm::dd::DdType Type>
SymbolicQualitativeCheckResult<Type>::SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& states, storm::dd::Bdd<Type> const& truthValues) : reachableStates(reachableStates), states(states), truthValues(truthValues) {
// Intentionally left empty.
}
@ -17,7 +22,7 @@ namespace storm {
template <storm::dd::DdType Type>
bool SymbolicQualitativeCheckResult<Type>::isResultForAllStates() const {
return true;
return reachableStates == states;
}
template <storm::dd::DdType Type>
@ -51,10 +56,14 @@ namespace storm {
template <storm::dd::DdType Type>
std::ostream& SymbolicQualitativeCheckResult<Type>::writeToStream(std::ostream& out) const {
if (this->truthValues.isZero()) {
out << "[false]" << std::endl;
} else {
if (states == truthValues) {
out << "[true]" << std::endl;
} else {
if (truthValues.isZero()) {
out << "[false]" << std::endl;
} else {
out << "[true false]" << std::endl;
}
}
return out;
}
@ -62,6 +71,7 @@ namespace storm {
template <storm::dd::DdType Type>
void SymbolicQualitativeCheckResult<Type>::filter(QualitativeCheckResult const& filter) {
STORM_LOG_THROW(filter.isSymbolicQualitativeCheckResult(), storm::exceptions::InvalidOperationException, "Cannot filter symbolic check result with non-symbolic filter.");
this->states &= filter.asSymbolicQualitativeCheckResult<Type>().getTruthValuesVector();;
this->truthValues &= filter.asSymbolicQualitativeCheckResult<Type>().getTruthValuesVector();
}

4
src/modelchecker/results/SymbolicQualitativeCheckResult.h

@ -13,6 +13,7 @@ namespace storm {
public:
SymbolicQualitativeCheckResult() = default;
SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& truthValues);
SymbolicQualitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& states, storm::dd::Bdd<Type> const& truthValues);
SymbolicQualitativeCheckResult(SymbolicQualitativeCheckResult const& other) = default;
SymbolicQualitativeCheckResult& operator=(SymbolicQualitativeCheckResult const& other) = default;
@ -40,6 +41,9 @@ namespace storm {
// The set of all reachable states.
storm::dd::Bdd<Type> reachableStates;
// The states for which this check result contains a truth value.
storm::dd::Bdd<Type> states;
// The values of the qualitative check result.
storm::dd::Bdd<Type> truthValues;
};

5
src/modelchecker/results/SymbolicQuantitativeCheckResult.cpp

@ -15,6 +15,11 @@ namespace storm {
// Intentionally left empty.
}
template<storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeCheckResult<Type, ValueType>::SymbolicQuantitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& states, storm::dd::Add<Type, ValueType> const& values) : reachableStates(reachableStates), states(states), values(values) {
// Intentionally left empty.
}
template<storm::dd::DdType Type, typename ValueType>
std::unique_ptr<CheckResult> SymbolicQuantitativeCheckResult<Type, ValueType>::compareAgainstBound(storm::logic::ComparisonType comparisonType, double bound) const {
storm::dd::Bdd<Type> states;

1
src/modelchecker/results/SymbolicQuantitativeCheckResult.h

@ -13,6 +13,7 @@ namespace storm {
public:
SymbolicQuantitativeCheckResult() = default;
SymbolicQuantitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Add<Type, ValueType> const& values);
SymbolicQuantitativeCheckResult(storm::dd::Bdd<Type> const& reachableStates, storm::dd::Bdd<Type> const& states, storm::dd::Add<Type, ValueType> const& values);
SymbolicQuantitativeCheckResult(SymbolicQuantitativeCheckResult const& other) = default;
SymbolicQuantitativeCheckResult& operator=(SymbolicQuantitativeCheckResult const& other) = default;

12
src/utility/graph.h

@ -532,18 +532,26 @@ namespace storm {
return static_cast<bool>(player1Strategy);
}
storm::dd::Bdd<Type> const& getPlayer1Strategy() {
storm::dd::Bdd<Type> const& getPlayer1Strategy() const {
return player1Strategy.get();
}
boost::optional<storm::dd::Bdd<Type>> const& getOptionalPlayer1Strategy() {
return player1Strategy;
}
bool hasPlayer2Strategy() const {
return static_cast<bool>(player2Strategy);
}
storm::dd::Bdd<Type> const& getPlayer2Strategy() {
storm::dd::Bdd<Type> const& getPlayer2Strategy() const {
return player2Strategy.get();
}
boost::optional<storm::dd::Bdd<Type>> const& getOptionalPlayer2Strategy() {
return player2Strategy;
}
storm::dd::Bdd<Type> const& getStates() const {
return states;
}

Loading…
Cancel
Save