C++中求解二次规划问题(OSQP)的一个使用实例

C++中求解二次规划问题(OSQP)的一个使用实例

参考

库的安装(eigen/OSQP/OSQP-eigen)及其他实例可以参考这个链接
https://blog.csdn.net/nudt_zrs/article/details/124258999?spm=1001.2014.3001.5501

实例

以下面的一个优化问题求解为例
m i n ( x 1 − 1 ) 2 + ( x 2 − 1 ) 2 s . t . 0 ≤ x 1 ≤ 1.5 0 ≤ x 2 ≤ 1.5 \begin{equation} \begin{split} &min \hspace{0.5cm}(x_1 - 1)^2 + (x_2 -1)^2 \\ &s.t.\hspace{1cm} 0 \leq x_1 \leq 1.5 \\ &\hspace{1.5cm} 0 \leq x_2 \leq 1.5 \end{split} \end{equation} min(x11)2+(x21)2s.t.0x11.50x21.5

首先对目标方程进行简化,写成矩阵的形式:
o b j = ( x 1 2 − 2 x 1 + 1 ) + ( x 2 2 − 2 x 2 + 1 ) = x 1 2 + x 2 2 − 2 x 1 − 2 x 2 + 2 = [ x 1 x 2 ] [ 1 0 0 1 ] [ x 1 x 2 ] − 2 [ 1 1 ] [ x 1 x 2 ] + 2 \begin{equation} \begin{split} obj &= (x_1^2 - 2x_1 + 1) + (x_2^2-2x_2+1) \\ &= x_1^2 + x_2^2 -2x_1 - 2x_2 + 2 \\ &= \begin{bmatrix} x_1 & x_2 \end{bmatrix} \begin{bmatrix} 1 & 0 \\0 & 1 \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix}- 2\begin{bmatrix} 1 & 1 \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix}+ 2 \end{split} \end{equation} obj=(x122x1+1)+(x222x2+1)=x12+x222x12x2+2=[x1x2][1001][x1x2]2[11][x1x2]+2

由于二次规划问题求解器默认的求解形式为 o b j = 1 2 x T H x + f T x obj=\displaystyle \frac 12x^THx + f^Tx obj=21xTHx+fTx,其中常数项对二次型求解没有影响,可以直接忽略。因此将上式写为
o b j = 1 2 x T [ 2 0 0 2 ] x + [ − 2 − 2 ] T x = 1 2 x T H x + f T x \begin{equation} \begin{split} obj &= \frac 12\pmb x^T \begin{bmatrix} 2 & 0 \\0 & 2 \end{bmatrix} \pmb x + \begin{bmatrix} -2 \\ -2 \end{bmatrix}^T \pmb x \\ &= \frac 12 x^THx + f^Tx \end{split} \end{equation} obj=21xT[2002]x+[22]Tx=21xTHx+fTx

而其不等式约束则可改写为如下形式
[ 0 0 ] ≤ [ 1 0 0 1 ] [ x 1 x 2 ] ≤ [ 1.5 1.5 ] ⇒ l b ≤ A x ≤ u b \begin{equation} \begin{split} \begin{bmatrix} 0 \\ 0 \end{bmatrix} \leq &\begin{bmatrix} 1 & 0 \\ 0 &1 \end{bmatrix}\begin{bmatrix} x_1 \\ x_2 \end{bmatrix} \leq \begin{bmatrix} 1.5 \\ 1.5 \end{bmatrix} \\ \Rightarrow &lb \leq A x \leq ub \end{split} \end{equation} [00][1001][x1x2][1.51.5]lbAxub

// osqp-eigen
#include "OsqpEigen/OsqpEigen.h"
 
// eigen
#include <Eigen/Dense>
#include <iostream>
 
