#ifndef STORM_SOLVER_SYMBOLICMINMAXLINEAREQUATIONSOLVER_H_ #define STORM_SOLVER_SYMBOLICMINMAXLINEAREQUATIONSOLVER_H_ #include #include #include #include #include "storm/solver/SymbolicEquationSolver.h" #include "storm/solver/OptimizationDirection.h" #include "storm/solver/SymbolicLinearEquationSolver.h" #include "storm/solver/MinMaxLinearEquationSolverRequirements.h" #include "storm/solver/SolverStatus.h" #include "storm/utility/NumberTraits.h" #include "storm/storage/expressions/Variable.h" #include "storm/storage/dd/DdType.h" #include "SolverSelectionOptions.h" namespace storm { class Environment; namespace dd { template class Add; template class Bdd; } namespace solver { /*! * An interface that represents an abstract symbolic linear equation solver. In addition to solving a system of * linear equations, the functionality to repeatedly multiply a matrix with a given vector is provided. */ template class SymbolicMinMaxLinearEquationSolver : public SymbolicEquationSolver { public: SymbolicMinMaxLinearEquationSolver(); virtual ~SymbolicMinMaxLinearEquationSolver() = default; /*! * Constructs a symbolic min/max linear equation solver with the given meta variable sets and pairs. * * @param A The matrix defining the coefficients of the linear equation system. * @param diagonal An ADD characterizing the elements on the diagonal of the matrix. * @param allRows A BDD characterizing all rows of the equation system. * @param illegalMask A mask that characterizes all illegal choices (that are therefore not to be taken). * @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 choiceVariables The variables encoding the choices of each row group. * @param rowColumnMetaVariablePairs The pairs of row meta variables and the corresponding column meta * variables. * @param settings The settings to use. */ SymbolicMinMaxLinearEquationSolver(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs, std::unique_ptr>&& linearEquationSolverFactory); /*! * Solves the equation system A*x = b. The matrix A is required to be square and have a unique solution. * The solution of the set of linear equations will be written to the vector x. Note that the matrix A has * to be given upon construction time of the solver object. * * @param dir Determines the direction of the optimization. * @param x The initual guess for the solution vector. Its length must be equal to the number of row * groups of A. * @param b The right-hand side of the equation system. Its length must be equal to the number of row groups * of A. * @return The solution of the equation system. */ virtual storm::dd::Add solveEquations(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; /*! * Performs repeated matrix-vector multiplication, using x[0] = x and x[i + 1] = A*x[i] + b. After * performing the necessary multiplications, the result is written to the input vector x. Note that the * matrix A has to be given upon construction time of the solver object. * * @param dir Determines the direction of the optimization. * @param x The initial vector with which to perform matrix-vector multiplication. Its length must be equal * to the number of row groups of A. * @param b If non-null, this vector is added after each multiplication. If given, its length must be equal * to the number of row groups of A. * @return The solution of the equation system. */ virtual storm::dd::Add multiply(storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const* b = nullptr, uint_fast64_t n = 1) const; /*! * Sets an initial scheduler that is required by some solvers (see requirements). */ void setInitialScheduler(storm::dd::Bdd const& scheduler); /*! * Retrieves the initial scheduler (if there is any). */ storm::dd::Bdd const& getInitialScheduler() const; /*! * Retrieves whether an initial scheduler was set. */ bool hasInitialScheduler() const; /*! * Retrieves the requirements of the solver. */ virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const& env, boost::optional const& direction = boost::none) const; /*! * Sets whether the solution to the min max equation system is known to be unique. */ void setHasUniqueSolution(bool value = true); /*! * Retrieves whether the solution to the min max equation system is assumed to be unique */ bool hasUniqueSolution() const; /*! * Notifies the solver that the requirements for solving equations have been checked. If this has not been * done before solving equations, the solver might issue a warning, perform the checks itself or even fail. */ void setRequirementsChecked(bool value = true); /*! * Retrieves whether the solver is aware that the requirements were checked. */ bool isRequirementsCheckedSet() const; /*! * Determines whether the given vector x satisfies x = min/max Ax + b. */ bool isSolution(OptimizationDirection dir, storm::dd::Add const& x, storm::dd::Add const& b) const; private: MinMaxMethod getMethod(Environment const& env, bool isExactMode) const; storm::dd::Add solveEquationsWithScheduler(Environment const& env, storm::dd::Bdd const& scheduler, storm::dd::Add const& x, storm::dd::Add const& b) const; storm::dd::Add solveEquationsWithScheduler(Environment const& env, SymbolicLinearEquationSolver& solver, storm::dd::Bdd const& scheduler, storm::dd::Add const& x, storm::dd::Add const& b, storm::dd::Add const& diagonal) const; storm::dd::Add solveEquationsValueIteration(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; storm::dd::Add solveEquationsPolicyIteration(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; storm::dd::Add solveEquationsRationalSearch(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; template static storm::dd::Add sharpen(OptimizationDirection dir, uint64_t precision, SymbolicMinMaxLinearEquationSolver const& rationalSolver, storm::dd::Add const& x, storm::dd::Add const& rationalB, bool& isSolution); template storm::dd::Add solveEquationsRationalSearchHelper(Environment const& env, OptimizationDirection dir, SymbolicMinMaxLinearEquationSolver const& rationalSolver, SymbolicMinMaxLinearEquationSolver const& impreciseSolver, storm::dd::Add const& rationalB, storm::dd::Add const& x, storm::dd::Add const& b) const; template typename std::enable_if::value && storm::NumberTraits::IsExact, storm::dd::Add>::type solveEquationsRationalSearchHelper(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; template typename std::enable_if::value && !storm::NumberTraits::IsExact, storm::dd::Add>::type solveEquationsRationalSearchHelper(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; template typename std::enable_if::value, storm::dd::Add>::type solveEquationsRationalSearchHelper(Environment const& env, storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b) const; template friend class SymbolicMinMaxLinearEquationSolver; struct ValueIterationResult { ValueIterationResult(SolverStatus status, uint64_t iterations, storm::dd::Add const& values) : status(status), iterations(iterations), values(values) { // Intentionally left empty. } SolverStatus status; uint64_t iterations; storm::dd::Add values; }; ValueIterationResult performValueIteration(storm::solver::OptimizationDirection const& dir, storm::dd::Add const& x, storm::dd::Add const& b, ValueType const& precision, bool relativeTerminationCriterion, uint64_t maximalIterations) const; protected: // The matrix defining the coefficients of the linear equation system. storm::dd::Add A; // A BDD characterizing the illegal choices. storm::dd::Bdd illegalMask; // An ADD characterizing the illegal choices. storm::dd::Add illegalMaskAdd; // The row variables. std::set rowMetaVariables; // The column variables. std::set columnMetaVariables; // The choice variables. std::set choiceVariables; // The pairs of meta variables used for renaming. std::vector> rowColumnMetaVariablePairs; // A factory for creating linear equation solvers when needed. std::unique_ptr> linearEquationSolverFactory; // Whether the solver can assume that the min-max equation system has a unique solution bool uniqueSolution; // A flag indicating whether the requirements were checked. bool requirementsChecked; // A scheduler that specifies with which schedulers to start. boost::optional> initialScheduler; private: /*! * Forwards the known bounds of this solver to the given linear equation solver. */ void forwardBounds(storm::solver::SymbolicLinearEquationSolver& solver) const; }; template class SymbolicMinMaxLinearEquationSolverFactory { public: virtual ~SymbolicMinMaxLinearEquationSolverFactory() = default; virtual std::unique_ptr> create(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs) const = 0; /*! * Retrieves the requirements of the solver that would be created when calling create() right now. The * requirements are guaranteed to be ordered according to their appearance in the SolverRequirement type. */ MinMaxLinearEquationSolverRequirements getRequirements(Environment const& env, bool hasUniqueSolution = false, boost::optional const& direction = boost::none) const; private: virtual std::unique_ptr> create() const = 0; }; template class GeneralSymbolicMinMaxLinearEquationSolverFactory : public SymbolicMinMaxLinearEquationSolverFactory { public: virtual std::unique_ptr> create(storm::dd::Add const& A, storm::dd::Bdd const& allRows, storm::dd::Bdd const& illegalMask, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& choiceVariables, std::vector> const& rowColumnMetaVariablePairs) const override; private: virtual std::unique_ptr> create() const override; }; } // namespace solver } // namespace storm #endif /* STORM_SOLVER_SYMBOLICMINMAXLINEAREQUATIONSOLVER_H_ */