目录
- MATLAB LINGO API
- 安装
- LINGO_Pointer 对象
- LINGO_Model 对象
- 求解模型
- 模型示例
- 可选回调函数
- 回调示例
MATLAB LINGO API
这个包的目的是将 LINGO 的强大求解器和模型表达的简便性与 MATLAB 环境结合起来。本文档的第一个目的是将该包安装到你的 MATLAB,然后帮助你开始从 MATLAB 与 LINGO 模型进行交互。
安装
LINGO MATLAB API 需要你使用的是 Windows 64 位并安装了 LINGO,且 MATLAB 版本至少为 R2018b。满足所有要求后,导航到 \C:\PATH\TO\LINGO64_21\Programming Samples\MATLAB
并点击 LINGO_API.mltbx
。这样做会将 LINGO_API 工具箱安装到你的 MATLAB 中。
LINGO_Pointer 对象
本节将介绍 LINGO_Pointer 对象的创建,该对象模拟 LINGO 函数 @POINTER() 用于在 LINGO 和 MATLAB 之间传递数据。
matlab
myPointer = LINGO_Pointer(type, data);
输入参数:
- type: 此参数告诉 MATLAB 如何准备数据以供 LINGO 使用,以及模型完成后如何将数据返回给你。此参数可以是以下三个 LINGO_Pointer 常量之一:
- LINGO_Pointer.PARAM 或 0: 数值模型参数数据。
- LINGO_Pointer.SET 或 1: 集合索引的字符串字符名。
- LINGO_Pointer.VAR 或 2: 数值模型变量数据。
- data: 要发送到 LINGO 的 MATLAB 数据。对于变量和参数类型,MATLAB 数据可以是数组或矩阵。集合数据可以是字符串数组或单元格数组。
LINGO_Pointer 对象有三个属性,可以在构造后访问。
- type: 与构造时相同的类型。
- data: 与构造时相同的数据。
- LINGO_data: 已整理好发送到 LINGO 的数据。此属性供 LINGO_Model 访问。
要访问对象的属性,请使用对象点符号。
matlab
myPointersData = myPointer.data;
LINGO_Model 对象
本节将介绍 LINGO_Model 对象的构造以及如何添加可选属性。LINGO_Model 对象用于保存你想要求解的 LINGO 模型的信息。
matlab
myModel = LINGO_Model(pointers, modelPath);
输入参数:
- pointers: LINGO_Pointer 的数组,每个 LINGO_Pointer 的顺序与它在 LINGO 模型中的顺序相同。
- modelPath: LINGO 模型文件的绝对或相对路径的字符字符串。
LINGO_Model 对象有四个可在构造后设置的附加属性。这些属性是可选的。
- logPath: 日志文件的绝对或相对路径的字符字符串。此文件不需要存在,模型运行时 LINGO 会创建或覆盖它。
- solverCB: 求解器回调函数的名称字符字符串。此回调函数必须写在 MATLAB 函数文件中。有关求解器回调的详细信息,请参见可选回调函数部分。
- errorCB: 错误回调函数的名称字符字符串。此回调函数必须写在 MATLAB 函数文件中。有关错误回调的详细信息,请参见可选回调函数部分。
- uData: 从 LINGO 传递给可选求解器和错误回调函数的 MATLAB 数据。
要在 LINGO_Model 对象上设置可选属性,请使用对象点符号。
matlab
% 创建一个结构体来保存 uData
uData.niter = 0;
uData.objVal = 0;
% 将 uData 添加到 myModel
myModel.uData = uData;
要访问对象的属性,请使用对象点符号。
matlab
myModelPath = myModel.modelPath;
求解模型
一旦创建了 LINGO_Model 并设置了你想使用的所有可选参数,调用 solve()
将数据发送到 LINGO。
matlab
Pointers = LINGO_Model.solve(model)
输入参数:
- model: LINGO_Model 对象。
输出参数: - Pointers: LINGO_Pointer 对象的数组。
模型示例
有关可运行的示例,请参见 \C:\PATH\TO\LINGO64_21\Programming Samples\MATLAB
文件夹中的示例文件夹。下面是一个简单示例,用于澄清上述各部分内容。
matlab
modelPath = 'chess.lng';
logPath = 'chess.log';
% 模型集合数据
NUTS = ["Peanut", "Cashew"];
BRANDS = ["Pawn", "Knight", "Bishop", "King"];
% 模型参数数据
SUPPLY = [750, 250];
PRICE = [2,3,4,5];
FORMULA = [15 1
10 6
6 10
2 14];
% 模型变量数据
PRODUCE = [0,0,0,0];
% 从一个空的 LINGO_Pointer 对象数组开始
Pointer = LINGO_Pointer.empty();
% 对于 chess.lng 中的每个指针,将指针数据添加到 Pointer 列表中
Pointer( 1) = LINGO_Pointer(LINGO_Pointer.SET, NUTS );
Pointer( 2) = LINGO_Pointer(LINGO_Pointer.SET, BRANDS );
Pointer( 3) = LINGO_Pointer(LINGO_Pointer.PARAM, SUPPLY );
Pointer( 4) = LINGO_Pointer(LINGO_Pointer.PARAM, PRICE );
Pointer( 5) = LINGO_Pointer(LINGO_Pointer.PARAM, FORMULA );
Pointer( 6) = LINGO_Pointer(LINGO_Pointer.VAR, PRODUCE );
uData.nIter = 0;
solverCb = "SolverCb";
% 将数据添加到 LINGO_Model 对象以及 modelPath 和 logPath
model = LINGO_Model(Pointer, modelPath);
model.logPath = logPath;
model.solverCB = solverCb;
model.uData = uData;
% 求解模型并返回更新的指针
Pointer = LINGO_Model.solve(model);
% 显示变量 PRODUCE 指针
display(Pointer( 6).data);
可选回调函数
如 LINGO_Model 对象部分所述,有两个可选的回调函数。首先是求解器回调函数,该函数在 LINGO 求解模型期间定期调用。其次是错误回调函数,仅当 LINGO 在求解时遇到错误时调用。
下面是求解器回调函数的模板。输入和输出必须匹配模板,因为 LINGO API 将按此顺序发送和接收数据。
matlab
function [flag, udata] = SolverCb(env, reserved, udata)
% 你的代码
flag = int32(0); % flag = int32(1); 以中断 LINGO 求解器。
end
输入参数:
- env: 表示 LINGO 模型环境指针的 Long Long Int。
- reserved: 忽略此数据,它是 LINGO 将来扩展的占位符。
- udata: LINGO_Model 对象的可选 udata 属性。如果在调用 solve 之前未设置 udata 且设置了求解器回调,则 udata 将是一个空结构体。
输出参数: - flag: 一个 int32 值,告诉 LINGO 继续或停止。如果 flag 设置为 0,则 LINGO 将继续,如果 flag 设置为 1,则 LINGO 将终止。
- udata: 每次调用求解器回调时返回的 udata 参数,以保存对其所做的任何更改。
可以从求解器回调函数中调用 LINGO_API.LSgetCallbackInfoLng 函数,以请求 LINGO 的具体信息。
matlab
[errorCode, data] = LINGO_API.LSgetCallbackInfoLng(env, nObject);
输入参数:
- env: 由 LINGO 传递给求解器回调函数的 env。
- nObject: LINGO_API 常量 int32,告诉 LINGO 你请求的信息。参见下表了解可用选项的描述。
matlab
索引 名称 类型 信息项
0 LINGO_API.LS_IINFO_VARIABLES_LNG Int 变量总数
1 LINGO_API.LS_IINFO_VARIABLES_INTEGER_LNG Int 整数变量数
2 LINGO_API.LS_IINFO_VARIABLES_NONLINEAR_LNG Int 非线性变量数
3 LINGO_API.LS_IINFO_CONSTRAINTS_LNG Int 约束总数
4 LINGO_API.LS_IINFO_CONSTRAINTS_NONLINEAR_LNG Int 非线性约束数
5 LINGO_API.LS_IINFO_NONZEROS_LNG Int 非零矩阵元素总数
6 LINGO_API.LS_IINFO_NONZEROS_NONLINEAR_LNG Int 非线性非零矩阵元素数
7 LINGO_API.LS_IINFO_ITERATIONS_LNG Int 迭代次数
8 LINGO_API.LS_IINFO_BRANCHES_LNG Int 分支数(仅限 IP)
9 LINGO_API.LS_DINFO_SUMINF_LNG Double 不合格总和
10 LINGO_API.LS_DINFO_OBJECTIVE_LNG Double 目标值
11 LINGO_API.LS_DINFO_MIP_BOUND_LNG Double 目标边界(仅限 IP)
12 LINGO_API.LS_DINFO_MIP_BEST_OBJECTIVE_LNG Double 目前找到的最佳目标值(仅限 IP)
输出参数:
- errorCode: 一个整数,成功为 0,否则请参见 LINGO 用户手册了解解释错误代码的详细信息。
- data: 调用 LSgetCallbackInfoLng 的结果的标量值。
下面是求解器回调函数的模板。输入必须匹配模板,因为 LINGO API 将按此顺序发送和接收数据。
function ErrorCb(env, udata, nErrorCode, errorString)
% 你的代码
end
输入参数:
- env: 表示 LINGO 模型环境指针的 Long Long Int。
- udata: LINGO_Model 对象的可选 udata 属性。如果在调用 solve 之前未设置 udata 且设置了求解器回调,则 udata 将是一个空结构体。
- nErrorCode: 对应于 errorString 的 int32 值。LINGO 错误代码的列表可以在 LINGO 手册的附录中找到。
- errorString: 可打印到控制台的字符字符串错误消息。
回调示例
下面是一个求解器回调函数,当模型可行时,在每次新迭代时打印目标值。
matlab
function [flag, udata] = SolverCb(env, reserved, udata)
atol = 0.0005;
[errorCode, niter] = LINGO_API.LSgetCallbackInfoLng(env, ...
LINGO_API.LS_IINFO_ITERATIONS_LNG);
[errorCode, sumInf] = LINGO_API.LSgetCallbackInfoLng(env, ...
LINGO_API.LS_DINFO_SUMINF_LNG);
if udata.nIter < niter && abs(sumInf) < atol
[errorCode, objVal] = LINGO_API.LSgetCallbackInfoLng(env, ...
LINGO_API.LS_DINFO_OBJECTIVE_LNG);
udata.nIter = niter;
fprintf("====> \t Objval: %5.4f \n", objVal);
end
flag = int32(0);
end
下面是一个错误回调函数,如果调用它,则打印错误代码和字符串。
matlab
function ErrorCb(env, udata, nErrorCode, errorString)
fprintf("Error code: %d\n", nErrorCode);
fprintf("Error string: %s\n", errorString);
end
仅供个人学习使用