Matlab与GAMS交互
目的:GAMS处理优化问题;MATLAB调用优化结果数据,进行后处理。
原理:gdx格式文件(两者的交互工具)
主要参考文献:
- 知乎问答“如何在Matlab里调用GAMS?”:https://www.zhihu.com/question/50259729?from=profile_question_card
- GAMS帮助文档“GDXMRW”:https://www.gams.com/latest/docs/T_GDXMRW.html#GDXMRW_APPENDIX_C
- ReachGate问答“Gams Optimization With MATLAB”:https://www.researchgate.net/post/Gams_Optimization_With_MATLAB
- GDXMRW项目主页:https://research.cs.wisc.edu/math-prog/matlab.html
- "optimization with gams"网站(有视频):http://www.gamsoptimization.com/gams-and-matlab/
- “gams-matlab”网站:https://gams-matlab.readthedocs.io/en/latest/
- CSDN博客“GAMS中导入Excel数据”:https://blog.csdn.net/weixin_44805836/article/details/88769221
- CSDN博客“GAMS与MATLAB的数据交互”(相似):https://blog.csdn.net/weixin_42421209/article/details/86436008
步骤:(以下主要来源于GDXMRW官方文档的附录部分)
配置GDXMRW
- 确认安装了MATLAB和GAMS程序(另外确认:GAMS\matout.gms 和 matlab\toolbox\local.dll存在)
- 在MATLAB中添加GAMS的启动路径(例如path = C:\GAMS)
>> addpath 'C:\GAMS'; savepath;
或者,在MATLAB工具栏操作:主页->环境->设置路径->添加并包含子文件夹->选择GAMS启动文件夹
- 测试
3.1 创建一个临时文件夹用于执行测试
>> mkdir \dir
3.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 offembedded
MATLAB调用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 foo
GAMS中的参数(或集合)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交互相关推荐
- GAMS与MATLAB的数据交互
GAMS与MATLAB的数据交互 背景 1 学习材料准备 2 添加路径 3 数据交互 3.1 GAMS数据写入与读取 3.1.1 将GAMS数据写到gdx文件中 3.1.2 GAMS读取gdx文件中的 ...
- Win32编程之基于MATLAB与VC交互的多项式回归
运行环境 Matlab R2018b x64 or x32 Visual Studio 2017 企业版 程序预览 文末有完整程序代码下载地址,有任何问题欢迎留言,谢谢点赞哟! 程序功能描述 矩阵运算 ...
- MATLAB和EXCEL交互 Spreadsheet Link
Matlab和Excel交互 Spreadsheet Link Send data to MATLAB Get data from MATLAB Excel中调用matlab函数计算 本文所有都是参考 ...
- excel和matlab交互,Excel与Matlab的数据交互(精选5篇)
Excel与Matlab的数据交互 假设列举十只股票,算其五日平均线,平均股价,标准差...等,如果用Excel Link的话,可将资料由Excel 传给Matlab处理,再将结果送回excel 中我 ...
- matlab与python交互_Python和MATLAB交互的基本操作
MATLAB和Python可以在一定程度上互相调用,起到互补的作用.本文就来抛砖引玉,总结一些最基本的操作步骤. 在MATLAB调用Python MATLAB里可以很方便的调用Python的模块.笔者 ...
- matlab调用gams错误,求助:GAMS软件运行中错误报告
我用GAMS软件解决StoNED模型,运行中出现错误报告(第91行),修改多次仍然没有解决.求高手帮忙!正确解决者奖励100论坛币. GAMS Rev 240 WIN-VS8 24.0.2 x86/ ...
- matlab导入记事本数据库,怎么才能让记事本与MATLAB的数据交互?
用MATLAB读取记事本中的数据 1.用MATLAB读取记事本中的数据. 在MATLAB当前目录下新建一个txt文本,命名为'myExample.txt'.在其中输出1 2 3 4 5 6 7 8 9 ...
- 如何实现excel与matlab的数据交互 / 如何在Excel中设置MATLAB的加载宏 / 如何实现Excel与MATLAB的连接
1.打开Excel,点击文件,点击选项. 2.点击加载项,点击转到. 3.在弹出的加载宏中点击浏览. 4.弹出的浏览选项卡中,找到你的matlab安装目录下的toolbox文件夹下的exlink文件夹 ...
- 记事本与Matlab的数据交互
一.Matlab在记事本中读取数据 1.当记事本中都是数据时: load('filename.txt') 2.当记事本中有其他不需要读入的字符 [A,B,C...] = textread('filen ...
最新文章
- 【集合论】Stirling 子集数 ( 斯特林子集数概念 | 放球模型 | Stirling 子集数递推公式 | 划分的二元关系 加细关系 )
- 报表系统FineReport通过权限控制数据访问方案
- Android开发系列之屏幕密度和单位转换
- 微信支付软件架构重构之旅
- visual studio哪一款比较好用_时下比较流行的7种家居装修风格,你钟爱哪一款?...
- Flashlight should be gray after finishing Recor...
- 《C++Primer》14、15章
- 不要老谈“设计模式”
- 拓端tecdat|Python基于粒子群优化的投资组合优化研究
- pdf数据脱敏 如何恢复_如何恢复Word文档丢失的数据?
- 关于修复msvcp110.dll丢失的问题
- 转回到Edison上开发
- 我曾在外包公司呆过,谈一谈外包要不要进?
- 配置有误:由于权限不足而无法读取配置文件
- mysql查询最新的一条记录_mysql 查询不同用户 最新的一条记录
- 免费打造自己的个人网站,免费域名、免费空间、FTP、数据库什么的,一个不能少,没钱,也可以这么任性...
- cesium实现运动模型的相机上帝视角跟随
- Vue3中的setup前加上async后页面不显示
- SpringSecurity如何处理logout注销操作
- Android 10 新增物理按键
热门文章
- token是什么?如何获取token
- 类型多样的家居装饰C4D模型素材,速来收藏
- 备份服务器有哪几种方式
- 深谈计算机网络互联技术论文,浅谈计算机网络技术对音乐发展的影响
- python通过POST提交页面请求
- [ 渗透入门篇 ] 渗透行业必备术语大集合(六)
- 黑莓手机今天彻底死了,但黑莓活得很滋润
- editplus自动换行html,editplus的设置
- telnet mysql3306端口失败
- 全麦吐司和普通吐司的区别_“全麦面包”是“全麦”吗?一字之差区别大,专家建议标明全麦含量...