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包

from mindoptpy import *


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()
        if status_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)))
            for curr_x in x:
                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))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        # Step 4. 释放模型。
        model.free_mdl()

MindOpt求解的结果

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

Model summary.
 - Num. variables     : 4
 - Num. constraints   : 2
 - Num. nonzeros      : 7
 - Num. integer vars. : 3
 - Bound range        : [1.0e+00,1.0e+01]
 - Objective range    : [1.0e+00,1.0e+00]

Branch-and-cut method started. #使用分支定界法
Model summary.
 - Num. variables     : 4
 - Num. constraints   : 2
 - Num. nonzeros      : 7
 - Bound range        : [1.0e+00,1.0e+01]
 - Objective range    : [1.0e+00,1.0e+00]
 - Matrix range       : [1.0e+00,6.0e+00]  

Presolver started.
Presolver terminated. Time : 0.000s

Simplex method started. #使用了单纯形法

    Iteration       Objective       Dual Inf.     Primal Inf.     Time
            0     0.00000e+00      0.0000e+00      1.3102e+00     0.00s    
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.00s    
Postsolver started.
Simplex method terminated. Time : 0.001s

            2     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.01s    
Branch-and-cut method terminated. Time : 0.016s

Optimizer terminated with an OPTIMAL status (code 1).
Primal objective : 1.0
 - x[0]          : 1.0
 - x[1]          : -0.0   #决策变量们的最佳取值,即X0取值为1,其他为0
 - x[2]          : -0.0
 - x[3]          : 0.0
Optimizer summary.
 - Optimizer used     : Branch-and-cut method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.016s

Solution summary.       Primal solution    #目标函数最优解,即目标最小值是1
 - Objective          : 1.0000000000e+00 

联系我们

钉钉:damodi

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

相关文章
|
15天前
|
数据可视化 算法 数据挖掘
Python量化投资实践:基于蒙特卡洛模拟的投资组合风险建模与分析
蒙特卡洛模拟是一种利用重复随机抽样解决确定性问题的计算方法,广泛应用于金融领域的不确定性建模和风险评估。本文介绍如何使用Python和EODHD API获取历史交易数据,通过模拟生成未来价格路径,分析投资风险与收益,包括VaR和CVaR计算,以辅助投资者制定合理决策。
63 15
|
3月前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1710 17
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
3月前
|
机器学习/深度学习 数据采集 算法
【BetterBench博士】2024华为杯C题:数据驱动下磁性元件的磁芯损耗建模 Python代码实现
本文介绍了2024年中国研究生数学建模竞赛C题的详细分析,涵盖数据预处理、特征提取、模型训练及评估等多个方面。通过对磁通密度数据的处理,提取关键特征并应用多种分类算法进行波形分类。此外,还探讨了斯坦麦茨方程及其温度修正模型的应用,分析了温度、励磁波形和磁芯材料对磁芯损耗的影响,并提出了优化磁芯损耗与传输磁能的方法。最后,提供了B站视频教程链接,供进一步学习参考。
204 6
【BetterBench博士】2024华为杯C题:数据驱动下磁性元件的磁芯损耗建模 Python代码实现
|
3月前
|
存储 Go C语言
Python 的整数是怎么实现的?这篇文章告诉你答案
Python 的整数是怎么实现的?这篇文章告诉你答案
72 7
|
2月前
|
开发者 Python
Python类和子类的小示例:建模农场
Python类和子类的小示例:建模农场
17 0
|
4月前
|
供应链 数据可视化 数据挖掘
【2023年第十一届泰迪杯数据挖掘挑战赛】B题:产品订单的数据分析与需求预测 建模及python代码详解 问题一
本文详细介绍了第十一届泰迪杯数据挖掘挑战赛B题的解决方案,涵盖了对产品订单数据的深入分析、多种因素对需求量影响的探讨,并建立了数学模型进行未来需求量的预测,同时提供了Python代码实现和结果可视化的方法。
156 3
【2023年第十一届泰迪杯数据挖掘挑战赛】B题:产品订单的数据分析与需求预测 建模及python代码详解 问题一
|
4月前
|
数据建模 大数据 数据库
【2023年4月美赛加赛】Y题:Understanding Used Sailboat Prices 建模思路、建模方案、数据来源、相关资料、Python代码
本文提供了2023年MCM问题Y的解题思路、建模方案、数据来源、相关资料以及Python代码,旨在建立数学模型解释二手帆船的挂牌价格,并分析地区对价格的影响,以及在香港(SAR)市场上的应用。
50 1
【2023年4月美赛加赛】Y题:Understanding Used Sailboat Prices 建模思路、建模方案、数据来源、相关资料、Python代码
|
4月前
|
算法 Serverless Python
使用 Python 查找整数中的数字长度
【8月更文挑战第27天】
86 5
|
4月前
|
机器学习/深度学习 搜索推荐 数据可视化
【2023年第十一届泰迪杯数据挖掘挑战赛】C题:泰迪内推平台招聘与求职双向推荐系统构建 建模及python代码详解 问题二
本文介绍了2023年第十一届泰迪杯数据挖掘挑战赛C题的解决方案,重点讲解了如何构建招聘与求职双向推荐系统的建模过程和Python代码实现,并对招聘信息和求职者信息进行了详细分析和画像构建。
91 1
|
4月前
|
机器学习/深度学习 数据采集 数据挖掘
【2023年第十一届泰迪杯数据挖掘挑战赛】B题:产品订单的数据分析与需求预测 建模及python代码详解 问题二
本文提供了第十一届泰迪杯数据挖掘挑战赛B题问题二的详细解题步骤,包括时间序列预测模型的建立、多元输入时间预测问题的分析、时间序列预测的建模步骤、改进模型的方法,以及使用Python进行SARIMA模型拟合和预测的具体实现过程。
119 1