/** * @file Solver.hpp * @author Giulio Romualdi * @copyright Released under the terms of the BSD 3-Clause License * @date 2018 */ #ifndef OSQPEIGEN_SOLVER_HPP #define OSQPEIGEN_SOLVER_HPP // Std #include // Eigen #include // OSQP #include // OsqpEigen #include #include #include #include /** * OsqpEigen namespace. */ namespace OsqpEigen { /** * Solver class is a wrapper of the OSQP OSQPWorkspace struct. */ class Solver { bool m_isSolverInitialized; /**< Boolean true if solver is initialized. */ #ifdef OSQP_EIGEN_OSQP_IS_V1 std::unique_ptr> m_solver; /**< Pointer to OSQPSolver struct. */ #else std::unique_ptr> m_workspace; /**< Pointer to OSQPWorkspace struct. */ #endif std::unique_ptr m_settings; /**< Pointer to Settings class. */ std::unique_ptr m_data; /**< Pointer to Data class. */ Eigen::Matrix m_primalVariables; Eigen::Matrix m_dualVariables; Eigen::Matrix m_solution; Eigen::Matrix m_dualSolution; std::vector m_hessianNewIndices; std::vector m_hessianNewValues; std::vector m_constraintsNewIndices; std::vector m_constraintsNewValues; std::vector> m_oldHessianTriplet, m_newHessianTriplet, m_newUpperTriangularHessianTriplets; std::vector> m_oldLinearConstraintsTriplet, m_newLinearConstraintsTriplet; /** * Evaluate the position and the values of the new elements of a sparse matrix. * @param oldMatrixTriplet vector containing the triplets of the old sparse matrix; * @param newMatrixTriplet vector containing the triplets of the mew sparse matrix; * @param newIndices vector of the index mapping new elements * to position in the sparse matrix; * @param newValues vector of new elements in the sparse matrix. * @return true if the sparsity pattern is not changed false otherwise. */ template bool evaluateNewValues(const std::vector>& oldMatrixTriplet, const std::vector>& newMatrixTriplet, std::vector& newIndices, std::vector& newValues) const; /** * Takes only the triplets which belongs to the upper triangular part of the matrix. * @param fullMatrixTriplets vector containing the triplets of the sparse matrix; * @param upperTriangularMatrixTriplets vector containing the triplets of the mew sparse matrix; */ template void selectUpperTriangularTriplets( const std::vector>& fullMatrixTriplets, std::vector>& upperTriangularMatrixTriplets) const; #ifdef OSQP_EIGEN_OSQP_IS_V1 /** * Custom Deleter for the OSQPSolver. It is required to free the @ref m_workspace unique_ptr * @param ptr raw pointer to the workspace */ static void OSQPSolverDeleter(OSQPSolver* ptr) noexcept; #else /** * Custom Deleter for the OSQPWorkspace. It is required to free the @ref m_workspace unique_ptr * @param ptr raw pointer to the workspace */ static void OSQPWorkspaceDeleter(OSQPWorkspace* ptr) noexcept; #endif inline const OSQPData* getData() const noexcept { #ifdef OSQP_EIGEN_OSQP_IS_V1 return m_data->getData(); #else return m_workspace->data; #endif } inline const OSQPInfo* getInfo() const noexcept { #ifdef OSQP_EIGEN_OSQP_IS_V1 return m_solver->info; #else return m_workspace->info; #endif } inline const OSQPSolution* getOSQPSolution() const noexcept { #ifdef OSQP_EIGEN_OSQP_IS_V1 return m_solver->solution; #else return m_workspace->solution; #endif } public: /** * Constructor. */ Solver(); /** * Initialize the solver with the actual initial data and settings. * @return true/false in case of success/failure. */ bool initSolver(); /** * Check if the solver is initialized. * @return true if the solver is initialized. */ bool isInitialized(); /** * Deallocate memory. */ void clearSolver(); /** * Set to zero all the solver variables. * @return true/false in case of success/failure. */ bool clearSolverVariables(); /** * Solve the QP optimization problem. * @return true/false in case of success/failure. */ [[deprecated("Use solveProblem() instead.")]] bool solve(); /** * Solve the QP optimization problem. * @return the error exit flag */ OsqpEigen::ErrorExitFlag solveProblem(); /** * Get the status of the solver * @return The inner solver status */ OsqpEigen::Status getStatus() const; /** * Get the primal objective value * @return The primal objective value */ c_float getObjValue() const; /** * Get the optimization problem solution. * @return an Eigen::Vector containing the optimization result. */ const Eigen::Matrix& getSolution(); /** * Get the dual optimization problem solution. * @return an Eigen::Vector containing the optimization result. */ const Eigen::Matrix& getDualSolution(); /** * Update the linear part of the cost function (Gradient). * @param gradient is the Gradient vector. * @note the elements of the gradient are not copied inside the library. * The user has to guarantee that the lifetime of the objects passed is the same of the * OsqpEigen object. * @return true/false in case of success/failure. */ bool updateGradient(const Eigen::Ref>& gradient); /** * Update the lower bounds limit (size m). * @param lowerBound is the lower bound constraint vector. * @note the elements of the lowerBound are not copied inside the library. * The user has to guarantee that the lifetime of the object passed is the same of the * OsqpEigen object. * @return true/false in case of success/failure. */ bool updateLowerBound(const Eigen::Ref>& lowerBound); /** * Update the upper bounds limit (size m). * @param upperBound is the upper bound constraint vector. * @note the elements of the upperBound are not copied inside the library. * The user has to guarantee that the lifetime of the object passed is the same of the * OsqpEigen object. * @return true/false in case of success/failure. */ bool updateUpperBound(const Eigen::Ref>& upperBound); /** * Update both upper and lower bounds (size m). * @param lowerBound is the lower bound constraint vector; * @param upperBound is the upper bound constraint vector. * @note the elements of the lowerBound and upperBound are not copied inside the library. * The user has to guarantee that the lifetime of the objects passed is the same of the * OsqpEigen object * @return true/false in case of success/failure. */ bool updateBounds(const Eigen::Ref>& lowerBound, const Eigen::Ref>& upperBound); /** * Update the quadratic part of the cost function (Hessian). * It is assumed to be a symmetric matrix. * \note * If the sparsity pattern is preserved the matrix is simply update * otherwise the entire solver will be reinitialized. In this case * the primal and dual variable are copied in the new workspace. * * @param hessian is the Hessian matrix. * @return true/false in case of success/failure. */ template bool updateHessianMatrix(const Eigen::SparseCompressedBase& hessianMatrix); /** * Update the linear constraints matrix (A) * \note * If the sparsity pattern is preserved the matrix is simply update * otherwise the entire solver will be reinitialized. In this case * the primal and dual variable are copied in the new workspace. * * @param linearConstraintsMatrix is the linear constraint matrix A * @return true/false in case of success/failure. */ template bool updateLinearConstraintsMatrix( const Eigen::SparseCompressedBase& linearConstraintsMatrix); /** * Set the entire * @param linearConstraintsMatrix is the linear constraint matrix A * @return true/false in case of success/failure. */ template bool setWarmStart(const Eigen::Matrix& primalVariable, const Eigen::Matrix& dualVariable); template bool setPrimalVariable(const Eigen::Matrix& primalVariable); template bool setDualVariable(const Eigen::Matrix& dualVariable); template bool getPrimalVariable(Eigen::Matrix& primalVariable); template bool getDualVariable(Eigen::Matrix& dualVariable); /** * Get the solver settings pointer. * @return the pointer to Settings object. */ const std::unique_ptr& settings() const; /** * Get the pointer to the solver initial data. * @return the pointer to Data object. */ const std::unique_ptr& data() const; #ifdef OSQP_EIGEN_OSQP_IS_V1 /** * Get the pointer to the OSQP solver. * @return the pointer to Solver object. */ const std::unique_ptr>& solver() const; #else /** * Get the pointer to the OSQP workspace. * @return the pointer to Workspace object. */ const std::unique_ptr>& workspace() const; #endif }; #include } // namespace OsqpEigen #endif