? ? ? ? 博客中所有內(nèi)容均來(lái)源于自己學(xué)習(xí)過(guò)程中積累的經(jīng)驗(yàn)以及對(duì)yalmip官方文檔的翻譯:YALMIP
1.Yalmip工具箱的下載與安裝
1.1下載
????????Yalmip的作者是Johan L?fberg,是由Matlab平臺(tái)編程實(shí)現(xiàn)的一個(gè)免費(fèi)開(kāi)源數(shù)學(xué)優(yōu)化工具箱,在官網(wǎng)上就可以下載。官方下載鏈接如下:
Download - YALMIP
????????下載時(shí)可以選擇最新版本或者舊版本(如果使用的Matlab版本比較舊,有可能與最新版Yalmip工具箱不兼容,這時(shí)候就可以選擇下載舊版本的Yalmip)
圖1 Yalmip工具箱下載
1.2安裝
????????Yamlip工具箱所有功能都是基于m文件實(shí)現(xiàn)的,因此安裝過(guò)程實(shí)際上就是把Yalmip工具箱的路徑添加到Matlab平臺(tái)中,具體安裝方式有以下幾種:
????????1)手動(dòng)添加路徑
????????第一步,將下載的壓縮包解壓,然后把解壓后的文件夾放在Matlab路徑中的toolbox中(也可以隨便放在其他的文件夾中,只要保證該文件夾不會(huì)被刪除,被移動(dòng)即可)。
????????第二步,將Yalmip工具箱添加到Matlab的路徑中。
?圖2?Matlab手動(dòng)添加路徑示意
????????2)使用addpath(genpath(pwd))命令
????????pwd表示當(dāng)前路徑,這個(gè)命令表示將當(dāng)前文件夾下的所有子文件夾都添加到Matlab的路徑中。首先使用時(shí)首先將下載的壓縮包解壓,然后把解壓后的文件夾放在Matlab路徑中的toolbox中(也可以隨便放在其他的文件夾中,只要保證該文件夾不會(huì)被刪除,被移動(dòng)即可)。然后使用addpath(genpath(pwd))命令,并將其中的pwd修改為對(duì)應(yīng)的路徑即可,例如:
addpath(genpath(‘D:\Program Files\MATLAB\R2016b\toolbox\YALMIP-master’))
1.3測(cè)試
????????安裝成功后,可以使用yalmiptest函數(shù)測(cè)試是否安裝成功。使用時(shí)在命令行輸入yalmiptest并回車,Yalmip會(huì)自動(dòng)求解一組優(yōu)化問(wèn)題來(lái)測(cè)試工具箱是否安裝成功(中間有一段需要輸入任意內(nèi)容并回車,才能繼續(xù)測(cè)試):
圖3?Yalmip測(cè)試結(jié)果
????????如果和圖3的求解結(jié)果一樣,除了三個(gè)無(wú)解的問(wèn)題,都顯示”successfully solved”,表示工具箱可以正常使用了。但是,在求解優(yōu)化問(wèn)題時(shí),Yalmip其實(shí)相當(dāng)于“中間商”的地位,只是將各類求解器不同的數(shù)學(xué)建模方式修改為統(tǒng)一的形式,真正求解優(yōu)化問(wèn)題的還是那些求解器。工具箱中已經(jīng)內(nèi)置了一些免費(fèi)的求解器,可以求解簡(jiǎn)單的優(yōu)化問(wèn)題,但針對(duì)復(fù)雜問(wèn)題這些求解器的性能可能不是很好,這時(shí)候就需要功能更強(qiáng)大的商業(yè)求解器了。具有學(xué)術(shù)免費(fèi)版的商業(yè)求解器主要有Gurobi、Cplex、Mosek,它們的下載地址和優(yōu)缺點(diǎn)如表1所示:
表1 常用的學(xué)術(shù)免費(fèi)版商業(yè)求解器
求解器 |
官網(wǎng)地址 |
優(yōu)點(diǎn) |
缺點(diǎn) |
Gurobi |
http://www.gurobi.com |
1.集成了啟發(fā)式算法 2.MILP求解性能排名前列 3.有官方中文網(wǎng)站,學(xué)術(shù)許可證申請(qǐng)容易 4.學(xué)術(shù)版沒(méi)有規(guī)模限制 |
1.學(xué)術(shù)許可證只有一年有效,到期需要重新申請(qǐng) 2.使用人數(shù)較少,遇到問(wèn)題時(shí)通過(guò)檢索不容易找到答案 |
Cplex |
IBM Products |
1.擁有自己的建模環(huán)境?Ilog,也支持Java、C++、C?等語(yǔ)言 2.目前使用人數(shù)最多,通過(guò)檢索較容易找到相關(guān)問(wèn)題的解答 |
免費(fèi)版和學(xué)術(shù)版都有規(guī)模限制,無(wú)法求解大規(guī)模問(wèn)題 |
Mosek |
http://www.mosek.com |
內(nèi)點(diǎn)法性能比較好,解SOCP、SDP等錐優(yōu)化性能最優(yōu)。 |
學(xué)術(shù)許可申請(qǐng)比較麻煩,需要學(xué)校郵箱支持 |
2.Yalmip使用方法介紹
????????使用Yalmip工具箱包括定義變量、定義約束條件、定義目標(biāo)函數(shù)、定義求解器選項(xiàng)、求解優(yōu)化問(wèn)題以及檢查優(yōu)化結(jié)果并獲取優(yōu)化問(wèn)題的解。下面的代碼是Yalmip官方給出的示例,包括了上述所有步驟(PS:下文代碼選擇的求解器為cplex,如果沒(méi)有安裝cplex,只需在定義options時(shí)刪除該求解器的設(shè)置,Yalmip將自動(dòng)選擇其他已安裝的求解器):
% 定義變量
x = sdpvar(10,1);
% 設(shè)置約束條件
Constraints = [sum(x) <= 10, x(1) == 0, 0.5 <= x(2) <= 1.5];
for i = 1 : 7
Constraints = [Constraints, x(i) + x(i+1) <= x(i+2) + x(i+3)];
end
% 定義目標(biāo)函數(shù)
Objective = x'*x + norm(x,1);
% 使用options結(jié)構(gòu)體來(lái)為YALMIP和所需求解器指定優(yōu)化參數(shù)
options = sdpsettings('verbose',1,'solver','cplex');
% 將約束條件、目標(biāo)函數(shù)和選項(xiàng)作為輸入傳遞給優(yōu)化函數(shù),進(jìn)行問(wèn)題求解
sol = optimize(Constraints,Objective,options);
% 獲取最終解或進(jìn)行錯(cuò)誤分析
if sol.problem == 0
% 獲取解的值
disp(‘求解成功’)
solution = value(x);
else
disp('出錯(cuò)了!');
sol.info
yalmiperror(sol.problem)
end
????????下面將對(duì)以上步驟分別進(jìn)行介紹。
2.1定義決策變量
????????工具箱中定義決策變量的命令包括Binvar,blkvar,intvar,sdpvar和semivar,這里僅介紹sdpvar的用法,其余命令和sdpvar的用法相似。
????????sdpvar用于定義連續(xù)型的決策變量,其基本語(yǔ)法如下:
x = sdpvar(n)
x = sdpvar(n,m)
x = sdpvar(n,m,'type')
x = sdpvar(n,m,'type','field')
x = sdpvar(dim1,dim2,dim3,...,dimn,'type','field')
sdpvar x
????????例如定義一個(gè)n行m列決策變量P的方法如下:
P = sdpvar(n,m);
????????需要注意的是,使用sdpvar定義決策變量時(shí),若決策變量為方陣,則默認(rèn)其為對(duì)稱陣(如果使用sdpvar定義了方陣x,則x(i,j) = x(j,i))。
????????例如,定義一個(gè)3行3列決策變量P的語(yǔ)法如下:
P = sdpvar(3,3);
????????這時(shí)候變量P默認(rèn)為一個(gè)對(duì)稱矩陣,也就是P(1,2) = P(2,1),P(1,3) = P(3,1),P(2,3) = P(3,2)。如果需要定義一個(gè)不對(duì)稱的變量P,則需要添加’full’,語(yǔ)法如下:
P = sdpvar(3,3,’full’);
????????定義矩陣時(shí)沒(méi)有添加參數(shù)’full’,導(dǎo)致變量默認(rèn)為方陣,這是初學(xué)Yalmip工具箱最容易犯一個(gè)錯(cuò)誤,需要留意?。。。∥覀兒芏鄷r(shí)候定義變量時(shí),維度都是不確定的,為了避免出錯(cuò),就可以在不需要定義對(duì)稱矩陣時(shí),都添加參數(shù)’full’。
????????另外一點(diǎn)需要說(shuō)明的是,Matlab中對(duì)于標(biāo)量和矩陣的絕大部分函數(shù)都可以用于sdpvar類型變量,記住這一點(diǎn)可以簡(jiǎn)化很多代碼量。
????????例如:
x = sdpvar(1,6);
len_x = length(x)
????????對(duì)于sdpvar類型變量,建模時(shí)其他常用的命令還有diag、eye、end等等,這就需要在使用過(guò)程中慢慢地嘗試。定義決策變量的更多內(nèi)容將在后文進(jìn)行介紹。
2.2定義約束條件
????????Yalmip工具箱中可以非常方便的定義約束條件,針對(duì)決策變量使用約束條件定義函數(shù)或約束條件定義運(yùn)算符即可表示一個(gè)約束條件。最常用的約束條件定義運(yùn)算符包括’>=’、’<=’、’==’,分別表示大于等于、小于等于和等于。
????????例如,假設(shè)二維決策變量x的約束條件包括:
????????上面的式子實(shí)際上包含三個(gè)約束條件,可以分別寫成:
x = sdpvar(1,2);
C1 = [x(1) >= 1];
C2 = [x(1) <= 2];
C3 = [x(2) == 3];
????????將每個(gè)約束條件通過(guò)矩陣拼接或者使用’+’相加的方式連接在一起,便可以組合多個(gè)約束條件。
C = [C1 , C2 , C3];
????????或者
C_dot = C1 + C2 + C3;
????????兩種表達(dá)方式是完全等價(jià)的。上面的例子中,變量x1的約束是一個(gè)連續(xù)不等式,也可以同時(shí)進(jìn)行定義,方式如下:
C4 = [1 <= x(1) <= 2];
????????需要注意的是,Yalmip中不支持嚴(yán)格的不等式約束(也就是不含等號(hào)的不等式),如果使用了嚴(yán)格的不等號(hào),將會(huì)收到非常經(jīng)典的Yalmip“貓貓警告”,例如,運(yùn)行下面這份代碼,將會(huì)彈出如圖4的警告:
x = sdpvar(1,2);
C1 = [x(1) > 1];
圖4?嚴(yán)格不等號(hào)收到的錯(cuò)誤提示
????????除了最常用的約束條件定義運(yùn)算符包括’>=’、’<=’、’==’之外,Yalmip中還支持使用其他命令定義約束,如alldifferent, ?binary,? complements,? cone,? cut,? expcone,? iff,? implies,? integer,? ismember等等,將在后文進(jìn)行詳細(xì)介紹。
2.3定義目標(biāo)函數(shù)
????????Yalmip優(yōu)化時(shí)默認(rèn)的目標(biāo)函數(shù)是取最小值。如果目標(biāo)函數(shù)是取最大值,在目標(biāo)函數(shù)前加上一個(gè)負(fù)號(hào)就可以了。
????????例如,有兩個(gè)不同的目標(biāo)函數(shù)分別為:
定義這兩個(gè)目標(biāo)函數(shù)的代碼如下:
x = sdpvar(1,2);
f1 = x(1)^2 + 3*x(2);
f2 = -(x(1)^3 + 2*x(2)^2);
2.4設(shè)置求解參數(shù)
????????使用sdpsettings函數(shù)可以對(duì)求解的相關(guān)參數(shù)進(jìn)行設(shè)置。最常用的設(shè)置選項(xiàng)包括求解器的選擇(solver)、命令行結(jié)果展示的詳細(xì)程度(verbose)與步驟展示(showprogress)。例如,下面的代碼就是將求解器選擇為cplex,結(jié)果展示的詳細(xì)程度為0(最少的命令行展示,最大值為3),不顯示步驟(showprogress為0):
ops = sdpsettings('solver','cplex','verbose',0,'showprogress',0);
????????也可以先對(duì)選項(xiàng)結(jié)構(gòu)體進(jìn)行賦值,然后通過(guò)結(jié)構(gòu)體操作修改具體選項(xiàng)的內(nèi)容,例如:
ops = sdpsettings;
ops.solver?= cplex;
ops.verbose = 0;
ops.showprogress = 0;
????????Yalmip求解的參數(shù)非常多,如果想要查看完整的參數(shù),可以先定義一個(gè)默認(rèn)的參數(shù)選項(xiàng)ops,然后在工作區(qū)或者命令行查看該結(jié)構(gòu)體的內(nèi)容:
>> ops
ops =
??包含以下字段的 struct:
???????????????????solver: ''
??????????????????verbose: 1
????????????????????debug: 0
????????????????????usex0: 0
??????????????????warning: 1
?????????????cachesolvers: 0
?????????????showprogress: 0
????????????????saveduals: 1
?????????removeequalities: 0
?????????savesolveroutput: 0
??????????savesolverinput: 0
??????????saveyalmipmodel: 0
????????convertconvexquad: 1
????assertgpnonnegativity: 1
?????????????thisisnotagp: 0
???????????????????radius: Inf
????????????????????relax: 0
??????????????????dualize: 0
????????????????savedebug: 0
???????????????????expand: 1
????????????????allowmilp: 1
???????????allownonconvex: 1
????????????????????shift: 0
???????????????????dimacs: 0
????????????beeponproblem: [-5 -4 -3 -2 -1]
????????????mosektaskfile: ''
????????????????bisection: [1×1 struct]
??????????????????bilevel: [1×1 struct]
???????????????????bmibnb: [1×1 struct]
??????????????????????bnb: [1×1 struct]
???????????????????cutsdp: [1×1 struct]
??????????????????????kkt: [1×1 struct]
???????????????????moment: [1×1 struct]
???????????????????????mp: [1×1 struct]
????????????????????mpcvx: [1×1 struct]
?????????????????????plot: [1×1 struct]
???????????????????robust: [1×1 struct]
??????????????????????sos: [1×1 struct]
??????????????????refiner: [1×1 struct]
????????????????????baron: []
?????????????????bintprog: [1×1 struct]
???????????????????bonmin: []
?????????????????????cdcs: [1×1 struct]
??????????????????????cdd: [1×1 struct]
??????????????????????cbc: [1×1 struct]
??????????????????????clp: [1×1 struct]
????????????????????cplex: [1×1 struct]
?????????????????coneprog: []
?????????????????????csdp: [1×1 struct]
?????????????????????dsdp: [1×1 struct]
?????????????????????ecos: []
?????????????????filtersd: [1×1 struct]
??????????????????fmincon: [1×1 struct]
???????????????fminsearch: [1×1 struct]
????????????????????frlib: [1×1 struct]
?????????????????????glpk: [1×1 struct]
???????????????????gurobi: [1×1 struct]
????????????????????ipopt: [1×1 struct]
???????????????intlinprog: [1×1 optim.options.Intlinprog]
???????????????????knitro: [1×1 struct]
??????????????????linprog: [1×1 struct]
???????????????????lmilab: [1×1 struct]
??????????????????lmirank: [1×1 struct]
????????????????logdetppa: [1×1 struct]
??????????????????lpsolve: [1×1 struct]
????????????????lsqnonneg: [1×1 struct]
???????????????????lsqlin: [1×1 struct]
?????????????????????kypd: [1×1 struct]
????????????????????kktqp: [1×1 struct]
??????????????????????nag: [1×1 struct]
????????????????????mosek: [1×1 struct]
????????????????????nomad: []
?????????????????????ooqp: []
???????????????????penbmi: [1×1 struct]
???????????????????penlab: []
???????????????????pensdp: [1×1 struct]
??????????????????????pop: [1×1 struct]
??????????????????qpoases: []
?????????????????????osqp: []
????????????????????qsopt: [1×1 struct]
?????????????????quadprog: [1×1 struct]
???????????????quadprogbb: [1×1 struct]
?????????????????????scip: [1×1 struct]
??????????????????????scs: [1×1 struct]
?????????????????????sdpa: [1×1 struct]
????????????????????sdplr: [1×1 struct]
????????????????????sdpt3: [1×1 struct]
???????????????????sdpnal: [1×1 struct]
???????????????????sedumi: [1×1 struct]
????????????????sparsepop: [1×1 struct]
????????????????????snopt: [1×1 struct]
???????????????sparsecolo: [1×1 struct]
?????????????????????vsdp: [1×1 struct]
???????????????????xpress: []
??????????????????default: [1×1 struct]
????????求解參數(shù)設(shè)置的更多內(nèi)容將在后文進(jìn)行介紹,此處不再贅述。
2.5求解優(yōu)化問(wèn)題
????????Yalmip中求解優(yōu)化問(wèn)題用到的函數(shù)為optimize,使用的語(yǔ)法為:
sol?= optimize(Constraints,Objective,options);
????????其中,Constraints表示約束條件,Objective表示目標(biāo)函數(shù),options表示求解的參數(shù)。
????????如果只需要在約束條件中找到?jīng)Q策變量的一組解,就可以省略目標(biāo)函數(shù),例如:
x = sdpvar(1,2);
Constraints = [x <= 3 , x(1) >=?2 , x(2) >= 1];
ops = sdpsettings;
sol = optimize(Constraints);
????????或者將最后一行代碼改為:
sol = optimize(Constraints , [] , ops);
????????就可以在省略目標(biāo)函數(shù)的同時(shí),使用自己定義的求解參數(shù)。想要求解完整的優(yōu)化問(wèn)題,在加上目標(biāo)函數(shù)即可:
x = sdpvar(2,1);
Constraints = [x <= 3 , x(1) >=?2 , x(2) >= 1];
Objective = [1 3]*x;
ops = sdpsettings;
sol = optimize(Constraints , Objective , ops);
????????上面2.3節(jié)提到,因?yàn)閅almip默認(rèn)是求目標(biāo)函數(shù)最小值,所以求最大值時(shí)可以在目標(biāo)函數(shù)前加一個(gè)負(fù)號(hào)。當(dāng)然,也可以在定義目標(biāo)函數(shù)時(shí)保持原有的形式,使用optimize求解時(shí)給目標(biāo)函數(shù)添加負(fù)號(hào),可實(shí)現(xiàn)一樣的效果。
sol = optimize(Constraints , Objective , ops);
2.6檢查并獲取優(yōu)化問(wèn)題的解
????????optimize函數(shù)的返回值sol是一個(gè)包含六個(gè)字段的結(jié)構(gòu)體:
>> sol
sol =
??包含以下字段的 struct:
????yalmipversion: '20210331'
????matlabversion: '9.1.0.441655 (R2016b)'
???????yalmiptime: 0.0851
???????solvertime: 0.0439
?????????????info: 'Successfully solved (GUROBI-GUROBI)'
??????????problem: 0
其中,yalmipversion表示Yalmip工具箱的版本,matlabversion表示Matlab的版本,yalmiptime表示Yalmip的建模時(shí)間,solvertime表示求解器的求解時(shí)間,info表示返回的信息,problem為求解成功的標(biāo)志,0表示求解成功,1表示求解失敗。
????????其中最重要的參數(shù)就是problem和info,可以顯示求解是否成功,以及可能遇到的問(wèn)題。因此通常可以在optimize函數(shù)求解之后再加一部分代碼來(lái)展示是否求解成功和求解失敗的原因:
if sol.problem == 0
?disp('求解成功')
else
?disp('求解失敗,失敗原因?yàn)椋?)
?disp(sol.info)
end
以下的代碼是一個(gè)能求解成功的例子:
x = sdpvar(2,1);
Constraints = [x <= 3 , x(1) >=?2 , x(2) >= 1];
Objective = [1 3]*x;
ops = sdpsettings;
sol = optimize(Constraints , Objective , ops);
if sol.problem == 0
?disp('求解成功')
else disp('求解失敗,失敗原因?yàn)椋?)
?disp(sol.info)
end
下面的例子是一個(gè)求解失敗的代碼:
x = sdpvar(2,1);
Constraints = [x <= 1?, x(1) >=?2 , x(2) >= 1];
Objective = [1 3]*x;
ops = sdpsettings;
sol = optimize(Constraints , Objective , ops);
if sol.problem == 0
?disp('求解成功')
else
?disp('求解失敗,失敗原因?yàn)椋?)
?disp(sol.info)
end
????????因?yàn)榧s束條件中x1≤1且x1≥2,所以導(dǎo)致優(yōu)化問(wèn)題無(wú)解。
????????在確保優(yōu)化問(wèn)題求解成功的情況下,可以采用value命令或者目標(biāo)函數(shù)或者決策變量的取值,例如:
x = sdpvar(2,1);
Constraints = [x <= 3 , x(1) >= 2 , x(2) >= 1];
Objective = [1 3]*x;
ops = sdpsettings;
sol = optimize(Constraints , Objective , ops);
if sol.problem == 0
????disp('求解成功')
????x1 = value(x(1))
????x2 = value(x(2))
????Objective = value(Objective)
else
????disp('求解失敗,失敗原因?yàn)椋?)
????disp(sol.info)
end
結(jié)果為:
????????表示這個(gè)優(yōu)化問(wèn)題的最優(yōu)解為x1=2,x2=1,目標(biāo)函數(shù)最小值為5。
3.測(cè)試題
3.1測(cè)試1
求如下優(yōu)化問(wèn)題的解
max z=3x1+x2
s.t. x1-x2≥-2
x1-2x2≤3
3x1+2x2≤14
x1≥0, x2≥0
3.2測(cè)試2
????????找出下列代碼中的錯(cuò)誤并修改,使優(yōu)化問(wèn)題可以正常求解:
clc
clear
x = sdpvar(2,2);
Constraints = [x >= 1 , 5 >= x(1,:) >= 3 , 8 >= x(2,:) >= 6];
Objective = sum(x(:));
ops = sdpsettings('solver' , 'BNB' , 'verbose' , 3 , 'showprogress' , 1);
sol = optimize(Constraints , Objective , ops);
if sol.problem == 0
????disp('求解成功')
else
????disp('求解失敗,失敗原因?yàn)椋?)
????disp(sol.info)
end
3.3測(cè)試3
????????某廠生產(chǎn)甲乙兩種口味的飲料,每噸甲飲料需用原料6千克,工人10名,可獲利10萬(wàn)元。每噸乙飲料需用原料5千克,工人20名,可獲利9萬(wàn)元。今工廠共有原料60千克,工人150名,又由于其他條件所限甲飲料產(chǎn)量不超過(guò)8噸。問(wèn)如何安排生產(chǎn)計(jì)劃,即兩種飲料各生產(chǎn)多少使獲利最大?使用Matlab+Yalmip工具箱求解上述問(wèn)題。
3.4測(cè)試題參考答案
????????第一章測(cè)試題的參考答案可以從下面的鏈接中獲?。?mark hidden color="red">文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-614603.html
https://download.csdn.net/download/weixin_44209907/88035061文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-614603.html
到了這里,關(guān)于Yalmip入門教程(1)-入門學(xué)習(xí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!