MOSEK二次规划函数quadprog错误: ERROR - (quadprog): H is not a square matrix of dimension length(f)

题目:MOSEK二次规划函数quadprog错误: ERROR - (quadprog): H is not a square matrix of dimension length(f)

 

本篇需要如下基础:

(1)使用Matlab二次规划quadprog函数:参见《二次规划问题和MATLAB函数quadprog的使用》,链接:https://blog.csdn.net/jbb0523/article/details/50598641

(2)在Matlab中安装使用Mosek软件:参见《MOSEK优化包的安装、使用及注册:以Matlab中的二次规划为例》,链接:https://blog.csdn.net/jbb0523/article/details/101384191

 

        最近需要求解一个不含一次项的二次规划问题,即min 0.5*x'*H*x, 约束条件为部分变量不小于1,部分变量不大于-1,其余的变量无约束。由于变量x的维度较高,Matlab自带的quadprog函数求解起来比较慢,因此打算调用Mosek求解,但却不能使用。后来发现是个很简单的设置问题,记录在此。

        接下来,为了说明问题,在Matlab中随机生成了一个类似的二次规划问题,变量个数为1000,二次项矩阵H随机生成,约束条件为前25%变量不小于1,后25%变量不大于-1,中间50%变量无约束。约束条件采用了两种实现方式,任选一种即可。

 

(1)使用Matlab自带的quadprog求解:

clear all;close all;clc;
%% create QP problem
%控制随机数生成,保证每次产生的数据集相同
%旧版本Matlab的rand('seed', 0)等价于新版本Matlab的rng(0,'v4')
%旧版本Matlab的rand('state', 0)等价于新版本Matlab的rng(0,'v5uniform')
%本版本程序在MATLAB R2016a编写,同时支持两种写法,但诸如Matlab R2009b仅支持旧版本写法
rand('state', 0);%rng(0,'v5uniform');
rng(0,'v5uniform');
n = 1000;
H = rand(n);
H = H'*H;%Hesse matrix
%constraints: 前25%变量不小于1, 后25%变量不大于-1, 中间50%变量无约束
% (1)inequalities constraints
c = [ones(round(n*0.25),1);zeros(round(n*0.5),1);-ones(round(n*0.25),1)];
A = sparse(diag(c));
A = -A(c~=0,:);
b = -ones(sum(c~=0),1);
% (2)lower/upper bounds
lb = [ones(round(n*0.25),1);-inf*ones(round(n*0.75),1)];
ub = [inf*ones(round(n*0.75),1);-ones(round(n*0.25),1)];
%Matlab built-in quadprog solver
opts = optimoptions('quadprog','Display','off');
tic;clock_s=clock;
x_matlab_inequ = quadprog(H,[],A,b,[],[],[],[],[],opts);
toc;clock_f=clock;time_matlab_inequ=etime(clock_f,clock_s);
%Matlab built-in quadprog solver
opts = optimoptions('quadprog','Display','off');
tic;clock_s=clock;
x_matlab_bound = quadprog(H,[],[],[],[],[],lb,ub,[],opts);
toc;clock_f=clock;time_matlab_bound=etime(clock_f,clock_s);

命令行窗口显示如下:

时间已过 4.587010 秒。

时间已过 4.363230 秒。

 

(2)使用Mosek的quadprog求解:

%Mosek test 
clear all;close all;clc;
%% create QP problem
%控制随机数生成,保证每次产生的数据集相同
%旧版本Matlab的rand('seed', 0)等价于新版本Matlab的rng(0,'v4')
%旧版本Matlab的rand('state', 0)等价于新版本Matlab的rng(0,'v5uniform')
%本版本程序在MATLAB R2016a编写,同时支持两种写法,但诸如Matlab R2009b仅支持旧版本写法
rand('state', 0);%rng(0,'v5uniform');
rng(0,'v5uniform');
n = 1000;
H = rand(n);
H = H'*H;%Hesse matrix
%constraints: 前25%变量不小于1, 后25%变量不大于-1, 中间50%变量无约束
% (1)inequalities constraints
c = [ones(round(n*0.25),1);zeros(round(n*0.5),1);-ones(round(n*0.25),1)];
A = sparse(diag(c));
A = -A(c~=0,:);
b = -ones(sum(c~=0),1);
% (2)lower/upper bounds
lb = [ones(round(n*0.25),1);-inf*ones(round(n*0.75),1)];
ub = [inf*ones(round(n*0.75),1);-ones(round(n*0.25),1)];
%Mosek quadprog solver
mosek_path = 'C:\Program Files\Mosek\8\toolbox\r2014a\';
addpath(mosek_path);
tic;clock_s=clock;
x_mosek_inequ = quadprog(H,[],A,b);
toc;clock_f=clock;time_mosek_inequ=etime(clock_f,clock_s);
rmpath(mosek_path);
%Mosek quadprog solver
mosek_path = 'C:\Program Files\Mosek\8\toolbox\r2014a\';
addpath(mosek_path);
tic;clock_s=clock;
x_mosek_bound = quadprog(H,[],[],[],[],[],lb,ub);
toc;clock_f=clock;time_mosek_bound=etime(clock_f,clock_s);
rmpath(mosek_path);

