OSQP出现 “P is not upper triangular“的solution

8 篇文章 0 订阅

error

在这里插入图片描述

why:

minimize        0.5 x' P x + q' x
subject to      l <= A x <= u

由于新的版本考虑了P矩阵中要是对称的一个矩阵,然后为了减少一个空间的使用情况,所以是只存储上三角部分。

solution:

1.更换0.5.0版本的osqp.
2.不想更换版本的话,可以使用以下方式:

csc_to_triu((csc_matrix(data->n, data->n, P_nnz, P_x, P_i, P_p)); //csc_to_triu可以将csc的矩阵转换为上三角矩阵

补充知识点

csc_matrix

另外,记录一下csc_matrix的一个构造方式,参考的以下博客:
https://blog.csdn.net/qq_41959288/article/details/118519021
主要的思想可以用里面的一张图概括
在这里插入图片描述

Eigen_Matrix To csc_Matrix函数

一般我都是写好eigen矩阵,所以为了方便使用,将eigen矩阵转化为csc矩阵所需要的参数写成一个函数,好方便调用

  // 函数外先定义好OSQP parameters
  MatrixXd denseMatrix;
  SparseMatrix<double> sparseMatrix;
  double* values;
  int* rows;
  int* cols;
  c_float *matrix_x;
  c_int *matrix_i;
  c_int *matrix_p;
  c_int matrix_nnz, matrix_col;
void eigen2csc(MatrixXd maxtrix_demo){
	// 函数将计算eigen_maxtrix转换为csc_matrix所需要的参数
	// 1.先将eigen_matrix转为稠密矩阵
   denseMatrix = maxtrix_demo;
   // 2.再进一步转为稀疏矩阵
   sparseMatrix = denseMatrix.sparseView();
    sparseMatrix.makeCompressed();
    // 3.保存矩阵的非0值以及行列位置
    values = sparseMatrix.valuePtr();
    rows = sparseMatrix.innerIndexPtr();
    cols = sparseMatrix.outerIndexPtr();
    // 4.计算矩阵列数
     matrix_col = sparseMatrix.outerSize();
	// 5.初始化csc_matrix的相关变量
    matrix_nnz = sparseMatrix.nonZeros();
    matrix_x = new c_float[matrix_nnz];
    matrix_i = new c_int[matrix_nnz];
    matrix_p = new c_int[matrix_col + 1];

    // std::cout << matrix_col << std::endl;
	// 6.将稀疏矩阵的values赋值给csc_matrix相关变量
    for (int i = 0; i < matrix_nnz; i++) {
	      matrix_x[i] = *(values + i);
	      matrix_i[i] = *(rows + i);
      // std::cout << matrix_x[i] << std::endl;
      // std::cout << matrix_i[i] << std::endl;
    }
    for (int i = 0; i <= matrix_col; i++) {
	      matrix_p[i] = *(cols + i);
	      // std::cout << matrix_p[i] << std::endl;
    }
    }
int main(int argc, char **argv) {
// 主函数中调用eigen2csc
......
    eigen2csc( p);
    data->P = csc_to_triu(csc_matrix(data->n, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p));  //osqp >0.5.0
     // data->P = csc_matrix(data->n, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p));  //osqp <= 0.5.0
    eigen2csc(A);
    data->A = csc_matrix(data->m, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p);
......
}

为了方便大家更好的理解,直接通过osqp的一个demo:osqp.c来举例,完整的代码如下


```cpp
#include "osqp.h"
#include "Eigen/Core"
#include "Eigen/Dense"
#include "Eigen/SVD"
#include "Eigen/Sparse"
#include <iostream>

using namespace std;

using namespace Eigen;

// OSQP parameters
MatrixXd denseMatrix;
SparseMatrix<double> sparseMatrix;
double *values;
int *rows;
int *cols;
c_float *matrix_x;
c_int *matrix_i;
c_int *matrix_p;
c_int matrix_nnz, matrix_col;
OSQPWorkspace *work;    // Workspace
OSQPSettings *settings; // Settings
OSQPData *data;         // OSQPData
OSQPInfo *info;

void eigen2csc(MatrixXd maxtrix_demo){
	// 函数将计算eigen_maxtrix转换为csc_matrix所需要的参数
	// 1.先将eigen_matrix转为稠密矩阵
   denseMatrix = maxtrix_demo;
   // 2.再进一步转为稀疏矩阵
   sparseMatrix = denseMatrix.sparseView();
    sparseMatrix.makeCompressed();
    // 3.保存矩阵的非0值以及行列位置
    values = sparseMatrix.valuePtr();
    rows = sparseMatrix.innerIndexPtr();
    cols = sparseMatrix.outerIndexPtr();
    // 4.计算矩阵列数
     matrix_col = sparseMatrix.outerSize();
	// 5.初始化csc_matrix的相关变量
    matrix_nnz = sparseMatrix.nonZeros();
    matrix_x = new c_float[matrix_nnz];
    matrix_i = new c_int[matrix_nnz];
    matrix_p = new c_int[matrix_col + 1];

    // std::cout << matrix_col << std::endl;
	// 6.将稀疏矩阵的values赋值给csc_matrix相关变量
    for (int i = 0; i < matrix_nnz; i++) {
	      matrix_x[i] = *(values + i);
	      matrix_i[i] = *(rows + i);
      // std::cout << matrix_x[i] << std::endl;
      // std::cout << matrix_i[i] << std::endl;
    }
    for (int i = 0; i <= matrix_col; i++) {
	      matrix_p[i] = *(cols + i);
	      // std::cout << matrix_p[i] << std::endl;
    }
    }

int main(int argc, char **argv) {
  // Load problem data
  Matrix2d p;
  MatrixXd A(3, 2);
  p << 4.0, 1.0, 1.0, 2.0;
  A << 1, 1, 1, 0, 0, 1;
  c_int n = 2;
  c_int m = 3;
  VectorXd vecQ(n), vecL(m), vecU(m);
  vecQ << 1.0, 1.0;
  vecL << 1.0, 0.0, 0.0;
  vecU << 1.0, 0.7, 0.7;
  c_float q[2]; //  = { 1.0, 1.0, };
   // c_float P_x[3] = { 4.0, 1.0, 2.0, };
  // c_int   P_nnz  = 3;
  // c_int   P_i[3] = { 0, 0, 1, };
  // c_int   P_p[3] = { 0, 1, 3, };
  // c_float A_x[4] = { 1.0, 1.0, 1.0, 1.0, };
  // c_int   A_nnz  = 4;
  // c_int   A_i[4] = { 0, 1, 0, 2, };
  // c_int   A_p[3] = { 0, 2, 4, };
  c_float l[3]; //   = { 1.0, 0.0, 0.0, };
  c_float u[3]; //   = { 1.0, 0.7, 0.7, };
  for (int i = 0; i < n; i++) {
    q[i] = vecQ(i);
  }
  for (int i = 0; i < m; i++) {
    l[i] = vecL(i);
    u[i] = vecU(i);
  }

  // Exitflag
  c_int exitflag = 0;

  // Workspace structures
  // OSQPWorkspace *work;
  settings = (OSQPSettings *)c_malloc(sizeof(OSQPSettings));
  data = (OSQPData *)c_malloc(sizeof(OSQPData));

  // Populate data
  if (data) {
    data->n = n;
    data->m = m;
    eigen2csc(p);
    data->P = csc_to_triu(csc_matrix(data->n, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p));  //osqp >0.5.0
     // data->P = csc_matrix(data->n, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p));  //osqp <= 0.5.0
    data->q = q;
    eigen2csc(A);
    data->A =
        csc_matrix(data->m, data->n, matrix_nnz, matrix_x, matrix_i, matrix_p);
    data->l = l;
    data->u = u;
  }

  // Define solver settings as default
  if (settings)
    osqp_set_default_settings(settings);

  // Setup workspace
exitflag = osqp_setup(&work, data, settings);  //osqp >0.5.0
  //  work = osqp_setup(data, settings); //osqp <= 0.5.0

  // Solve Problem
  osqp_solve(work);

  // Clean workspace
  osqp_cleanup(work);
  if (data) {
    if (data->A)
      c_free(data->A);
    if (data->P)
      c_free(data->P);
    c_free(data);
  }
  if (settings)
    c_free(settings);

  return exitflag;
}

运行结果如下:
在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值