8 changed files with 307 additions and 0 deletions
			
			
		- 
					1src/models/ModelType.cpp
- 
					70src/solver/FullySymbolicGameSolver.cpp
- 
					67src/solver/FullySymbolicGameSolver.h
- 
					17src/solver/SymbolicGameSolver.cpp
- 
					70src/solver/SymbolicGameSolver.h
- 
					8src/utility/solver.cpp
- 
					10src/utility/solver.h
- 
					64test/functional/solver/FullySymbolicGameSolverTest.cpp
| @ -0,0 +1,70 @@ | |||
| #include "src/solver/FullySymbolicGameSolver.h"
 | |||
| 
 | |||
| #include "src/storage/dd/CuddBdd.h"
 | |||
| #include "src/storage/dd/CuddAdd.h"
 | |||
| 
 | |||
| namespace storm { | |||
|     namespace solver { | |||
| 
 | |||
|         template<storm::dd::DdType Type> | |||
|         FullySymbolicGameSolver<Type>::FullySymbolicGameSolver(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) : SymbolicGameSolver<Type>(gameMatrix, allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs, player1Variables, player2Variables), precision(precision), maximalNumberOfIterations(maximalNumberOfIterations), relative(relative) { | |||
|             // Intentionally left empty.
 | |||
|         } | |||
|          | |||
|         template<storm::dd::DdType Type> | |||
|         FullySymbolicGameSolver<Type>::FullySymbolicGameSolver(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) : SymbolicGameSolver<Type>(gameMatrix, allRows, rowMetaVariables, columnMetaVariables, rowColumnMetaVariablePairs, player1Variables, 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> | |||
|         storm::dd::Add<Type> FullySymbolicGameSolver<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.
 | |||
|                 // TODO: can this order be reversed?
 | |||
|                 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 FullySymbolicGameSolver<storm::dd::DdType::CUDD>; | |||
|          | |||
|     } | |||
| } | |||
| @ -0,0 +1,67 @@ | |||
| #ifndef STORM_SOLVER_FULLYSYMBOLICGAMESOLVER_H_ | |||
| #define STORM_SOLVER_FULLYSYMBOLICGAMESOLVER_H_ | |||
| 
 | |||
| #include "src/solver/SymbolicGameSolver.h" | |||
| 
 | |||
| namespace storm { | |||
|     namespace solver { | |||
|          | |||
|         /*! | |||
|          * A interface that represents an abstract symbolic game solver. | |||
|          */ | |||
|         template<storm::dd::DdType Type> | |||
|         class FullySymbolicGameSolver : public SymbolicGameSolver<Type> { | |||
|         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. | |||
|              * @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. | |||
|              */ | |||
|             FullySymbolicGameSolver(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. | |||
|              */ | |||
|             FullySymbolicGameSolver(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); | |||
|              | |||
|             virtual storm::dd::Add<Type> solveGame(bool player1Min, bool player2Min, storm::dd::Add<Type> const& x, storm::dd::Add<Type> const& b) const override; | |||
|              | |||
|         private: | |||
|             // 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_FULLYSYMBOLICGAMESOLVER_H_ */ | |||
| @ -0,0 +1,17 @@ | |||
| #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) { | |||
|             // Intentionally left empty.
 | |||
|         } | |||
|       | |||
|         template class SymbolicGameSolver<storm::dd::DdType::CUDD>; | |||
|          | |||
|     } | |||
| } | |||
| @ -0,0 +1,70 @@ | |||
| #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 { | |||
|          | |||
|         /*! | |||
|          * A 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); | |||
|              | |||
|             /*! | |||
|              * 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 = 0; | |||
|          | |||
|         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; | |||
|         }; | |||
|          | |||
|     } // namespace solver | |||
| } // namespace storm | |||
| 
 | |||
| #endif /* STORM_SOLVER_SYMBOLICGAMESOLVER_H_ */ | |||
| @ -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()); | |||
| } | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue