#ifndef STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ #define STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ #include #include "storm/solver/LinearEquationSolver.h" #include "storm/solver/NativeMultiplier.h" namespace storm { namespace solver { template class NativeLinearEquationSolverSettings { public: enum class SolutionMethod { Jacobi, GaussSeidel, SOR, WalkerChae, Power, RationalSearch }; NativeLinearEquationSolverSettings(); void setSolutionMethod(SolutionMethod const& method); void setPrecision(ValueType precision); void setMaximalNumberOfIterations(uint64_t maximalNumberOfIterations); void setRelativeTerminationCriterion(bool value); void setOmega(ValueType omega); void setPowerMethodMultiplicationStyle(MultiplicationStyle value); void setForceSoundness(bool value); SolutionMethod getSolutionMethod() const; ValueType getPrecision() const; uint64_t getMaximalNumberOfIterations() const; uint64_t getRelativeTerminationCriterion() const; ValueType getOmega() const; MultiplicationStyle getPowerMethodMultiplicationStyle() const; bool getForceSoundness() const; private: bool forceSoundness; SolutionMethod method; double precision; bool relative; uint_fast64_t maximalNumberOfIterations; ValueType omega; MultiplicationStyle multiplicationStyle; }; /*! * A class that uses storm's native matrix operations to implement the LinearEquationSolver interface. */ template class NativeLinearEquationSolver : public LinearEquationSolver { public: NativeLinearEquationSolver(NativeLinearEquationSolverSettings const& settings = NativeLinearEquationSolverSettings()); NativeLinearEquationSolver(storm::storage::SparseMatrix const& A, NativeLinearEquationSolverSettings const& settings = NativeLinearEquationSolverSettings()); NativeLinearEquationSolver(storm::storage::SparseMatrix&& A, NativeLinearEquationSolverSettings const& settings = NativeLinearEquationSolverSettings()); virtual void setMatrix(storm::storage::SparseMatrix const& A) override; virtual void setMatrix(storm::storage::SparseMatrix&& A) override; virtual void multiply(std::vector& x, std::vector const* b, std::vector& result) const override; virtual void multiplyAndReduce(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const override; virtual bool supportsGaussSeidelMultiplication() const override; virtual void multiplyGaussSeidel(std::vector& x, std::vector const* b) const override; virtual void multiplyAndReduceGaussSeidel(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices = nullptr) const override; void setSettings(NativeLinearEquationSolverSettings const& newSettings); NativeLinearEquationSolverSettings const& getSettings() const; virtual LinearEquationSolverProblemFormat getEquationProblemFormat() const override; virtual LinearEquationSolverRequirements getRequirements() const override; virtual void clearCache() const override; protected: virtual bool internalSolveEquations(std::vector& x, std::vector const& b) const override; private: enum class Status { Converged, TerminatedEarly, MaximalIterationsExceeded, InProgress }; struct PowerIterationResult { PowerIterationResult(uint64_t iterations, Status status) : iterations(iterations), status(status) { // Intentionally left empty. } uint64_t iterations; Status status; }; template friend class NativeLinearEquationSolver; PowerIterationResult performPowerIteration(std::vector*& currentX, std::vector*& newX, std::vector const& b, ValueType const& precision, bool relative, SolverGuarantee const& guarantee, uint64_t currentIterations) const; void logIterations(bool converged, bool terminate, uint64_t iterations) const; virtual uint64_t getMatrixRowCount() const override; virtual uint64_t getMatrixColumnCount() const override; virtual bool solveEquationsSOR(std::vector& x, std::vector const& b, ValueType const& omega) const; virtual bool solveEquationsJacobi(std::vector& x, std::vector const& b) const; virtual bool solveEquationsWalkerChae(std::vector& x, std::vector const& b) const; virtual bool solveEquationsPower(std::vector& x, std::vector const& b) const; virtual bool solveEquationsSoundPower(std::vector& x, std::vector const& b) const; // 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> localA; // A pointer to the original sparse matrix given to this solver. If the solver takes posession of the matrix // the pointer refers to localA. storm::storage::SparseMatrix const* A; // The settings used by the solver. NativeLinearEquationSolverSettings settings; // An object to dispatch all multiplication operations. NativeMultiplier multiplier; // cached auxiliary data mutable std::unique_ptr, std::vector>> jacobiDecomposition; mutable std::unique_ptr> cachedRowVector2; // A.getRowCount() rows struct WalkerChaeData { WalkerChaeData(storm::storage::SparseMatrix const& originalMatrix, std::vector const& originalB); void computeWalkerChaeMatrix(storm::storage::SparseMatrix const& originalMatrix); void computeNewB(std::vector const& originalB); void precomputeAuxiliaryData(); storm::storage::SparseMatrix matrix; std::vector b; ValueType t; // Auxiliary data. std::vector columnSums; std::vector newX; }; mutable std::unique_ptr walkerChaeData; }; template class NativeLinearEquationSolverFactory : public LinearEquationSolverFactory { public: using LinearEquationSolverFactory::create; virtual std::unique_ptr> create() const override; NativeLinearEquationSolverSettings& getSettings(); NativeLinearEquationSolverSettings const& getSettings() const; virtual std::unique_ptr> clone() const override; private: NativeLinearEquationSolverSettings settings; }; } } #endif /* STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ */