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所致吧。

        還有,兩種約束的表示方法也會對求解產生影響,雖然它們表達的意思是一樣的;當然,兩種約束表示方法得到的結果是相同的。

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