MindOpt--C++语言-对一个简单的混合整数规划问题建模求解

简介: MindOpt是达摩院决策智能实验室研究的一款优化求解器,目前在优化求解线性规划问题这一功能上取得不错的成绩,希望大家能够帮我们多多打磨其他功能(混合整数线性规划、二次规划、半定规划目前都在公测),让我们的MindOpt在优化求解器这板块成为国产之光。

凌波微步是段誉所习得的上乘轻功功法,学习这门上乘轻功有那么一个约束条件,它需要对易经八卦等知识有了解,甚至可以说是精通。混合整数线性规划问题也有那么一点相似,那就是这个线性问题求解的结果需要有一个或者多个变量整数这么一个约束条件。下文我们将会重点讲述如何使用MindOpt C++ 语言的API来建模优化混合整数线性规划。


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


下载安装

用户可以点这里下载安装MindOpt优化求解器

开通算法服务控制台(免费的)

MindOpt的更多信息官网

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

image.png

定义

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

  • 不要小看只是多了一个为整数的约束,它会导致问题在很多时候会有更多的变数,这样计算起来就更加复杂。打一个简单的比喻,女朋友想吃你做的饭,那么你就在网上选菜,她会告诉你想吃什么(玉米啊、排骨啊、豆腐等等),然后给了你一百的资金,就这样你带着这些条件选择各种食材,但发现在一百块的条件下,最后想买点大葱时钱不够了,但大葱不可能切一半给你,这样你就得重新选择其他食材的数量完成订菜。
  • 还有经典的背包问题:桌子上有一组物品,每个物品有自己的价值和重量,但是包的承重是有限的;我们要装什么物品,在包的重量承受范围内,包里总物品的价值最高?这个里面选择那个物品就是个整数,并不能是小数切开,比如一个吹风机不能切开只带一半走。


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

数学算例

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

image.png

是不是看着数学算例很抽象?那么我们来举个例子带入:假设工厂有一种原材料,可以生产多种零件毛坯,但每种零件的生产方式也有多种,每种生产零件的方式可以得到不同零件的毛坯数以及每种零件的需要量,但需要其中一种零件生产必需为整数,我们要做的就是用MindOpt来帮助生产工人计算要怎么生产才能达到零件所需要的数量,所花费的原材料又最少。

MindOpt和C++下的建模优化

核心使用的几个APIs是:

MdoModel model;
model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);
model.addCons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0");
model.addCons(1.0, 1.0,          1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1");
model.solveProb();
model.displayResults();

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

#include <iostream>
#include <vector>
/*引入头文件*/
#include "MindoptCpp.h"
using namespace mindopt;
int main(void)
{
    /*------------------------------------------------------------------*/
    /* Step 1. 创建模型并更改参数。               */
    /*------------------------------------------------------------------*/
    /* 创建一个空模型 */
    MdoModel model;
    try 
        {
            /*------------------------------------------------------------------*/
            /* Step 2. 输入模型。.                                             */
            /*------------------------------------------------------------------*/
            /* 改为最小化问题 */
            /*通过 mindopt::MdoModel::setIntAttr() 将目标函数设置为 最小化*/ 
            model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);
            /* 添加变量 */
            /*调用 mindopt::MdoModel::addVar() 来添加四个优化变量,定义其下界、上界、名称和类型*/
            std::vector<MdoVar> x;
            x.push_back(model.addVar(0.0, 10.0,         1.0, "x0", MDO_YES));
            x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x1", MDO_YES));
            x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x2", MDO_YES));
            x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, "x3", MDO_NO));
            /* 添加约束 */
            /*通过 mindopt::MdoModel::addCons()来添加约束*/
            model.addCons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0");
            model.addCons(1.0, 1.0,          1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1");
            /*------------------------------------------------------------------*/
            /* Step 3. 解决问题并填充结果。              */
            /*------------------------------------------------------------------*/
            /* 调用 mindopt::MdoModel::solveProb() 求解优化问题,
               并通过 mindopt::MdoModel::displayResults() 查看优化结果 */
            model.solveProb();
            model.displayResults();
        }
    catch (MdoException & e)
        {
            std::cerr << "===================================" << std::endl;
            std::cerr << "Error   : code <" << e.getResult() << ">" << std::endl;
            std::cerr << "Reason  : " << model.explainResult(e.getResult()) << std::endl;
            std::cerr << "===================================" << std::endl;
            return static_cast<int>(e.getResult());
        }
    return static_cast<int>(MDO_OKAY);
}

MindOpt求解的结果

运行MdoMiloEx1.cpp文件的步骤

linux和Mac系统在命令行输入以下代码
cd <MDOHOME>/<VERSION>/examples/CPP
make -f Makefile all
./MdoMiloEx1

windows系统本例是在Visual Studio上运行,版本为2019

#运行方式与前文    一致,只需要修改文件就好;把MdoLoEx1.cpp换成MdoMiloEx1.cpp

C++.gif

