Matlab与GAMS交互
目的:GAMS處理優化問題;MATLAB調用優化結果數據,進行后處理。
原理:gdx格式文件(兩者的交互工具)
主要參考文獻:
步驟:(以下主要來源于GDXMRW官方文檔的附錄部分)
配置GDXMRW
3.1 創建一個臨時文件夾用于執行測試
>> mkdir \dir3.2 從GAMS測試庫中提取運行測試模型和支持文件,存放在臨時文件夾
>> cd \tmp >> testlib gdxmrw03 %測試rgdx >> testlib gdxmrw04 %測試wgdx >> testlib gdxmrw05 %gams中的MATLAB路徑 >> testlib gdxmrw06 %測試irgdx和iwgdx(在執行這一步驟時,可能會出現找不到這幾個文件的報錯,原因是GAMS庫中的這些文件的格式出現亂碼。解決方法:在GAMS路徑中打開testlib_ml文件夾,找到gdxmrw03.***這幾個文件,將文件后綴改為.gms)
(出現未定義testlib函數或變量的報錯。可能解決方法:修改testlib的后綴,或者是因為盜版軟件、中文系統導致的部分文件亂碼、丟失?)
?疑惑?:這里的gdxmrw**的例子里,gams文檔里用call語句調用了MATLAB,最終的結果卻一直沒能指定在MATLAB的文件夾路徑之下。思路1:是否需要在call語句中指定matlab的路徑或執行程序的路徑;思路2:call語句的句法?是否需要特別設置參數?
>> testinst /集體測試如果上面的幾個testlib測試都不成功,只有這個測試成功,基本也說明gdxmrw可用的。
也可以用這個testinst來驗證測試rgdx:
>> [x, y] = gams('testinst'); %結果會出現兩個結構體x,y公用函數:gdxWhos和gdxInfo
這兩個公用程序能使GDXMRW能被MATLAB的命令提示符調用。gdxWhos函數是在MATLAB函數whos查詢過.mat文件之后松弛構造的,它提供了指定GDX文件的(符號)信息,唯一的輸入參數就是所指定GDX文件的名稱(可以不加.gdx后綴)。如果gdxWhos沒有指定輸出參數,那么它會在MATLAB的命令提示符中顯示指定GDX文件的(符號)信息;如果指定一個輸出參數的話,GDX的(符號)信息將會包含在返回的一個結構體數組(arrary of structrues)里,這個元數據(meta-data)在編程時很有用,有多種用途。
一個沒有返回參數的gdxWhos調用:
>> gdxWhos('idx1_.gdx'); Symbol info of GDX idx1_.gdxIndex Type Dim NRecs Name1 Parameter 0 1 a0 2 Parameter 1 3 a1(5) 3 Parameter 2 4 a2(2,2) 4 Parameter 3 6 a3(3,5,2) 5 Parameter 10 256 a10(3,5,2,2,2,2,2,2,2,2)這個例子中,idx1_gdx有5個參數,每個參數的索引參數可以在“Name”這一列看到。如果沒有索引數據,那么參數將會作為一個集合或者顯示一個'*'符號,下面這個例子的前三個參數沒有索引,最后一個有索引:
>> gdxWhos('fake.gdx'); Symbol info of GDX fake.gdxIndex Type Dim NRecs Name1 Set 1 3 i(*)2 Parameter 1 3 a(i)3 Set 1 3 d_i_m__3(*)4 Parameter 1 3 aa(3)gdxInfo函數是在gdxdump公用函數之后構造的,它在MATLAB的命令行窗口列出并消除指定GDX文件每個符號的數據值。用法同gdxWhos。例如:
>> gdxInfo('idx1_.gdx') * Library in use : F:\GAMS25.1 * Library version: GDX Library 25.1.3 r4e34d435fbd Released Oct 30, 2018 WEI x86 64bit/MS Wi * File version : GDX Library 24.2.0 r42219 ALFA Released 26Sep13 LNX x86/Linux * Producer : GAMS Base Module 24.2.0 r42219 ALFA Released 26Sep13 LNX x86/Linux * Symbols : 5 * Unique Elements: 5//文檔的具體內容 $ontext . . . . . . $offempty offembeddedMATLAB調用GAMS模型
MATLAB通過一個公用函數“gams”,使用MATLAB數據初始化并運行GAMS模型,再將結果返回給MATLAB。雖然“gams”函數與“rgdx”和“wgdx”都是基于同樣的設計,但是它做任何事都只需要調用一下,這個函數是可以多輸入多輸出的,標準語法:
>> [x1, x2, x3] = gams('model', s1, s2.., c1, c2..);其中第一個參數是GAMS中model的名稱和用戶任意設置的命令。例如,用戶可以設置給定model(下面例子中是qp.gms)的不同求解器(在GAMS model名稱后添加求解器名稱:"qp nlp=baron"),也可以改變模型的執行時間。
GAMS的其他輸入參數都是結構體(structures),它們的位置不重要。這些結構體有兩類:一類是與wgdx的輸入結構體相類似;另一類結構體只有兩個字符串字段:名稱(name)和值(val)。后一類能夠在GAMS中通過“$set”變量語法來設置或者重寫model的值。
一個二次優化的GAMS模型例子:minimizes ? xTQx+cTx subject to Ax≥b and x≥0
$set matout "'matsol.gdx', x, dual, obj, returnStat ";Seti / 1*2 /j / 1*3 /;Alias (j1,j);ParameterQ(j,j1) / 1 .1 1.02 .2 1.03 .3 1.0 /A(i,j) / 1 .1 1.01 .2 1.01 .3 1.02 .1 -1.02 .3 1.0 /b(i) / 1 1.02 1.0 /c(j) / 1 2.0 /;Variable obj;Positive Variable x(j);Equation cost, dual(i);cost.. obj =e= 0.5*sum(j, x(j)*sum(j1, Q(j,j1)*x(j1))) + sum(j, c(j)*x(j));dual(i).. sum(j, A(i,j)*x(j)) =g= b(i);Model qp / cost, dual /;$if exist matdata.gms $include matdata.gmssolve qp using nlp minimizing obj;Set stat / modelStat, solveStat /;Parameter returnStat(stat); returnStat('modelStat') = qp.modelstat; returnStat('solveStat') = qp.solvestat;execute_unload %matout%;如果直接在GAMSIDE中運行,優化結果是0.5。
在MATLAB中運行:
>> x = gams('qp');這個命令首先收集輸入的結構體數據,然后在一個'matdata.gdx'和能在matdata.gdx文件中創建包含能寫入符號狀態描述的'matdata.gms'。在上面這個例子中,它沒有結構體的輸入,所以創建一個空的“matdata.gdx”文件,“matdata.gms”將只加載一個沒有符號的描述。如果已經存在了一個“matdata.gdx”或者“matdata.gms”文件,這將是為了在主模型中阻止任何不期望的數據加載。當創建了這兩個文件后,"gams"程序段將會使用一個系統調用來執行“gams qp”。當這個模型被執行過之后,模型最后一行的描述語句“execute_unload”將會創建另一個“matsol.gdx”文件。注意,想要使用MATLAB的gams路徑執行任何模型,都應該包含類似下面這樣的語句(在第一行或者模型文件的開頭部分):
$set matout "'matsol.gdx', x, dual, obj, returnStat ";這是GAMS一個標準的$set語句,用來設置局部變量“matout”的值。GAMS程序會從gms文件的開頭開始搜索'$set matout',而這些gms文件可能是很大的,所以要把這個語句放在gms文件開頭附近。在這個語句中,將會創建一個包含'x1''x2'等符號的文件名為'fileName'的gdx文件,這些符號隨后可以被輸出至MATLAB。模型的最后一行應該總是:
execute_unload %matout%;模型的首行和最后一行設置這樣語句的原因是,在模型的’header'中明確用戶想要輸出到MATLAB的數據。如果MATLAB沒有給除了期望參數以外的其他輸出參數,我們必須要明確在GAMS中的model輸出什么數據到MATLAB。在上面這個例子中只有一個輸出參數,因此'gams‘程序將為了它的第一個元素,從輸出的gdx文件獲取數據并儲存在MATLAB的輸出參數中。
如果要輸出不止一個參數,例如:
>> [x, u] = gams('qp');這個gams程序將會讀取輸出的gdx文件:儲存gdx文件的第一個元素信息作為MATLAB的第一個輸出參數,例如'x’;gdx文件的第二個元素信息作為MATLAB的第二個輸出參數,例如'u',以此類推。如果MATLAB輸出參數的數量多于了gdx文件的元素數量,gams程序將輸出error。(可以參考datalib的gdxmrw_qp4例子)
(bug: 在GAMS中可以直接運行qp.gms得到結果,但是matlab調用時出現“abnormal GAMS termination running F:\GAMS25.1\gams.exe qp lo=0: check listing file”的錯誤。debug:原因是文件夾的中文名稱過長,結果出現ASCII,解決方法為,文件夾名稱精簡成短英文)
輸入結構體
如前所述,gams程序的輸入參數是結構體的形式。它允許兩種結構體類型,一種是類似于wgdx輸入結構體,它包含符號數據被輸出至gdx文件,另一種只有兩個字符串字段'name'和'val'。使用示例:
>> s.name = 'Q'; >> s.val = eye(3); >> s.form = 'full'; >> m = struct('name', 'm', 'val', '2'); >> [x] = gams('qpmcp', s, m);在這個例子中,'s'和'm'都是結構體,但是'm'只有兩個字符串字段。gams程序將使用's'結構體創建一個'matdata.gdx‘文件,使用'm'修改執行命令行使得在最后包含"--m=2"。例如一條命令將會像“gams qpmcp --m=2”這樣執行。
雖然's'結構體與wgdx的輸入結構體類似,但還是有兩個主要的不同。首先,從上面例子也可以看到's'結構體沒有'type'字段,在wgdx中我們默認結構體的type為'set',而在gams程序中是被默認為'parameter'的;其次,'s'有一個可選的額外的輸入字段'load'。
關于‘load’:它是一個代表相應數據將如何被加載到GAMS程序的字符串輸入。GAMS讀取的輸入數據可以根據全局選項'gamso.input'的值有不同的方式,加入輸入結構體's'有一個被稱為'foo'的"name'字段,matdata.gms文件將(在gamso.input = ‘compile’)默認:
$ loadR fooGAMS中的參數(或集合)foo將會被在'matdata.gdx'容器中的'foo'所替代(注:foo在編程中常用于函數/方法的名稱,此外還有bar、foobar等,像“張三”“李四”一樣,并無實際用途和引用意義),如果數據已經在模型中被初始化了,這將會用'matdata.gdx'中的新數據替代初始化數據,可以明確的設置這個可選項:
s.load = 'replace'還有其他兩種編譯時間加載選項,稱為'initialize'和'merge',前者僅在參數值還沒在GAMS文件中初始化時有效,否則就會報錯,它的GAMS語法是:
$load foo后者的有效條件是當GAMS文件運行時參數值已經被初始化了,MATLAB的's'結構體的新值將與根據新值重寫的參數進行簡單合并。明確的說,'matdat.gms'文件包含
$loadM foo這樣的描述,用來相應地指導GAMS。
最后,如果gamso.input='exec',那么加載將會出現在運行時間。在這個例子中,s.load='initialize'不是一個有效的輸入,默認的設置是s.load='replace',通過執行
execute_load "matdata.gdx" foo另一個設置s.load='merge'是通過執行
execute_loadpoint "matdata.gdx" foo通過這樣的方式,數據在運行時間被加載,并做出合適的repalce或者merge。
改變默認行為的全局輸入
以上是如何具體規定gams程序的不同輸入,這一節是介紹如何改變gams調用的默認行為。它可以通過在工作空間創建一個'gamso'結構體,并往這個結構體中添加不同的字段。目前這個結構體中有9個能影響程序行為的字段可以被設置。除了uels字段,所有其他字符串字段都采用不區分大小寫的字段。這些可選項都是面向全局的。
- gamso.output
- gamso.input
- gamso.write_data
- gamso.show
- gamso.path
- gamso.compress
- gamso.form
- gamso.uels
- gamso.fields
總結
1. 對于GAMS文件
在文件開始部分加上
$set matout "'***.gdx', *, *, ...";在文件末尾加上
execute_unload %matout%2.對于MATLAB文件
調用語法格式為
[*, *, ...] = gams('***.gms', *, *, ...)?
?
?
總結
以上是生活随笔為你收集整理的Matlab与GAMS交互的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用java把中文小写数字转化为阿拉伯数
- 下一篇: 如何手动下载最新的 macOS Beta