优化求解器介绍
Mindopt是一款高性能优化求解器,专为求解大规模数学规划问题,当前支持线性规划 (LP) 、混合整数线性规划 (MILP) 、非线性规划(QP、SDP)。其强大的算法旨在有效地找到符合规规则约束、目标值最优的最佳解决方案,使其成为运筹学必学工具,广泛用在电商互联网、金融、电力能源、工业制造、交通物流等领域。
MindOpt的调用方式
优化求解器通常可以通过多种方式调用,具体取决于求解器的接口。以下是调用MindOpt的方法:
- 编程语言接口:MindOpt提供了编程语言接口,可以直接在编程语言中调用求解器。接口支持的语言包括: Python、Java、C/C++、C#
- 建模语言:像AMPL, Pyomo,PuLP,JuMP, MindOpt APL(MAPL)等这样的建模语言支持直接构建优化模型,并且可以在后台调用不同的求解器,MAPL可以一行代码直接切换不同求解器。
- 命令行工具:可以通过命令行工具调用,这意味着可以在终端或脚本中直接运行求解器命令。
- Web服务:支持通过网页访问,免下载(云上建模求解平台)
- 直接将模型文件传递给求解器:能够读取特定格式的文件,比如MPS, LP,NL格式等。可以构建一个模型文件,然后直接传递给求解器。
在这些调用方式中,通常建模语言与编程语言是最最常见的。编程语言通常需要编写更多的代码来定义问题的数学模型,编写复杂的逻辑、数据处理、循环的方式更灵活,并且对优化工程的控制更精细,如设置参数、启发式、分支定界策略等等。
建模语言专门为构建和求解优化模型设计,它们提供了高层次的语法,以直观的方式定义模型,代码编写相对比较简洁,并且能够与多个后端求解器兼容,模型也更易于阅读和维护。
下面将展示编程与建模语言的调用方法。
调用方法
当前MindOpt优化求解器的最新版本为V1.1.1,可以支持将上述编程语言的数据文件在终端中用命令行的模式直接求解不需要打开各种编译器。下面将展示C#的调用方法,以及达摩院研发的代数建模语言MAPL的使用。
编程语言
使用C#的编程语言调用我们需要下载一个.NET SDK,版本为6.0~8.0,命令行模式调用求解方法如下:
cd <MDOHOME>\<VERSION>\examples\csharp
copy ReadMps.cs csproject
cd csproject
dotnet build
dotnet run ..\..\data\afiro.mps --framework netcoreapp7.0
调用 MindOpt C# API 读取优化问题模型文件并进行求解的示例如下:
using Mindopt;
namespace Example
{
public class ReadMps
{
public static void Main(string[] args)
{
if (args.Length != 1)
return;
/*------------------------------------------------------------------*/
/* Step 1. Create a model and change the parameters. */
/*------------------------------------------------------------------*/
/* Create an empty model. */
MDOEnv env = new MDOEnv();
MDOModel? model = null;
try
{
/*--------------------------------------------------------------*/
/* Step 2. Input model. */
/*--------------------------------------------------------------*/
/* Read model from file. */
model = new MDOModel(env, args[0]);
/*--------------------------------------------------------------*/
/* Step 3. Solve the problem and print the result. */
/*--------------------------------------------------------------*/
/* Solve the problem. */
model.Optimize();
/* Print the result. */
Console.WriteLine($"Obj value: {model.Get(MDO.DoubleAttr.ObjVal)}");
}
catch (MDOException e)
{
Console.WriteLine(e.Message);
}
finally
{
/* Dispose of model and environment */
if (model != null) model.Dispose();
env.Dispose();
}
}
}
}
建模语言
MindOpt APL(MAPL)建模求解示例:
clear model;#清除model,多次run的时候使用
option modelname model/diet; #方便与方法2的中间文件生成在同一个目录
print "-----------------建模---------------";
#--------------------------
# diet.mapl
# 该例子由《AMPL: A Modeling Language for Mathematical
# Programming》第二章的diet例子改编而来
set NUTR := { "A", "B1", "B2", "C" };
set FOOD := {"BEEF", "CHK", "FISH", "HAM", "MCH", "MTL", "SPG", "TUR"} ;
set F:= {"cost", "f_min", "f_max"};
set N:= {"n_min", "n_max"};
param data1[FOOD * F] :=
| "cost" , "f_min" , "f_max" |
|"BEEF" | 3.19 , 0 , 100 |
|"CHK" | 2.59 , 0 , 100 |
|"FISH" | 2.29 , 0 , 100 |
|"HAM" | 2.89 , 0 , 100 |
|"MCH" | 1.89 , 0 , 100 |
|"MTL" | 1.99 , 0 , 100 |
|"SPG" | 1.99 , 0 , 100 |
|"TUR" | 2.49 , 0 , 100 |;
param data2[NUTR * N] :=
| "n_min", "n_max"|
|"A" | 700, 10000 |
|"C" | 700, 10000 |
|"B1" | 700, 10000 |
|"B2" | 700, 10000 |;
param amt[FOOD * NUTR] :=
| "A", "C", "B1", "B2"|
|"BEEF" | 60, 20, 10, 15 |
|"CHK" | 8, 0, 20, 20 |
|"FISH" | 8, 10, 15, 10 |
|"HAM" | 0, 40, 35, 10 |
|"MCH" | 15, 35, 0, 15 |
|"MTL" | 70, 30, 15, 0 |
|"SPG" | 0, 50, 25, 15 |
|"TUR" | 60, 0, 15, 0 |;
var x[j in FOOD] >= data1[j, "f_min"] <= data1[j, "f_max"];
minimize Total_Cost: sum {j in FOOD} : data1[j, "cost"] * x[j];
subto Diet: forall {i in NUTR}
data2[i, "n_min"] <= sum {j in FOOD}: amt[j, i] * x[j] <= data2[i, "n_max"];
#------------------------------
print "-----------------用MindOpt求解---------------";
option solver mindopt; # (可选)指定求解用的求解器,默认是MindOpt
solve; # 求解
print "-----------------Display---------------";
display; # 展示结果
print "最低价格是:";
print sum {<j> in FOOD} data1[j, "cost"] * x[j];
结语
在实践中,选择哪一种方式取决于具体任务、开发者的专业背景以及项目需要。如果需要开发具有复杂业务逻辑或数据处理要求的应用程序,比较推荐编程语言调用。如果焦点是在快速开发和测试优化模型,或者需要在多个求解器之间轻松切换,推荐使用建模语言。