Browse Source

added some convenience accessor methods in symbolic model/games. added return type for prob01 for games that can also store strategies. added tests for prob0 for games

Former-commit-id: f0a8b156ca
main
dehnert 10 years ago
parent
commit
972795912a
  1. 5
      src/models/symbolic/Model.cpp
  2. 10
      src/models/symbolic/Model.h
  3. 1
      src/models/symbolic/StochasticTwoPlayerGame.cpp
  4. 2
      src/storage/prism/menu_games/AbstractProgram.cpp
  5. 13
      src/storage/prism/menu_games/MenuGame.cpp
  6. 17
      src/storage/prism/menu_games/MenuGame.h
  7. 44
      src/utility/graph.cpp
  8. 13
      src/utility/graph.h
  9. 35
      test/functional/utility/GraphTest.cpp

5
src/models/symbolic/Model.cpp

@ -90,6 +90,11 @@ namespace storm {
return transitionMatrix;
}
template<storm::dd::DdType Type>
storm::dd::Bdd<Type> Model<Type>::getQualitativeTransitionMatrix() const {
return this->getTransitionMatrix().notZero();
}
template<storm::dd::DdType Type>
std::size_t Model<Type>::getSizeInBytes() const {
return sizeof(*this) + sizeof(DdNode) * (reachableStates.getNodeCount() + initialStates.getNodeCount() + transitionMatrix.getNodeCount());

10
src/models/symbolic/Model.h

@ -123,7 +123,7 @@ namespace storm {
* Returns the set of states labeled satisfying the given expression (that must be of boolean type).
*
* @param expression The expression that needs to hold in the states.
* @return The set of states labeled satisfying the given expression.
* @return The set of states satisfying the given expression.
*/
virtual storm::dd::Bdd<Type> getStates(storm::expressions::Expression const& expression) const;
@ -148,6 +148,14 @@ namespace storm {
* @return A matrix representing the transitions of the model.
*/
storm::dd::Add<Type>& getTransitionMatrix();
/*!
* Retrieves the matrix qualitatively (i.e. without probabilities) representing the transitions of the
* model.
*
* @return A matrix representing the qualitative transitions of the model.
*/
storm::dd::Bdd<Type> getQualitativeTransitionMatrix() const;
/*!
* Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.

1
src/models/symbolic/StochasticTwoPlayerGame.cpp

@ -28,6 +28,7 @@ namespace storm {
: NondeterministicModel<Type>(storm::models::ModelType::S2pg, manager, reachableStates, initialStates, transitionMatrix, rowVariables, rowExpressionAdapter, columnVariables, columnExpressionAdapter, rowColumnMetaVariablePairs, nondeterminismVariables, labelToExpressionMap, rewardModels), player1Variables(player1Variables), player2Variables(player2Variables) {
// Compute legal player 1 mask.
transitionMatrix.exportToDot("trans.dot");
illegalPlayer1Mask = transitionMatrix.notZero().existsAbstract(this->getColumnVariables()).existsAbstract(this->getPlayer2Variables());
// Correct the mask for player 2. This is necessary, because it is not yet restricted to the legal choices of player 1.

2
src/storage/prism/menu_games/AbstractProgram.cpp

@ -153,7 +153,7 @@ namespace storm {
storm::dd::Add<DdType> transitionMatrix = (gameBdd.first && reachableStates).toAdd() * commandUpdateProbabilitiesAdd + deadlockTransitions;
std::set<storm::expressions::Variable> usedPlayer2Variables;
for (uint_fast64_t index = 0; index < ddInformation.optionDdVariables.size(); ++index) {
for (uint_fast64_t index = 0; index < gameBdd.second; ++index) {
usedPlayer2Variables.insert(usedPlayer2Variables.end(), ddInformation.optionDdVariables[index].first);
}

13
src/storage/prism/menu_games/MenuGame.cpp

@ -24,7 +24,7 @@ namespace storm {
std::set<storm::expressions::Variable> const& player2Variables,
std::set<storm::expressions::Variable> const& allNondeterminismVariables,
storm::expressions::Variable const& updateVariable,
std::map<storm::expressions::Expression, storm::dd::Bdd<Type>> const& expressionToBddMap) : storm::models::symbolic::StochasticTwoPlayerGame<Type>(manager, reachableStates, initialStates, transitionMatrix, rowVariables, nullptr, columnVariables, nullptr, rowColumnMetaVariablePairs, player1Variables, player2Variables, allNondeterminismVariables), updateVariable(updateVariable), expressionToBddMap(expressionToBddMap) {
std::map<storm::expressions::Expression, storm::dd::Bdd<Type>> const& expressionToBddMap) : storm::models::symbolic::StochasticTwoPlayerGame<Type>(manager, reachableStates, initialStates, transitionMatrix.sumAbstract({updateVariable}), rowVariables, nullptr, columnVariables, nullptr, rowColumnMetaVariablePairs, player1Variables, player2Variables, allNondeterminismVariables), updateVariable(updateVariable), expressionToBddMap(expressionToBddMap) {
// Intentionally left empty.
}
@ -35,9 +35,18 @@ namespace storm {
template<storm::dd::DdType Type>
storm::dd::Bdd<Type> MenuGame<Type>::getStates(storm::expressions::Expression const& expression) const {
return this->getStates(expression, false);
}
template<storm::dd::DdType Type>
storm::dd::Bdd<Type> MenuGame<Type>::getStates(storm::expressions::Expression const& expression, bool negated) const {
auto it = expressionToBddMap.find(expression);
STORM_LOG_THROW(it != expressionToBddMap.end(), storm::exceptions::InvalidArgumentException, "The given expression was not used in the abstraction process and can therefore not be retrieved.");
return it->second && this->getReachableStates();
if (negated) {
return !it->second && this->getReachableStates();
} else {
return it->second && this->getReachableStates();
}
}
template<storm::dd::DdType Type>

17
src/storage/prism/menu_games/MenuGame.h

@ -59,7 +59,24 @@ namespace storm {
virtual storm::dd::Bdd<Type> getStates(std::string const& label) const override;
/*!
* Returns the set of states satisfying the given expression (that must be of boolean type). Note that
* for menu games, the given expression must be a predicate that was used to build the abstract game.
*
* @param expression The expression that needs to hold in the states.
* @return The set of states satisfying the given expression.
*/
virtual storm::dd::Bdd<Type> getStates(storm::expressions::Expression const& expression) const override;
/*!
* Returns the set of states satisfying the given expression (that must be of boolean type). Note that
* for menu games, the given expression must be a predicate that was used to build the abstract game.
*
* @param expression The expression that needs to hold in the states.
* @param negated If set to true, the result is the set of states not satisfying the expression.
* @return The set of states labeled satisfying the given expression.
*/
storm::dd::Bdd<Type> getStates(storm::expressions::Expression const& expression, bool negated) const;
virtual bool hasLabel(std::string const& label) const override;

44
src/utility/graph.cpp

@ -690,7 +690,7 @@ namespace storm {
}
template <storm::dd::DdType Type>
void performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy) {
GameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy) {
// The solution set.
storm::dd::Bdd<Type> solution = psiStates;
@ -725,26 +725,28 @@ namespace storm {
// Since we have determined the inverse of the desired set, we need to complement it now.
solution = !solution && model.getReachableStates();
// Determine all transitions between prob0 states.
storm::dd::Bdd<Type> transitionsBetweenProb0States = solution && (transitionMatrix && solution.swapVariables(model.getRowColumnMetaVariablePairs()));
return GameProb01Result<Type>(solution);
// Determine the distributions that have only successors that are prob0 states.
storm::dd::Bdd<Type> onlyProb0Successors = (transitionsBetweenProb0States || model.getIllegalSuccessorMask()).universalAbstract(model.getColumnVariables());
boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
if (player2Strategy == OptimizationDirection::Minimize) {
// Pick a distribution that has only prob0 successors.
player2StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer2Variables());
}
boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
if (player1Strategy == OptimizationDirection::Minimize) {
// Move from player 2 choices with only prob0 successors to player 1 choices with only prob 0 successors.
onlyProb0Successors = onlyProb0Successors.existsAbstract(model.getPlayer2Variables());
// Pick a prob0 player 2 state.
onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables());
}
// // Determine all transitions between prob0 states.
// storm::dd::Bdd<Type> transitionsBetweenProb0States = solution && (transitionMatrix && solution.swapVariables(model.getRowColumnMetaVariablePairs()));
//
// // Determine the distributions that have only successors that are prob0 states.
// storm::dd::Bdd<Type> onlyProb0Successors = (transitionsBetweenProb0States || model.getIllegalSuccessorMask()).universalAbstract(model.getColumnVariables());
//
// boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
// if (player2Strategy == OptimizationDirection::Minimize) {
// // Pick a distribution that has only prob0 successors.
// player2StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer2Variables());
// }
//
// boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
// if (player1Strategy == OptimizationDirection::Minimize) {
// // Move from player 2 choices with only prob0 successors to player 1 choices with only prob 0 successors.
// onlyProb0Successors = onlyProb0Successors.existsAbstract(model.getPlayer2Variables());
//
// // Pick a prob0 player 2 state.
// onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables());
// }
}
template <typename T>
@ -1079,7 +1081,7 @@ namespace storm {
template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(storm::models::symbolic::NondeterministicModel<storm::dd::DdType::CUDD> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates) ;
template void performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy);
template GameProb01Result<storm::dd::DdType::CUDD> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy);
} // namespace graph
} // namespace utility

