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