Python语言如何使用MindOpt建模并求解混合整数线性规划问题

简介: MindOpt是一款高效的优化算法软件包,求解算法实现了线性规划(LP)、混合整数线性规划(MILP)、二次规划(QP),可以支持命令行、c、c++、java和python调用。接下来我们将发布一系列文章,讲述各个语言如何使用 MindOpt 来求解数学规划问题。

本篇文章是系列文章的第二篇,下文会分享小编个人对混合整数线性规划的定义,然后举一个例题,最后将对使用 MindOpt Python 语言的 API 来建模以及求解 混合整数线性规划问题示例 中的问题以及展示求解的结果。


MindOpt Python、C、C++语言求解LP、MILP、QP问题系列


安装

用户可以点这里下载安装MindOpt优化求解器,免费的。找不到安装步骤点这里

(官网https://opt.aliyun.com有更多信息等着您哟!)


混合整数线性规划

我个人认为混合整数线性规划线性规划的区别在于,线性规划求解目标函数最优值的时候,决策变量是连续的,即可以是整数也可以是小数,但混合整数线性规划可能会有一个或者多个变量必须为整数。

比如经典的背包问题:桌子上有一组物品,每个物品有自己的价值和重量,但是包的承重是有限的;我们要装什么物品,在包的重量承受范围内,包里总物品的价值最高?这个里面选择那个物品就是个整数,并不能是小数切开,比如一个吹风机不能切开只带一半走。

数学形式下的混合整数线性规划问题:

image.png


混合整数线性规划很多时候会更难求解。在求解的时候,可以用分支定界法、割平面法等,会切分成子问题调用线性规划(LP)求解模块。MindOpt在今年也发布了混合整数线性规划(MILP)的求解能力。接下来我会举个例子如何使用。



例子

和上篇 线性规划一样,我们对于混合线性规划问题示例 做一个假设,把它当作一个生活中实际的例子,而不是数学公式这么抽象。

假设工厂有一种原材料,可以生产多种零件毛坯,但每种零件的生产方式也有多种,每种生产零件的方式可以得到不同零件的毛坯数以及每种零件的需要量,但需要其中一种零件生产必需为整数,那么要怎么生产才能达到零件所需要的数量,所花费的原材料又最少。

image.png


数学算例

混合整数线性规划问题示例:

image.png

Python+MindOpt代码实现

核心使用的几个APIs是:

model=MdoModel()
model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
x.append(model.add_var(0.0,         10.0, 1.0, None, "x0", True))
model.add_cons(1.0, MDO_INFINITY, 1.0*x[0] +1.0*x[1] +2.0*x[2] +3.0*x[3], "c0")
model.solve_prob()
model.display_results()

下面是完整的例子,可复制存为test_MILP.py文件。

# 引入python包frommindoptpyimport*if__name__=="__main__":
MDO_INFINITY=MdoModel.get_infinity()
# Step 1.创建模型并更改参数。model=MdoModel()
try:
# Step 2. 输入模型。# 改为最小化问题。# 通过 mindoptpy.MdoModel.set_int_attr() 将目标函数设置为 最小化model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
# 添加变量。# 调用 mindoptpy.MdoModel.add_var() 来添加四个优化变量,# 定义其下界、上界、名称和类型x= []
x.append(model.add_var(0.0,         10.0, 1.0, None, "x0", True))
x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x1", True))
x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x2", True))
x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x3", False))
# 添加约束。# 注意这里的非零元素是按行顺序输入的。model.add_cons(1.0, MDO_INFINITY, 1.0*x[0] +1.0*x[1] +2.0*x[2] +3.0*x[3], "c0")
model.add_cons(1.0,          1.0, 1.0*x[0]              -1.0*x[2] +6.0*x[3], "c1")
# Step 3.  解决问题并填充结果。# 调用 mindoptpy.MdoModel.solve_prob() 求解优化问题,# 并用 mindoptpy.MdoModel.display_results() 来查看优化结果model.solve_prob()
model.display_results()
# 调用 mindoptpy.MdoModel.get_status() 来检查求解器的优化状态,# 并通过 mindoptpy.MdoModel.get_real_attr() 和 # mindoptpy.MdoVar.get_real_attr() 来获取目标值和最优解。status_code, status_msg=model.get_status()
ifstatus_msg=="OPTIMAL":
print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
print("Primal objective : {0}".format(round(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL), 2)))
forcurr_xinx:
print(" - x[{0}]          : {1}".format(curr_x.get_index(), round(curr_x.get_real_attr(MDO_REAL_ATTR.PRIMAL_SOLN), 2)))
else:
print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
exceptMdoErrorase:
print("Received Mindopt exception.")
print(" - Code          : {}".format(e.code))
print(" - Reason        : {}".format(e.message))
exceptExceptionase:
print("Received exception.")
print(" - Reason        : {}".format(e))
finally:
# Step 4. 释放模型。model.free_mdl()