13
src/utility/graph.h

@ -433,6 +433,17 @@ namespace storm {
template <storm::dd::DdType Type>
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
template <storm::dd::DdType Type>
struct GameProb01Result {
GameProb01Result(storm::dd::Bdd<Type> const& states, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy = boost::none, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy = boost::none) : states(states), player1Strategy(player1Strategy), player2Strategy(player2Strategy) {
// Intentionally left empty.
}
storm::dd::Bdd<Type> states;
boost::optional<storm::dd::Bdd<Type>> player1Strategy;
boost::optional<storm::dd::Bdd<Type>> player2Strategy;
};
/*!
* Computes the set of states that have probability 0 given the strategies of the two players.
*
@ -442,7 +453,7 @@ namespace storm {
* @param psiStates The BDD containing all psi states of the model.
*/
template <storm::dd::DdType Type>
void performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy);
GameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy);
/*!
* Performs a topological sort of the states of the system according to the given transitions.

35
test/functional/utility/GraphTest.cpp

@ -88,6 +88,41 @@ TEST(GraphTest, SymbolicProb01MinMax) {
EXPECT_EQ(16ul, statesWithProbability01.second.getNonZeroCount());
}
#ifdef STORM_HAVE_MSAT
#include "src/storage/prism/menu_games/AbstractProgram.h"
#include "src/storage/expressions/Expression.h"
#include "src/utility/solver.h"
TEST(GraphTest, SymbolicProb0StochasticGame) {
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/die.pm");
std::vector<storm::expressions::Expression> initialPredicates;
storm::expressions::ExpressionManager& manager = program.getManager();
initialPredicates.push_back(manager.getVariableExpression("s") < manager.integer(3));
storm::prism::menu_games::AbstractProgram<storm::dd::DdType::CUDD, double> abstractProgram(program.getManager(), program, initialPredicates, std::make_unique<storm::utility::solver::MathsatSmtSolverFactory>(), false);
storm::prism::menu_games::MenuGame<storm::dd::DdType::CUDD> game = abstractProgram.getAbstractGame();
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result1 = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), game.getStates(initialPredicates.front(), true), storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize);
EXPECT_EQ(1, result1.states.getNonZeroCount());
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result2 = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), game.getStates(initialPredicates.front(), true), storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Maximize);
EXPECT_EQ(1, result2.states.getNonZeroCount());
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result3 = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), game.getStates(initialPredicates.front(), true), storm::OptimizationDirection::Maximize, storm::OptimizationDirection::Minimize);
EXPECT_EQ(0, result3.states.getNonZeroCount());
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result4 = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), game.getStates(initialPredicates.front(), true), storm::OptimizationDirection::Maximize, storm::OptimizationDirection::Maximize);
EXPECT_EQ(0, result4.states.getNonZeroCount());
}
#endif
TEST(GraphTest, ExplicitProb01) {
storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/crowds-5-5.pm");
std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);

Loading…
Cancel
Save