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

简介: MindOpt是达摩院决策智能实验室研究的一款优化求解器,能帮助做方案设计、生产方案优化、资源合理分配、辅助决策等。可以支持命令行、c、c++、java和python调用,目前求解算法实现了线性规划、混合整数线性规划、二次规划。

下文我们将讲述小编对线性规划的理解以及展示两个算例,和使用 MindOpt C 语言的 API 来建模以及求解 混合整数线性规划示例 中的问题。

(混合整数线性规划定义、算数例题都是与前文python语言的混合整数线性规划问题是一致的,已经阅读了前文可以忽略,直接点击目录进阶算例阅读建模优化代码。)


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


下载安装

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

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


混合整数线性规划

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

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

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

image.png

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



案例

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

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

image.png


数学算例

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

image.png

C语言+MindOpt代码实现

核心使用的几个APIs是:

MDO_CHECK_CALL(Mdo_createMdl(&model))

MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES))

MDO_CHECK_CALL(Mdo_addRow(model, 1.0, MDO_INFINITY, 4, row1_idx, row1_val, "c0"));
MDO_CHECK_CALL(Mdo_addRow(model, 1.0, 1.0,          3, row2_idx, row2_val, "c1"));

MDO_CHECK_CALL(Mdo_solveProb(model));
Mdo_displayResults(model);

#关于更多API的详细使用方式,请参考 C 接口函数

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

#include <stdio.h>
/*引入头文件*/
#include "Mindopt.h"

/* 检查返回码的宏 */
#define MDO_CHECK_CALL(MDO_CALL)                                    \
code = MDO_CALL;                                                \
if (code != MDO_OKAY)                                           \
{                                                               \
Mdo_explainResult(model, code, str);                        \
Mdo_freeMdl(&model);                                        \
fprintf(stderr, "===================================\n");   \
fprintf(stderr, "Error   : code <%d>\n", code);             \
fprintf(stderr, "Reason  : %s\n", str);                     \
fprintf(stderr, "===================================\n");   \
return (int)code;                                           \
}

int main(void)
{
    /* 变量 */
    char str[1024] = { "\0" };
    MdoMdl * model = NULL;
    MdoResult code = MDO_OKAY;
    MdoStatus status = MDO_UNKNOWN;

    const int    row1_idx[] = { 0,   1,   2,   3   };
    const double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
    const int    row2_idx[] = { 0,    2,   3   };
    const double row2_val[] = { 1.0, -1.0, 6.0 };

    /*------------------------------------------------------------------*/
    /* Step 1. 创建模型并更改参数。               */
    /*------------------------------------------------------------------*/
    /* 创建一个空模型。 */
    MDO_CHECK_CALL(Mdo_createMdl(&model));

    /*------------------------------------------------------------------*/
    /* Step 2. 输入模型。                                             */
    /*------------------------------------------------------------------*/
    /* 改成最小化问题。 */
    /*通过 Mdo_setIntAttr() 将目标函数设置为 最小化 */
    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));

    /* 添加变量。 */
    /*调用 Mdo_addCol() 来添加四个优化变量,定义其下界、上界、名称和类型*/
    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, 10.0,         1.0, 0, NULL, NULL, "x0", MDO_YES));
    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x1", MDO_YES));
    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x2", MDO_YES));
    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x3", MDO_NO));

    /* 添加约束。
     * 请注意,这里的非零元素是按行顺序输入的。
     *调用 Mdo_addRow() 来输入约束
*/
    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, MDO_INFINITY, 4, row1_idx, row1_val, "c0"));
    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, 1.0,          3, row2_idx, row2_val, "c1"));

    /*------------------------------------------------------------------*/
    /* Step 3. 解决问题并填充结果。               */
    /*------------------------------------------------------------------*/
    /* 调用 Mdo_solveProb() 求解优化问题,并通过 Mdo_displayResults() 查看优化结果 */
    MDO_CHECK_CALL(Mdo_solveProb(model));
    Mdo_displayResults(model);

    /*------------------------------------------------------------------*/
    /* Step 4. 释放模型。                                          */
    /*------------------------------------------------------------------*/
    /* 调用 Mdo_freeMdl() 来释放内存 */
    Mdo_freeMdl(&model);

    return (int)code;
}

MindOpt求解的结果

如何编译及运行MdoMiloEx1.c文件

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

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

c语言 windows系统运行mindopt.gif

/*linux和mac系统直接在命令行输入*/

