Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SymbolicGameSolver.cpp
Go to the documentation of this file.
2
6
8
12
13namespace storm {
14namespace solver {
15
16template<storm::dd::DdType Type, typename ValueType>
18 storm::dd::Add<Type, ValueType> const& A, storm::dd::Bdd<Type> const& allRows, storm::dd::Bdd<Type> const& illegalPlayer1Mask,
19 storm::dd::Bdd<Type> const& illegalPlayer2Mask, std::set<storm::expressions::Variable> const& rowMetaVariables,
20 std::set<storm::expressions::Variable> const& columnMetaVariables,
21 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
22 std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables)
23 : A(A),
24 allRows(allRows),
25 illegalPlayer1Mask(
26 illegalPlayer1Mask.ite(A.getDdManager().getConstant(storm::utility::infinity<ValueType>()), A.getDdManager().template getAddZero<ValueType>())),
27 illegalPlayer2Mask(
28 illegalPlayer2Mask.ite(A.getDdManager().getConstant(storm::utility::infinity<ValueType>()), A.getDdManager().template getAddZero<ValueType>())),
29 rowMetaVariables(rowMetaVariables),
30 columnMetaVariables(columnMetaVariables),
31 rowColumnMetaVariablePairs(rowColumnMetaVariablePairs),
32 player1Variables(player1Variables),
33 player2Variables(player2Variables),
34 generatePlayer1Strategy(false),
35 generatePlayer2Strategy(false) {
36 // Get the default settings
37}
38
39template<storm::dd::DdType Type, typename ValueType>
43 boost::optional<storm::dd::Bdd<Type>> const& basePlayer1Strategy,
44 boost::optional<storm::dd::Bdd<Type>> const& basePlayer2Strategy) {
45 STORM_LOG_WARN_COND(env.solver().game().getMethod() == GameMethod::ValueIteration,
46 "Switching game method to Value iteration since the selected method is not supported by this solver.");
47
48 // Set up the environment.
49 ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().game().getPrecision());
50 bool relative = env.solver().game().getRelativeTerminationCriterion();
51 uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations();
53 uint_fast64_t iterations = 0;
54 bool converged = false;
55
56 // Prepare some data storage in case we need to generate strategies.
57 if (generatePlayer1Strategy) {
58 if (basePlayer1Strategy) {
59 player1Strategy = basePlayer1Strategy.get();
60 } else {
61 player1Strategy = A.getDdManager().getBddZero();
62 }
63 }
64 boost::optional<storm::dd::Add<Type, ValueType>> previousPlayer2Values;
65 if (generatePlayer2Strategy) {
66 if (basePlayer2Strategy && player2Goal == storm::OptimizationDirection::Maximize) {
67 player2Strategy = basePlayer2Strategy.get();
68
69 // If we are required to generate a player 2 strategy based on another one that is not the zero strategy,
70 // we need to determine the values, because only then we can update the strategy only if necessary.
71 previousPlayer2Values = (player2Strategy.get().template toAdd<ValueType>() *
72 (this->A.multiplyMatrix(x.swapVariables(this->rowColumnMetaVariablePairs), this->columnMetaVariables) + b))
73 .sumAbstract(this->player2Variables);
74 } else {
75 player2Strategy = A.getDdManager().getBddZero();
76 previousPlayer2Values = A.getDdManager().template getAddZero<ValueType>();
77 }
78 }
79
80 do {
81 // Compute tmp = A * x + b.
82 storm::dd::Add<Type, ValueType> xCopyAsColumn = xCopy.swapVariables(this->rowColumnMetaVariablePairs);
83 storm::dd::Add<Type, ValueType> tmp = this->A.multiplyMatrix(xCopyAsColumn, this->columnMetaVariables);
84 tmp += b;
85
86 // Now abstract from player 2 and player 1 variables.
87 if (player2Goal == storm::OptimizationDirection::Maximize) {
88 storm::dd::Add<Type, ValueType> newValues = tmp.maxAbstract(this->player2Variables);
89
90 if (generatePlayer2Strategy) {
91 // Update only the choices that strictly improved the value.
92 storm::dd::Bdd<Type> maxChoices = tmp.maxAbstractRepresentative(this->player2Variables);
93 player2Strategy.get() = newValues.greater(previousPlayer2Values.get()).ite(maxChoices, player2Strategy.get());
94 previousPlayer2Values = newValues;
95 }
96
97 tmp = newValues;
98 } else {
99 tmp = (tmp + illegalPlayer2Mask);
100 storm::dd::Add<Type, ValueType> newValues = tmp.minAbstract(this->player2Variables);
101
102 if (generatePlayer2Strategy) {
103 player2Strategy = tmp.minAbstractRepresentative(this->player2Variables);
104 }
105
106 tmp = newValues;
107 }
108
109 if (player1Goal == storm::OptimizationDirection::Maximize) {
110 storm::dd::Add<Type, ValueType> newValues = tmp.maxAbstract(this->player1Variables);
111
112 if (generatePlayer1Strategy) {
113 // Update only the choices that strictly improved the value.
114 storm::dd::Bdd<Type> maxChoices = tmp.maxAbstractRepresentative(this->player1Variables);
115 player1Strategy = newValues.greater(xCopy).ite(maxChoices, player1Strategy.get());
116 }
117
118 tmp = newValues;
119 } else {
120 tmp = (tmp + illegalPlayer1Mask);
121 storm::dd::Add<Type, ValueType> newValues = tmp.minAbstract(this->player1Variables);
122
123 if (generatePlayer1Strategy) {
124 player1Strategy = tmp.minAbstractRepresentative(this->player1Variables);
125 }
126
127 tmp = newValues;
128 }
129
130 // Now check if the process already converged within our precision.
131 converged = xCopy.equalModuloPrecision(tmp, precision, relative);
132
133 // If the method did not converge yet, we prepare the x vector for the next iteration.
134 if (!converged) {
135 xCopy = tmp;
136 }
137
138 ++iterations;
139 } while (!converged && iterations < maxIter);
140 STORM_LOG_INFO("Numerically solving the game took " << iterations << " iterations.");
141
142 return xCopy;
143}
144
145template<storm::dd::DdType Type, typename ValueType>
147 generatePlayer1Strategy = value;
148}
149
150template<storm::dd::DdType Type, typename ValueType>
152 generatePlayer2Strategy = value;
153}
154
155template<storm::dd::DdType Type, typename ValueType>
157 setGeneratePlayer1Strategy(value);
158 setGeneratePlayer2Strategy(value);
159}
160
161template<storm::dd::DdType Type, typename ValueType>
163 STORM_LOG_THROW(player1Strategy, storm::exceptions::IllegalFunctionCallException, "Cannot retrieve player 1 strategy because none was generated.");
164 return player1Strategy.get();
165}
166
167template<storm::dd::DdType Type, typename ValueType>
169 STORM_LOG_THROW(player2Strategy, storm::exceptions::IllegalFunctionCallException, "Cannot retrieve player 2 strategy because none was generated.");
170 return player2Strategy.get();
171}
172
173template<storm::dd::DdType Type, typename ValueType>
174std::unique_ptr<storm::solver::SymbolicGameSolver<Type, ValueType>> SymbolicGameSolverFactory<Type, ValueType>::create(
175 storm::dd::Add<Type, ValueType> const& A, storm::dd::Bdd<Type> const& allRows, storm::dd::Bdd<Type> const& illegalPlayer1Mask,
176 storm::dd::Bdd<Type> const& illegalPlayer2Mask, std::set<storm::expressions::Variable> const& rowMetaVariables,
177 std::set<storm::expressions::Variable> const& columnMetaVariables,
178 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
179 std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables) const {
180 return std::unique_ptr<storm::solver::SymbolicGameSolver<Type, ValueType>>(
181 new storm::solver::SymbolicGameSolver<Type, ValueType>(A, allRows, illegalPlayer1Mask, illegalPlayer2Mask, rowMetaVariables, columnMetaVariables,
182 rowColumnMetaVariablePairs, player1Variables, player2Variables));
183}
184
188
192
193} // namespace solver
194} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
uint64_t const & getMaximalNumberOfIterations() const
bool const & getRelativeTerminationCriterion() const
storm::solver::GameMethod const & getMethod() const
GameSolverEnvironment & game()
Add< LibraryType, ValueType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the ADD.
Definition Add.cpp:292
Bdd< LibraryType > greater(Add< LibraryType, ValueType > const &other) const
Retrieves the function that maps all evaluations to one whose function value in the first ADD are gre...
Definition Add.cpp:116
Add< LibraryType, ValueType > maxAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Max-abstracts from the given meta variables.
Definition Add.cpp:198
Bdd< LibraryType > minAbstractRepresentative(std::set< storm::expressions::Variable > const &metaVariables) const
Similar to minAbstract, but does not abstract from the variables but rather picks a valuation of each...
Definition Add.cpp:192
Add< LibraryType, ValueType > minAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Min-abstracts from the given meta variables.
Definition Add.cpp:185
Add< LibraryType, ValueType > multiplyMatrix(Add< LibraryType, ValueType > const &otherMatrix, std::set< storm::expressions::Variable > const &summationMetaVariables) const
Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given me...
Definition Add.cpp:372
bool equalModuloPrecision(Add< LibraryType, ValueType > const &other, ValueType const &precision, bool relative=true) const
Checks whether the current and the given ADD represent the same function modulo some given precision.
Definition Add.cpp:211
Bdd< LibraryType > maxAbstractRepresentative(std::set< storm::expressions::Variable > const &metaVariables) const
Similar to maxAbstract, but does not abstract from the variables but rather picks a valuation of each...
Definition Add.cpp:205
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
Definition Dd.cpp:39
virtual std::unique_ptr< storm::solver::SymbolicGameSolver< Type, ValueType > > create(storm::dd::Add< Type, ValueType > const &A, storm::dd::Bdd< Type > const &allRows, storm::dd::Bdd< Type > const &illegalPlayer1Mask, storm::dd::Bdd< Type > const &illegalPlayer2Mask, 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) const
An interface that represents an abstract symbolic game solver.
storm::dd::Bdd< Type > const & getPlayer1Strategy() const
SymbolicGameSolver(storm::dd::Add< Type, ValueType > const &A, storm::dd::Bdd< Type > const &allRows, storm::dd::Bdd< Type > const &illegalPlayer1Mask, storm::dd::Bdd< Type > const &illegalPlayer2Mask, 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.
virtual storm::dd::Add< Type, ValueType > solveGame(Environment const &env, OptimizationDirection player1Goal, OptimizationDirection player2Goal, storm::dd::Add< Type, ValueType > const &x, storm::dd::Add< Type, ValueType > const &b, boost::optional< storm::dd::Bdd< Type > > const &basePlayer1Strategy=boost::none, boost::optional< storm::dd::Bdd< Type > > const &basePlayer2Strategy=boost::none)
Solves the equation system defined by the game matrix.
storm::dd::Bdd< Type > const & getPlayer2Strategy() const
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
LabParser.cpp.
Definition cli.cpp:18