目录
如何在 VSCode 中配置和编写 LINGO
LINGO 是用来解决优化问题的一个特别好用的软件,可以快速求解线性规划、非线性规划、线性和非线性方程组等规划问题。,LINGO 好处多多确实很方便,但是 LINGO 18.0 原生的 IDE 不能说依托答辩吧,只能说惨不忍睹:无论是冷战风格的远古界面还是一写注释就会混乱的代码高亮,以及兼容性奇差无比的富文本支持,都让我这种赛博颜狗感到满满的恶意。按照我的理解和猜测,包括我在内的很多人都会强势诉诸于其他的代码编辑器,比如 Visual Stdio Code。
但是与此同时,当你在网上一搜索,就会发现全互联网上找不出几个关于怎么在 VSCode 里面配置和使用 LINGO 的教程。毕竟,确实,真到了解决大型复杂工程学规划问题的时候有 MATLAB、Gurobi 和 SCIP 等一大众高级货色,再怎么也不会真拿 LINGO 去求解。没有办法,只能自己动手丰衣足食了。
本教程将教会你如何一步一步在 VSCode 中配置自己的 LINGO IDE。
安装 VSCode 扩展
首先,VSCode 上面确实有一个 Lingo language support 的扩展,而且根据我的尝试,所有的扩展里面只有这一个扩展是靠谱的。(其他的扩展不要安装。有些是 lingoJS 的扩展,有些半身不遂,会把文件高亮覆盖掉。)我们首先把这个扩展安装上。
安装好扩展之后,可以看到模型文件已经拥有了还算不错的高亮可以看。但是仍然不能一键运行求解模型。
对于代码的自动运行,我们需要安装 Code Runner 插件 并进行自动化配置。自动化配置的具体流程我们会在下面的文章里面跟大家介绍。
LINGO 脚本文件与 runlingo 命令
查阅 LINGO 的帮助文档可以发现 LINGO 的帮助文档里面提及了一个名为 RunLingo 的程序。找到这样一段描述,我翻译了一下:
LINGO的Windows版本包括一个名为RunLingo的实用程序。RunLingo可以用于处理LINGO脚本文件,但是,RunLingo不包括LINGO交互式版本中的前端图形界面。RunLingo是从命令行调用的,您可以在命令行中输入脚本文件名。RunLingo将其输出写入标准输出设备。RunLingo在生产环境中非常有用——如果您希望LINGO作为更大规划系统的一部分在后台安静地运行。
尝试在命令行终端中输入 runlingo
命令:
$ runlingo
Enter "runlingo script_file_path" to execute the
LINGO command script in file script_file_path.
可以看见 runlingo
命令已经在 LINGO 安装时被添加到了环境变量,这个时候已经可以直接调用了,使用方法为:
runlingo <脚本文件名>.ltf
如果在程序安装的时候,出于某些原因 runlingo
没有被正常添加到环境变量导致命令无法执行,可能需要手动添加。手动添加环境变量的方法请自行在网上搜索。
LINGO 命令行交互和脚本文件
RunLingo 不能直接执行常见的 LINGO 模型文件(.lg4
或者 .lng
之类的)。相反,它直接运行的是 LINGO 的脚本文件 .ltf
格式。关于 .ltf
文件 LINGO 官方文档里面 [有相应的解释可以在这个链接里查看](LINGO 15 Online Users Manual。简单的来讲:.ltf
文件里面编写的是 LINGO 的交互命令。由于 LINGO 命令行交互对大多数人来讲都很陌生、很少使用,因此我们这里解释一下:
在 LINGO 主界面标签栏下依次点击 Window
、Command Window
可以打开命令行图窗,输入 COM
查看可用的命令:
: COM
LINGO commands by category. For information on a specific command, type:
'HELP command-name'.
1) Information
COM CAT HELP MEM
2) Input
MODEL TAKE RMPS FRMPS RMPI RLPF
3) Display
LOOK GEN PAUS HIDE STATS PICTURE DUAL XDETEQ SCENE
SHOWNL LISTFIX
4) File Output
DIV RVRT SAVE SMPS SMPI
5) Solution
GO SOLU NONZ RANGE DEBUG
6) Problem Editing
DEL EXT ALT
7) Quit
QUIT
8) System Parameters
PAGE TERS VERB WIDTH SET FREEZE DBUID DBPWD APISET
9) Miscellaneous
TIME
有一说一这个命令行交互相当的不好用,我的建议是没啥大事别瞎折腾……
输入 HELP <命令名称>
可以查看命令帮助提示。比如:
:HELP TAKE
TAKE command:
Allows a series of commands to be taken from a file. The
file contents should appear exactly as terminal input.
A file created with the "SAVE" command can be read with the
TAKE command.
与此同时,在 LINGO 安装的目录下的 Samples 文件夹里面有一个 LTF 脚本的示例文件 TEST.ltf
,文件里面展示了 LTF 脚本的一些基本使用方法和常用的书写方法。如果用任意的文本编辑器打开,就可以看到里面的内容为:
! Input a small model
MODEL:
MAX = 20 * X + 30 * Y;
X <= 50;
Y <= 60;
X + 2 * Y <= 120;
END
! Terse output mode
SET TERSEO 1
! Solve the model
GO
! Open a file
DIVERT SOLU.TXT
! Send solution to the file
SOLUTION
! Close solution file
RVRT
! Quit LINGO
QUIT
同时,结尾处有一个文本编辑器没有办法识别的特殊字符。我在这里没有贴出来。关于这个特殊字符的问题,我们会在后面纠结。
简单的来讲,从 LINGO 的官方文档来看,官方文档鼓励用户将脚本和模型写在同一个文件里面。我个人认为,对于简单的模型来说,确实可以这样做,但是对于复杂模型来说,这样做会增加代码编写的负担。 我的建议是将用于运行模型的脚本,书写在一个独立的 .ltf
文件里,同时,将模型书写在另外一个 .lng
文件里。前者定义在命令行中运行模型的各项规则,而后者则是模型的直接定义,方便项目的迁移和管理。以下是一个 DEMO:
以下是 lingo.ltf
的内容:
! LINGO 用于执行模型的脚本;
! 读取模型到 runlingo;
take LP.lng
! 运行模型;
GO
! 输出模型结果到文件 `sulution.txt`
! 要求目录下存在 `sulution.txt`
! 即使注释掉内容模型还是会在终端输出结果
!;
DIVERT solution.txt
SOLUTION
RVRT
! 退出 LINGO;
QUIT
以下是 LP.lng
的内容:
! 规划模型的定义文件
!
! 工程项目投资问题
! ================
!
! 某公司有一批资金欲投资到5个工程项目中,
! 各工程项目的净收益(投入资金的百分比)见下表所示
! 工程项目 | A | B | C | D | E
! -------- | --- | --- | --- | --- | ---
! 收益 / % | 10 | 12 | 15 | 12 | 8
!
! 由于一些原因,公司决定用于项目A的投资不大于其他各项投资之和,
! 而用于项目B和项目D的投资要大于项目C和项目E的投资。
!
! 试确定投资分配方案,使该公司收益最大。
!;
MODEL:
SETS:
Pro / 1..5 / : x;
ENDSETS
DATA:
ENDDATA
max = 0.10 * x(1) + 0.12 * x(2) + 0.15 * x(3) + 0.12 * x(4) + 0.08 * x(5);
x(1) - x(2) - x(3) - x(4) - x(5) <= 0;
x(2) - x(3) + x(4) - x(5) >= 0;
@sum(
Pro(i):x(i)
)=1;
@for(
Pro(i):x(i)>=0
);
END
这些内容都可以直接在 Visual Stdio Code 中编写。
配置 Visual Stdio Code 的设置
至此我们可以开始配置 VSCode。
配置 LTF 文件的代码高亮
LINGO 的扩展默认不支持 LTF 文件的高亮。我们可以在 VSCode 的设置框中搜索 files.Associations
,可以找到下面的设置。我们在 Files: Associations 中将 *.lng
和 *.ltf
格式的文件关联到 lingo 语言(由于已经安装了 LINGO 语言的扩展,因此 lingo
的 Value 已经可以被识别。)
接下来我们在搜索框里输入 code-runner
,在设置里找到 Executor Map
,点击 Edit in setting.json
。
像图中这样,在接下来立即打开的 .json
文件中找到如下的项:
"code-runner.executorMap":{
...
}
"code-runner.executorMap"
保存了由用户自行定义的、后缀名为 .*
的文件在按下一件运行之后执行的终端命令。对于 .ltf
文件,我们可以定义如下的规则:
"code-runner.executorMap":{
/* 由用户定义的各项编程语言源文件的运行命令 */
".ltf" : "runlingo $fileName"
},
至此为止,配置已经基本完成。其余的各项,可以根据个人需求的不同自行配制。
关于文件兼容的一些小问题
-
LINGO 默认的
.lg4
文件实际上是二进制文件格式,无法直接用文本编辑器打开。需要另存为.lng
的纯文本格式。 -
.lng
格式如果出现乱码,尤其是中文注释乱码,请在 VSCode 右下角找到编码格式按钮,重新通过 GB2312 编码格式打开。 -
对于
.lng
文件,由于我们现在用 RunLingo 命令从 LTF 调用,因此应当在文本开头用和末尾用MODEL: ... END
关键字包裹全文,SETS
和DATA
的定义也要包含在内。防止出现不必要的各种问题。 -
不知道为什么,LINGO 会默认在
.lng
格式的纯文本文件末尾添加一个文本编辑器无法识别的字符。如下图所示。目前看来直接删掉这个字符对求解没有影响。