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.youkuaiyun.com/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;
}
运行结果如下: