#pragma once #include "storm/solver/LinearEquationSolver.h" #include "storm/solver/GameSolver.h" namespace storm { namespace solver { template class StandardGameSolverSettings { public: StandardGameSolverSettings(); enum class SolutionMethod { ValueIteration, PolicyIteration }; void setSolutionMethod(SolutionMethod const& solutionMethod); void setMaximalNumberOfIterations(uint64_t maximalNumberOfIterations); void setRelativeTerminationCriterion(bool value); void setPrecision(ValueType precision); SolutionMethod const& getSolutionMethod() const; uint64_t getMaximalNumberOfIterations() const; ValueType getPrecision() const; bool getRelativeTerminationCriterion() const; private: SolutionMethod solutionMethod; uint64_t maximalNumberOfIterations; ValueType precision; bool relative; }; template class StandardGameSolver : public GameSolver { public: StandardGameSolver(storm::storage::SparseMatrix const& player1Matrix, storm::storage::SparseMatrix const& player2Matrix, std::unique_ptr>&& linearEquationSolverFactory, StandardGameSolverSettings const& settings = StandardGameSolverSettings()); StandardGameSolver(storm::storage::SparseMatrix&& player1Matrix, storm::storage::SparseMatrix&& player2Matrix, std::unique_ptr>&& linearEquationSolverFactory, StandardGameSolverSettings const& settings = StandardGameSolverSettings()); virtual bool solveGame(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector& x, std::vector const& b) const override; virtual void repeatedMultiply(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector& x, std::vector const* b, uint_fast64_t n = 1) const override; StandardGameSolverSettings const& getSettings() const; void setSettings(StandardGameSolverSettings const& newSettings); virtual void clearCache() const override; virtual ValueType getPrecision() const override; virtual bool getRelative() const override; private: bool solveGamePolicyIteration(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector& x, std::vector const& b) const; bool solveGameValueIteration(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector& x, std::vector const& b) const; // Computes p2Matrix * x + b, reduces the result w.r.t. player 2 choices, and then reduces the result w.r.t. player 1 choices. void multiplyAndReduce(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector& x, std::vector const* b, storm::solver::LinearEquationSolver const& linEqSolver, std::vector& multiplyResult, std::vector& p2ReducedMultiplyResult, std::vector& p1ReducedMultiplyResult) const; // Solves the equation system given by the two choice selections void getInducedMatrixVector(std::vector& x, std::vector const& b, std::vector const& player1Choices, std::vector const& player2Choices, storm::storage::SparseMatrix& inducedMatrix, std::vector& inducedVector) const; // Extracts the choices of the different players for the given solution x. // Returns true iff there are "better" choices for one of the players. bool extractChoices(OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector const& x, std::vector const& b, std::vector& player2ChoiceValues, std::vector& player1Choices, std::vector& player2Choices) const; bool valueImproved(OptimizationDirection dir, ValueType const& value1, ValueType const& value2) const; enum class Status { Converged, TerminatedEarly, MaximalIterationsExceeded, InProgress }; // possibly cached data mutable std::unique_ptr> linEqSolverPlayer2Matrix; mutable std::unique_ptr> auxiliaryP2RowVector; // player2Matrix.rowCount() entries mutable std::unique_ptr> auxiliaryP2RowGroupVector; // player2Matrix.rowGroupCount() entries mutable std::unique_ptr> auxiliaryP1RowGroupVector; // player1Matrix.rowGroupCount() entries Status updateStatusIfNotConverged(Status status, std::vector const& x, uint64_t iterations) const; void reportStatus(Status status, uint64_t iterations) const; /// The settings of this solver. StandardGameSolverSettings settings; /// The factory used to obtain linear equation solvers. std::unique_ptr> linearEquationSolverFactory; // If the solver takes posession of the matrix, we store the moved matrix in this member, so it gets deleted // when the solver is destructed. std::unique_ptr> localP1Matrix; std::unique_ptr> localP2Matrix; // A reference to the original sparse matrix given to this solver. If the solver takes posession of the matrix // the reference refers to localA. storm::storage::SparseMatrix const& player1Matrix; storm::storage::SparseMatrix const& player2Matrix; }; } }