Browse Source
First version of fully symbolic game solver.
First version of fully symbolic game solver.
Former-commit-id: 34406f25b9
tempestpy_adaptions
dehnert
10 years ago
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