如上文所述,运行MdoMiloEx1.cpp文件,得到求解的结果如下所示,/**/号里面是我添加的注释。

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.005s
Simplex method started.
    Iteration       Objective       Dual Inf.     Primal Inf.     Time
            0     0.00000e+00      0.0000e+00      1.3102e+00     0.04s
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.06s
Postsolver started.                      /*单纯形法开始*/
Simplex method terminated. Time : 0.051s
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.08s
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.09s
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.10s
            2     5.55556e-01      0.0000e+00      0.0000e+00     0.11s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.12s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.14s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.14s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.15s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.17s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.18s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.18s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.19s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.20s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.21s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.22s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.22s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.23s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.25s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.25s
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.26s
Branch-and-cut method terminated. Time : 0.567s
Optimizer summary.
 - Optimizer used     : Branch-and-cut method   /*显示最终使用分支切割方法*/
 - Optimizer status   : OPTIMAL
 - Total time         : 0.624s
Solution summary.       Primal solution
 - Objective          : 1.0000000000e+00    /*目标函数最优解*/

联系我们

钉钉群号:32451444

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

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


相关文章
|
11月前
|
存储 达摩院
「达摩院MindOpt」线性规划用于排程排程问题(02)
排产排程、原料采购、仓储存放等是制造业降本增效的关键问题。
「达摩院MindOpt」线性规划用于排程排程问题(02)
|
10月前
|
存储 达摩院
「达摩院MindOpt」线性规划用于排程排程问题(03)
比上一篇问题02中,我们只考虑了一次性的采购和生产计划,实际中的排产排程问题要更加复杂和精细。例如,我们要考虑未来三个月内采购和排产排程计划。其中,原材料每个月的采买价格均有不同,并且原材料购买后的存储也需要成本开销。在本节中,我们将考虑这样一个相对复杂的排产排程的决策问题。
「达摩院MindOpt」线性规划用于排程排程问题(03)
|
12月前
|
达摩院 调度
使用达摩院MindOpt优化交通调度_最大化通行量—线性规划问题
在数学规划中,网络流问题是指一类基于网络模型的流量分配问题。网络流问题的目标是在网络中分配资源,使得网络的流量满足一定的限制条件,并且使得某些目标函数最小或最大化。网络流问题通常涉及一个有向图,图中每个节点表示一个资源,每条边表示资源之间的关系。边上有一个容量值,表示该边上最多可以流动的资源数量。流量从源节点开始流出,经过一系列中间节点,最终到达汇节点。在这个过程中,需要遵守一定的流量守恒和容量限制条件。
|
12月前
|
存储 达摩院 供应链
混合整数线性规划-仓库选址问题-达摩院MindOpt
仓库选址问题是一个重要的运筹学问题,它涉及到在一个给定的地理区域中选择最佳的仓库位置以最小化总成本或者提高效率。仓库选址问题在现代物流和供应链管理中具有重要的应用,因为仓库的位置直接影响到货物的运输成本、交货时间和库存量等因素。
Python语言如何使用MindOpt建模并求解混合整数线性规划问题
MindOpt是一款高效的优化算法软件包,求解算法实现了线性规划(LP)、混合整数线性规划(MILP)、二次规划(QP),可以支持命令行、c、c++、java和python调用。接下来我们将发布一系列文章,讲述各个语言如何使用 MindOpt 来求解数学规划问题。
Python语言如何使用MindOpt建模并求解混合整数线性规划问题
|
达摩院 算法 API
如何吃,少花钱又营养丰富?可用MindOpt线性规划求解来决策
营养调配问题的的目标是利用优化模型来设定每日饮食菜单,在满足各类营养的需求同时更能优化总成本
如何吃,少花钱又营养丰富?可用MindOpt线性规划求解来决策
|
达摩院 API C语言
C语言如何使用MindOpt建模并求解线性规划问题
MindOpt是达摩院决策智能实验室研究的一款优化求解器,能帮助做方案设计、生产方案优化、资源合理分配、辅助决策等。可以支持命令行、c、c++、java和python调用,目前求解算法实现了线性规划、混合整数线性规划、二次规划。
C语言如何使用MindOpt建模并求解线性规划问题
|
达摩院 算法 Java
MindOpt也能使用C++ 来建模求解线性规划问题?
MindOpt是达摩院决策智能实验室研究的一款优化求解器,能帮助做方案设计、生产方案优化、资源合理分配、辅助决策等。可以支持命令行、c、c++、java和python调用,目前求解算法实现了线性规划、混合整数线性规划、二次规划。
MindOpt也能使用C++ 来建模求解线性规划问题?
|
达摩院 API C语言
C语言如何使用MindOpt建模并求解混合整数线性规划问题
MindOpt是达摩院决策智能实验室研究的一款优化求解器,能帮助做方案设计、生产方案优化、资源合理分配、辅助决策等。可以支持命令行、c、c++、java和python调用,目前求解算法实现了线性规划、混合整数线性规划、二次规划。
C语言如何使用MindOpt建模并求解混合整数线性规划问题
C++混合头文件实战——7-24 树种统计(25 分)
随着卫星成像技术的应用,自然资源研究机构可以识别每一棵树的种类。请编写程序帮助研究人员统计每种树的数量,计算每种树占总数的百分比。
244 0