但命令行窗口会显示如下:

ERROR - (quadprog): H is not a square matrix of dimension length(f)

时间已过 0.071813 秒。

ERROR - (quadprog): H is not a square matrix of dimension length(f)

时间已过 0.023629 秒。

 

说明使用Mosek出错了。

        正如之前所说,Mosek的quadprog函数并不如Matlab自带的quadprog函数稳定,可能是因数Mosek并非直接求解二次规划问题的,而是求解其它等价问题,或许Mosek不能求解不包含一次项的二次规划问题吧……

        琢磨之后忽然明白:由于没有一次项,默认将一次项系数设置为“[]”,但实际上此时的一次项系数应该是0而非没有,因此将一次项系数设置为长为n的零向量zeros(n,1)。Matlab自带的quadprog比Mosek的要鲁棒,因此可以正常运行,但Mosek则兼容性差一些。修改后再使用Mosek进行测试:

%Mosek test 
clear all;close all;clc;
%% create QP problem
%控制随机数生成,保证每次产生的数据集相同
%旧版本Matlab的rand('seed', 0)等价于新版本Matlab的rng(0,'v4')
%旧版本Matlab的rand('state', 0)等价于新版本Matlab的rng(0,'v5uniform')
%本版本程序在MATLAB R2016a编写,同时支持两种写法,但诸如Matlab R2009b仅支持旧版本写法
rand('state', 0);%rng(0,'v5uniform');
rng(0,'v5uniform');
n = 1000;
H = rand(n);
H = H'*H;%Hesse matrix
%constraints: 前25%变量不小于1, 后25%变量不大于-1, 中间50%变量无约束
% (1)inequalities constraints
c = [ones(round(n*0.25),1);zeros(round(n*0.5),1);-ones(round(n*0.25),1)];
A = sparse(diag(c));
A = -A(c~=0,:);
b = -ones(sum(c~=0),1);
% (2)lower/upper bounds
lb = [ones(round(n*0.25),1);-inf*ones(round(n*0.75),1)];
ub = [inf*ones(round(n*0.75),1);-ones(round(n*0.25),1)];
%Mosek quadprog solver
mosek_path = 'C:\Program Files\Mosek\8\toolbox\r2014a\';
addpath(mosek_path);
tic;clock_s=clock;
x_mosek_inequ = quadprog(H,zeros(n,1),A,b);
toc;clock_f=clock;time_mosek_inequ=etime(clock_f,clock_s);
rmpath(mosek_path);
%Mosek quadprog solver
mosek_path = 'C:\Program Files\Mosek\8\toolbox\r2014a\';
addpath(mosek_path);
tic;clock_s=clock;
x_mosek_bound = quadprog(H,zeros(n,1),[],[],[],[],lb,ub);
toc;clock_f=clock;time_mosek_bound=etime(clock_f,clock_s);
rmpath(mosek_path);

此时命令行窗口显示如下:

时间已过 1.266149 秒。

时间已过 1.299889 秒。

 

说明此时Mosek可以求解该二次规划问题。

        其实错误信息“ERROR - (quadprog): H is not a square matrix of dimension length(f)”说得很清楚,H不是一个与f的维度相同的方阵;而在Matlab中,求解的二次规划问题是min 0.5*x'*H*x + f'*x,习惯使用H表示二次项的Hesse矩阵,使用f表示一次项的系数向量,所以该错误信息就表明二次项的矩阵和一次项的向量维度不匹配。

        另外,从求解这个问题中也可以看出,Mosek的效率要比Matlab自带的quadprog高,而且此时n=1000,如果将n改为10000,则求解的时间相差就非常悬殊了。但很奇怪的是,具体到我个人的问题上(规模大概在10000左右),二者却相差不大,可能是我的问题中特殊的H所致吧。

        还有,两种约束的表示方法也会对求解产生影响,虽然它们表达的意思是一样的;当然,两种约束表示方法得到的结果是相同的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章