目的:GAMS处理优化问题;MATLAB调用优化结果数据,进行后处理。

原理:gdx格式文件(两者的交互工具)

主要参考文献:

  1. 知乎问答“如何在Matlab里调用GAMS?”:https://www.zhihu.com/question/50259729?from=profile_question_card
  2. GAMS帮助文档“GDXMRW”:https://www.gams.com/latest/docs/T_GDXMRW.html#GDXMRW_APPENDIX_C
  3. ReachGate问答“Gams Optimization With MATLAB”:https://www.researchgate.net/post/Gams_Optimization_With_MATLAB
  4. GDXMRW项目主页:https://research.cs.wisc.edu/math-prog/matlab.html
  5. "optimization with gams"网站(有视频):http://www.gamsoptimization.com/gams-and-matlab/
  6. “gams-matlab”网站:https://gams-matlab.readthedocs.io/en/latest/
  7. CSDN博客“GAMS中导入Excel数据”:https://blog.csdn.net/weixin_44805836/article/details/88769221
  8. CSDN博客“GAMS与MATLAB的数据交互”(相似):https://blog.csdn.net/weixin_42421209/article/details/86436008

步骤:(以下主要来源于GDXMRW官方文档的附录部分)

配置GDXMRW

  1. 确认安装了MATLAB和GAMS程序(另外确认:GAMS\matout.gms 和 matlab\toolbox\local.dll存在
  2. 在MATLAB中添加GAMS的启动路径(例如path = C:\GAMS)
    >> addpath 'C:\GAMS'; savepath;

    或者,在MATLAB工具栏操作:主页->环境->设置路径->添加并包含子文件夹->选择GAMS启动文件夹

  3. 测试

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交互相关推荐

  1. GAMS与MATLAB的数据交互

    GAMS与MATLAB的数据交互 背景 1 学习材料准备 2 添加路径 3 数据交互 3.1 GAMS数据写入与读取 3.1.1 将GAMS数据写到gdx文件中 3.1.2 GAMS读取gdx文件中的 ...

  2. Win32编程之基于MATLAB与VC交互的多项式回归

    运行环境 Matlab R2018b x64 or x32 Visual Studio 2017 企业版 程序预览 文末有完整程序代码下载地址,有任何问题欢迎留言,谢谢点赞哟! 程序功能描述 矩阵运算 ...

  3. MATLAB和EXCEL交互 Spreadsheet Link

    Matlab和Excel交互 Spreadsheet Link Send data to MATLAB Get data from MATLAB Excel中调用matlab函数计算 本文所有都是参考 ...

  4. excel和matlab交互,Excel与Matlab的数据交互(精选5篇)

    Excel与Matlab的数据交互 假设列举十只股票,算其五日平均线,平均股价,标准差...等,如果用Excel Link的话,可将资料由Excel 传给Matlab处理,再将结果送回excel 中我 ...

  5. matlab与python交互_Python和MATLAB交互的基本操作

    MATLAB和Python可以在一定程度上互相调用,起到互补的作用.本文就来抛砖引玉,总结一些最基本的操作步骤. 在MATLAB调用Python MATLAB里可以很方便的调用Python的模块.笔者 ...

  6. matlab调用gams错误,求助:GAMS软件运行中错误报告

    我用GAMS软件解决StoNED模型,运行中出现错误报告(第91行),修改多次仍然没有解决.求高手帮忙!正确解决者奖励100论坛币. GAMS Rev 240  WIN-VS8 24.0.2 x86/ ...

  7. matlab导入记事本数据库,怎么才能让记事本与MATLAB的数据交互?

    用MATLAB读取记事本中的数据 1.用MATLAB读取记事本中的数据. 在MATLAB当前目录下新建一个txt文本,命名为'myExample.txt'.在其中输出1 2 3 4 5 6 7 8 9 ...

  8. 如何实现excel与matlab的数据交互 / 如何在Excel中设置MATLAB的加载宏 / 如何实现Excel与MATLAB的连接

    1.打开Excel,点击文件,点击选项. 2.点击加载项,点击转到. 3.在弹出的加载宏中点击浏览. 4.弹出的浏览选项卡中,找到你的matlab安装目录下的toolbox文件夹下的exlink文件夹 ...

  9. 记事本与Matlab的数据交互

    一.Matlab在记事本中读取数据 1.当记事本中都是数据时: load('filename.txt') 2.当记事本中有其他不需要读入的字符 [A,B,C...] = textread('filen ...

最新文章

  1. 【集合论】Stirling 子集数 ( 斯特林子集数概念 | 放球模型 | Stirling 子集数递推公式 | 划分的二元关系 加细关系 )
  2. 报表系统FineReport通过权限控制数据访问方案
  3. Android开发系列之屏幕密度和单位转换
  4. 微信支付软件架构重构之旅
  5. visual studio哪一款比较好用_时下比较流行的7种家居装修风格,你钟爱哪一款?...
  6. Flashlight should be gray after finishing Recor...
  7. 《C++Primer》14、15章
  8. 不要老谈“设计模式”
  9. 拓端tecdat|Python基于粒子群优化的投资组合优化研究
  10. pdf数据脱敏 如何恢复_如何恢复Word文档丢失的数据?
  11. 关于修复msvcp110.dll丢失的问题
  12. 转回到Edison上开发
  13. 我曾在外包公司呆过,谈一谈外包要不要进?
  14. 配置有误:由于权限不足而无法读取配置文件
  15. mysql查询最新的一条记录_mysql 查询不同用户 最新的一条记录
  16. 免费打造自己的个人网站,免费域名、免费空间、FTP、数据库什么的,一个不能少,没钱,也可以这么任性...
  17. cesium实现运动模型的相机上帝视角跟随
  18. Vue3中的setup前加上async后页面不显示
  19. SpringSecurity如何处理logout注销操作
  20. Android 10 新增物理按键

热门文章

  1. token是什么?如何获取token
  2. 类型多样的家居装饰C4D模型素材,速来收藏
  3. 备份服务器有哪几种方式
  4. 深谈计算机网络互联技术论文,浅谈计算机网络技术对音乐发展的影响
  5. python通过POST提交页面请求
  6. [ 渗透入门篇 ] 渗透行业必备术语大集合(六)
  7. 黑莓手机今天彻底死了,但黑莓活得很滋润
  8. editplus自动换行html,editplus的设置
  9. telnet mysql3306端口失败
  10. 全麦吐司和普通吐司的区别_“全麦面包”是“全麦”吗?一字之差区别大,专家建议标明全麦含量...