cd <MDOHOME>/<VERSION>/examples/C
make -f Makefile all
./MdoMiloEx1

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

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.       /*分支切割方法*/
Original model: nrow = 2 ncol = 4 nnz = 7
Tolerance: primal = 1e-06 int = 1e-05 mipgap = 0.0001 mipgapAbs = 1e-06
Parallelism: root=1, tree=2
tree id 0 node 0 accept a new sol: obj 1 (heur) bnd vio 0 int vio 0 mipgap 1e+100
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.003s

Simplex method started.        /*单纯形法*/

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

            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
            0     5.55556e-01      0.0000e+00      0.0000e+00     0.03s    
Branch-and-cut method terminated. Time : 0.062s

Optimizer summary.   /*求解器最终选择的优化方法以及求解消耗的时间*/
 - Optimizer used     : Branch-and-cut method   /*分支和切割方法*/
 - Optimizer status   : OPTIMAL
 - Total time         : 0.087s

Solution summary.
 - Primal objective   : 1.0000000000e+00 /*目标函数最优解*/
 - Dual bound         : 5.5555555556e-01 

联系我们

钉钉:damodi

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

相关文章
|
缓存 JavaScript 前端开发
IDEA启动VUE前端项目
IDEA启动VUE前端项目操作流程
|
存储 云安全 运维
腾讯云认证云从业者考试系列 腾讯云从业者认证考试内容、范围、 学习资料
本文列举腾讯云从业者认证的考试范围、知识点、分数比例、教程学习地址、一些官方资料文档。
1292 0
腾讯云认证云从业者考试系列 腾讯云从业者认证考试内容、范围、 学习资料
|
3月前
|
Windows
这款免费Windows优化神器!只有5M电脑绿色工具!ZyperWin++下载安装教程
ZyperWin++是一款开源、轻量级的Windows系统优化工具,支持Win7至Win11,仅5MB,免安装。可加速开机、清理C盘、修复系统小毛病,由B站UP主开发,绿色免费,操作简单,轻松提升电脑性能。
1114 1
|
缓存 负载均衡 Java
Java分布式系统架构设计与实现
【4月更文挑战第2天】在快速发展的互联网时代,Java分布式系统成为应对复杂业务和高用户量的首选。通过服务化拆分、注册发现、负载均衡和缓存等技术,如Spring Cloud和Dubbo,开发者能构建高效、可靠、可扩展的系统。服务注册与发现确保服务间通信,负载均衡分配请求,分布式缓存如Redis提升性能。面对数据一致性和监控等挑战,Java提供工具解决,助力打造现代分布式应用。
865 2
Java分布式系统架构设计与实现
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
缓存 JavaScript 前端开发
没想到 Vue 中滥用 watch 危害这么大!吓得我连夜修改代码
没想到 Vue 中滥用 watch 危害这么大!吓得我连夜修改代码
|
Java 测试技术 Apache
《手把手教你》系列技巧篇(六十六)-java+ selenium自动化测试 - 读写excel文件 - 上篇(详细教程)
【6月更文挑战第7天】本文介绍了在Java自动化测试中如何操作Excel数据。文章提到了当测试数据存储在Excel文件时,可以使用Apache的POI库来读写Excel。POI提供了对OLE2(.xls)和OOXML(.xlsx)格式的支持,比JXL库功能更全面。文章还详细讲解了如何下载和添加POI库到项目中,以及准备测试用的Excel文件。最后,给出了一个简单的Java代码示例,演示如何读取Excel文件的内容。
224 1
|
机器学习/深度学习 数据挖掘 Python
潜力无限:Python与Gurobi合力解决无约束优化问题
潜力无限:Python与Gurobi合力解决无约束优化问题
608 0
|
达摩院 API C++
MindOpt--C++语言-对一个简单的混合整数规划问题建模求解
MindOpt是达摩院决策智能实验室研究的一款优化求解器,目前在优化求解线性规划问题这一功能上取得不错的成绩,希望大家能够帮我们多多打磨其他功能(混合整数线性规划、二次规划、半定规划目前都在公测),让我们的MindOpt在优化求解器这板块成为国产之光。
MindOpt--C++语言-对一个简单的混合整数规划问题建模求解
|
架构师 微服务
什么是软件架构?架构的本质是什么?
定义 ”架构是什么“ 是件非常困难的事情,不同的组织对于软件架构有不同的定义,每个人心中也有自身对于系统架构定义的认知。就好比我们无法百分之百表述模型而只能产出模型不同维度的视图,对架构进行完备的定义是不可能的。
350 4