MindOpt求解的结果

然后运行代码,如命令行中执行python test_MILP.py 后,得到求解的结果如下所示,#号后面是我添加的注释。

Modelsummary.
-Num. variables     : 4-Num. constraints   : 2-Num. nonzeros      : 7-Num. integervars. : 3-Boundrange        : [1.0e+00,1.0e+01]
-Objectiverange    : [1.0e+00,1.0e+00]
Branch-and-cutmethodstarted. #使用分支定界法Modelsummary.
-Num. variables     : 4-Num. constraints   : 2-Num. nonzeros      : 7-Boundrange        : [1.0e+00,1.0e+01]
-Objectiverange    : [1.0e+00,1.0e+00]
-Matrixrange       : [1.0e+00,6.0e+00]  
Presolverstarted.
Presolverterminated. Time : 0.000sSimplexmethodstarted. #使用了单纯形法IterationObjectiveDualInf.     PrimalInf.     Time00.00000e+000.0000e+001.3102e+000.00s25.55556e-010.0000e+000.0000e+000.00sPostsolverstarted.
Simplexmethodterminated. Time : 0.001s25.55556e-010.0000e+000.0000e+000.01s25.55556e-010.0000e+000.0000e+000.01s25.55556e-010.0000e+000.0000e+000.01s25.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01s05.55556e-010.0000e+000.0000e+000.01sBranch-and-cutmethodterminated. Time : 0.016sOptimizerterminatedwithanOPTIMALstatus (code1).
Primalobjective : 1.0-x[0]          : 1.0-x[1]          : -0.0#决策变量们的最佳取值,即X0取值为1,其他为0-x[2]          : -0.0-x[3]          : 0.0Optimizersummary.
-Optimizerused     : Branch-and-cutmethod-Optimizerstatus   : OPTIMAL-Totaltime         : 0.016sSolutionsummary.       Primalsolution#目标函数最优解,即目标最小值是1-Objective          : 1.0000000000e+00

联系我们

钉钉群号:32451444

邮箱地址:solver.damo@list.alibaba-inc.com

更多更新通知:https://solver.damo.alibaba.com

相关文章
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
113 2
|
2月前
|
存储 Go C语言
Python 的整数是怎么实现的?这篇文章告诉你答案
Python 的整数是怎么实现的?这篇文章告诉你答案
58 7
|
1月前
|
算法 安全 Go
Python与Go语言中的哈希算法实现及对比分析
Python与Go语言中的哈希算法实现及对比分析
40 0
|
3月前
|
JSON 数据格式 Python
python中有哪些常用语言成分?
Python作为一种广泛使用的编程语言,其语言成分丰富多样,涵盖了多个方面。
56 9
|
3月前
|
算法 Serverless Python
使用 Python 查找整数中的数字长度
【8月更文挑战第27天】
56 5
|
3月前
|
机器学习/深度学习 人工智能 文字识别
轻松识别文字,这款Python OCR库支持超过80种语言
轻松识别文字,这款Python OCR库支持超过80种语言
|
3月前
|
机器学习/深度学习 数据可视化 数据挖掘
为啥我敢说Python是数据分析界的扛把子语言?
为啥我敢说Python是数据分析界的扛把子语言?
|
4月前
|
存储 Python 容器
Python基础语法:变量和数据类型详解(整数、浮点数、字符串、布尔值)
变量和数据类型是Python编程的基础,理解这些概念对于编写高效和正确的代码至关重要。通过本文的介绍,希望你能对Python中的变量和常用数据类型有一个清晰的认识,并能够在实际编程中灵活运用这些知识。
142 13
|
3月前
|
Rust JavaScript Java
简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能
简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能
|
3月前
|
Python
【Leetcode刷题Python】343. 整数拆分
LeetCode 343题 "整数拆分" 的Python解决方案,使用动态规划算法来最大化正整数拆分为多个正整数之和的乘积。
27 0