int main()
{
    // allocate QP problem matrices and vectores
    Eigen::SparseMatrix<double> hessian(2, 2);      //P: n*n正定矩阵,必须为稀疏矩阵SparseMatrix
    Eigen::VectorXd gradient(2);                    //Q: n*1向量
    Eigen::SparseMatrix<double> linearMatrix(2, 2); //A: m*n矩阵,必须为稀疏矩阵SparseMatrix
    Eigen::VectorXd lowerBound(2);                  //L: m*1下限向量
    Eigen::VectorXd upperBound(2);                  //U: m*1上限向量
 
    hessian.insert(0, 0) = 2.0; //注意稀疏矩阵的初始化方式,无法使用<<初始化
    hessian.insert(1, 1) = 2.0;
    // std::cout << "hessian:" << std::endl
    //           << hessian << std::endl;
    gradient << -2, -2;
    linearMatrix.insert(0, 0) = 1.0; //注意稀疏矩阵的初始化方式,无法使用<<初始化
    linearMatrix.insert(1, 1) = 1.0;
    // std::cout << "linearMatrix:" << std::endl
    //           << linearMatrix << std::endl;
    lowerBound << 1, 1;
    upperBound << 1.5, 1.5;
 
    // instantiate the solver
    OsqpEigen::Solver solver;
 
    // settings
    solver.settings()->setVerbosity(false);
    solver.settings()->setWarmStart(true);
 
    // set the initial data of the QP solver
    solver.data()->setNumberOfVariables(2);   //变量数n
    solver.data()->setNumberOfConstraints(2); //约束数m
    if (!solver.data()->setHessianMatrix(hessian))
        return 1;
    if (!solver.data()->setGradient(gradient))
        return 1;
    if (!solver.data()->setLinearConstraintsMatrix(linearMatrix))
        return 1;
    if (!solver.data()->setLowerBound(lowerBound))
        return 1;
    if (!solver.data()->setUpperBound(upperBound))
        return 1;
 
    // instantiate the solver
    if (!solver.initSolver())
        return 1;
 
    Eigen::VectorXd QPSolution;
 
    // solve the QP problem
    if (!solver.solve())
    {
        return 1;
    }
 
    QPSolution = solver.getSolution();
    std::cout << "QPSolution" << std::endl
              << QPSolution << std::endl; //输出为m*1的向量
    return 0;
}

Cmakelist文件如下

cmake_minimum_required(VERSION 3.1)
 
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
project(OSQP_test LANGUAGES CXX)
 
find_package(OsqpEigen)
find_package(Eigen3)
 
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
 
#MPCExample
add_executable(OSQP_test main.cpp)
 
target_link_libraries(OSQP_test OsqpEigen::OsqpEigen)
如果您想在C++使用osqp库来解决二次规划问题,可以按照以下步骤进行操作: 1.安装osqp库并在C++代码包含osqp头文件: ```cpp #include "osqp.h" ``` 2.创建二次规划问题的数据。例如,考虑以下二次规划问题: ``` minimize 0.5*x'P*x + q'x subject to l <= Ax <= u ``` 其,P是一个对称正定矩阵,q是一个向量,A是一个矩阵,l和u是向量。 可以使用Eigen库来定义这些矩阵和向量: ```cpp #include <Eigen/Core> Eigen::MatrixXd P(2, 2); Eigen::VectorXd q(2); Eigen::MatrixXd A(3, 2); Eigen::VectorXd l(3); Eigen::VectorXd u(3); P << 4.0, 1.0, 1.0, 2.0; q << 1.0, 1.0; A << 1.0, 1.0, 1.0, 0.0, 0.0, 1.0; l << 1.0, 0.0, 0.0; u << 1.0, 0.7, 0.7; ``` 3.创建osqp的模型,并设置模型的参数: ```cpp // 创建模型 OSQPWorkspace *work; OSQPSettings *settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings)); OSQPData *data = (OSQPData *)c_malloc(sizeof(OSQPData)); osqp_set_default_settings(settings); // 设置模型的参数 data->n = 2; data->m = 3; data->P = csc_matrix(data->n, data->n, 4, P.data(), nullptr, nullptr); data->q = q.data(); data->A = csc_matrix(data->m, data->n, 6, A.data(), nullptr, nullptr); data->l = l.data(); data->u = u.data(); osqp_setup(&work, data, settings); ``` 在这里,我们使用osqp_set_default_settings()函数来设置模型的默认参数。然后,我们使用csc_matrix()函数将矩阵和向量转换为CSC格式(压缩列格式),并将它们分配给data结构体的相应属性。最后,我们使用osqp_setup()函数创建模型。 4.解决问题并输出结果: ```cpp osqp_solve(work); Eigen::VectorXd x(2); for (int i = 0; i < data->n; ++i) { x(i) = work->solution->x[i]; } std::cout << "Solution: " << x.transpose() << std::endl; ``` 在这里,我们使用osqp_solve()函数来解决问题,并使用work->solution->x来获取解决方案的向量。最后,我们输出解决方案的结果。 需要注意的是,在实际使用,您需要考虑更多的问题,例如如何定义约束条件和目标函数,如何设置模型的参数等。同时,需要在程序结束时释放模型和数据的内存空间,以避免内存泄漏问题
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值