求解整数规划问题的割平面法和分支定界法

news2024/11/16 21:59:38

文章目录

  • 整数规划
  • 割平面法
  • 分支定界法
  • 代码实现

整数规划

整数规划问题是优化变量必须取整数值的线性或非线性规划问题,不过,在大多数情况下,整数规划问题指的是整数线性规划问题。

其数学模型为
m i n f ( x ) = c T x s.t A x = b x ≥ 0 x i ∈ I , i ∈ I ⊂ { 1 , 2 , . . . , n } min \quad f(\pmb x)=\pmb c^T\pmb x \\ \text{s.t} \quad \pmb A\pmb x=\pmb b \\ \pmb x ≥ 0\\ x_i \in I, i\in I \subset\{1,2,...,n\} minf(x)=cTxs.tAx=bx0xiI,iI{1,2,...,n}
特别地,如果 I = { 0 , 1 } I = \{0, 1\} I={0,1},上述模型也被称为0-1规划问题。

相比此前已经介绍的线性规划问题,整数规划问题其实就是多了组整数约束。鉴于两者如此紧密的关系,如下所示的线性规划问题被称为整数规划问题的松弛问题。
m i n f ( x ) = c T x s.t A x = b x ≥ 0 min \quad f(\pmb x)=\pmb c^T\pmb x \\ \text{s.t} \quad \pmb A\pmb x=\pmb b \\ \pmb x ≥ 0 minf(x)=cTxs.tAx=bx0

虽然看起来只是优化变量多了组整数条件的约束,但是在理论上,整数规划问题的求解已经不再是多项式复杂度了。

目前最常用的整数规划问题求解算法有两个:割平面法和分支定界法。不用被名字吓到,它们的本质都只是在单纯形法之外再额外增加一些算法逻辑,从而保证可以取到整数解。而这些算法逻辑,更像是算法框架,通过简单的实例就能描述清楚其背后的设计思想。

割平面法

本节通过求解如下的一个整数规划问题,来说明割平面法的算法原理。
m i n z = − 5 x 1 − 8 x 2 s.t x 1 + x 2 + x 3 = 6 5 x 1 + 9 x 2 + x 4 = 45 x 1 , x 2 , x 3 , x 4 ≥ 0 , 且只能取整数 min \quad z= -5x_1-8x_2 \\ \text{s.t} \quad x_1+x_2+x_3=6 \\ \nonumber 5x_1+9x_2+x_4=45 \\ \nonumber x_1,x_2,x_3,x_4≥0,且只能取整数 minz=5x18x2s.tx1+x2+x3=65x1+9x2+x4=45x1,x2,x3,x40,且只能取整数
首先计算其对应的松弛问题,得到最优解为
x 1 = 9 / 4 , x 2 = 15 / 4 x_1=9/4,x_2=15/4 x1=9/4,x2=15/4
下图中,A点即为最优解。显然,该解并不满足优化变量为整数的约束。


此时,割平面法的思路是:先把A点附近的非整数区域从可行域中切掉,然后再重新计算最优解。“切”的数学描述可以表达为:给松弛问题增加一个约束。本实例中,约束的表达式为
0.75 x 3 + 0.25 x 4 ≥ 0.75 0.75x_3+0.25x_4≥0.75 0.75x3+0.25x40.75
增加约束后,可行域如下图所示,重新求解得到最优解为
x 1 = 0 , x 2 = 5 x_1=0,x_2=5 x1=0,x2=5
该解虽然是求解松弛问题得到的最优解,但由于也满足整数条件的约束,所以也自然是原整数规划的最优解。

现在唯一的问题就只有:如何得到新增的约束表达式?接下来详细阐述。

切割前,最优解对应的单纯形表如下所示。单纯形表是基于单纯形法得来的,这篇文章给予了详细说明。本文不单开章节描述单纯形表的创建和迭代过程,主要是因为在实际应用时并不需要这些。

-5-800
C_bbx_1x_2x_3x_4
-5x_19/4109/4-1/4
-8x_215/401-5/41/4

从单纯形表的 x 2 x_2 x2那一行,可知
15 4 = 0 x 1 + 1 x 2 − 5 4 x 3 + 1 4 x 4 \frac{15}{4}=0x_1+1x_2-\frac{5}{4}x_3+\frac{1}{4}x_4 415=0x1+1x245x3+41x4
将系数的整数部分和小数部分拆开,可得
3 + 3 4 = ( 0 + 0 ) x 1 + ( 1 + 0 ) x 2 + ( − 2 + 3 4 ) x 3 + ( 0 + 1 4 ) x 4 3+\frac{3}{4}=(0+0)x_1+(1+0)x_2+(-2+\frac{3}{4})x_3+(0+\frac{1}{4})x_4 3+43=(0+0)x1+(1+0)x2+(2+43)x3+(0+41)x4

合并整数和小数部分
( 0 x 1 + 1 x 2 − 2 x 3 + 0 x 4 − 3 ) + ( 0 x 1 + 0 x 2 + 3 4 x 3 + 1 4 x 4 ) = 3 4 (0x_1+1x_2-2x_3+0x_4-3)+(0x_1+0x_2+\frac{3}{4}x_3+\frac{1}{4}x_4)=\frac{3}{4} (0x1+1x22x3+0x43)+(0x1+0x2+43x3+41x4)=43

等式左边第一项为整数部分,而等式右边为 [ 0 , 1 ] [0,1] [0,1]的小数,所以等式左边第二项的小数部分必然大于等于右边的值,即
( 0 x 1 + 0 x 2 + 3 4 x 3 + 1 4 x 4 ) ≥ 3 4 (0x_1+0x_2+\frac{3}{4}x_3+\frac{1}{4}x_4)≥\frac{3}{4} (0x1+0x2+43x3+41x4)43
该式即刚刚我们要添加的约束。

当然了,从图上可以看出,横纵坐标是 x 1 , x 2 x_1,x_2 x1,x2,但是约束条件是关于 x 3 , x 4 x_3,x_4 x3,x4,所以要做可视化的话,还需要转换一下
x 3 = 6 − x 1 − x 2 , x 4 = 45 − 5 x 1 − 9 x 2 x_3=6-x_1-x_2, \quad x_4 = 45 - 5x_1 - 9x_2 x3=6x1x2,x4=455x19x2
然后代入新添加的约束,变为
2 x 1 + 3 x 2 ≤ 15 2x_1+3x_2≤15 2x1+3x215
这样就可以画出如上所示的图了。

至于为什么要选择 x 2 x_2 x2那一行来构造新的约束,这主要是因为,有经验表明,使用小数部分最大的那一行来构造约束,收敛会更快。

分支定界法

相比割平面法,分枝定界法的思路更容易理解。

以如下的实例为例:
m i n f ( x ) = − 10 x 1 − 20 x 2 s.t 5 x 1 + 8 x 2 ≤ 60 x 1 ≤ 8 x 2 ≤ 4 x 1 , x 2 ≥ 0 , 且只能取整数 min \quad f(\pmb x)= -10x_1-20x_2 \\ \text{s.t} \quad 5x_1+8x_2≤60 \\ x_1≤8 \\ x_2≤4 \\ x_1,x_2≥0,且只能取整数 minf(x)=10x120x2s.t5x1+8x260x18x24x1,x20,且只能取整数

(1) 定义P为原整数规划问题,P0为其对应的松弛问题,最优解为
x 0 = ( 5.6 , 4 ) , f 0 = − 136 \pmb x_0=(5.6,4),f_0=-136 x0=(5.6,4),f0=136
由于 x 0 \pmb x_0 x0不满足整数约束,所以该解并不是P的最优解。但是P的最优解 f ∗ f^\ast f肯定不会低于P0的最优解,所以 f 0 f_0 f0可以作为P的下界
f l b = − 136 f_{lb}=-136 flb=136

此外,我们很容易发现, x = ( 0 , 0 ) \pmb x=(0,0) x=(0,0)是P的一个可行解,此时 f = 0 f=0 f=0,P的最优解 f ∗ f^\ast f不会高于该值,所以P的上界是
f u b = 0 f_{ub}=0 fub=0

(2) 在P0的最优解中,由于 x 1 = 5.6 x_1=5.6 x1=5.6,引入两个互斥的约束条件:
x 1 ≤ 5 , x 1 ≥ 6 x_1≤5,x_1≥6 x15,x16
将这两个约束分别加入P中,得到子问题P1和P2。显然,P的最优解和P1、P2最优解的更小者相同。

求解P1对应的松弛问题,最优解为
x 1 = ( 5 , 4 ) , f 1 = − 130 \pmb x_1=(5,4),f_1=-130 x1=(5,4),f1=130
由于 x 1 \pmb x_1 x1为整数解,所以也是P1的最优解,上界 f u b f_{ub} fub可以修改为
f u b = f 1 = − 130 f_{ub}=f_1=-130 fub=f1=130
由于P1已经得到整数最优解,所以P1不需要再继续被分支。

求解P2对应的松弛问题,最优解为
x 2 = ( 6 , 3.75 ) , f 2 = − 135 \pmb x_2=(6,3.75),f_2=-135 x2=(6,3.75),f2=135
x 2 \pmb x_2 x2不满足整数条件,因此不是P2的最优解,但是 f ∗ f^\ast f不会低于 f 2 f_2 f2,所以可以更新下界
f l b = − 135 f_{lb}=-135 flb=135

(3) 在P2的最优解中,由于 x 2 = 3.75 x_2=3.75 x2=3.75,继续引入两个互斥的约束条件
x 2 ≤ 3 , x 2 ≥ 4 x_2≤3,x_2≥4 x23,x24
将这两个约束分别加入P2中,得到子问题P3和P4。

先求解P4对应的松弛问题,无可行解,所以可以停止分枝。

再求解P3对应的松弛问题,最优解为
x 3 = ( 7.2 , 3 ) , f 3 = − 132 \pmb x_3=(7.2,3),f_3=-132 x3=(7.2,3),f3=132
x 3 \pmb x_3 x3不满足整数条件,因此不是P3的最优解,但是 f ∗ f^\ast f不会低于 f 3 f_3 f3,所以可以继续更新下界
f l b = − 132 f_{lb}=-132 flb=132

(4) 在P3的最优解中,由于 x 1 = 7.2 x_1=7.2 x1=7.2,继续引入两个互斥的约束条件
x 1 ≤ 7 , x 1 ≥ 8 x_1≤7,x_1≥8 x17,x18
将这两个约束分别加入P3中,得到子问题P5和P6。

求解P5对应的松弛问题,最优解为
x 5 = ( 7 , 3 ) , f 5 = − 130 \pmb x_5=(7,3),f_5=-130 x5=(7,3),f5=130
由于 x 5 \pmb x_5 x5为整数解,所以也是P5的最优解,上界 f u b f_{ub} fub可以修改为
f ‾ = f 5 = − 130 \overline f=f_5=-130 f=f5=130
此时,P5不需要再继续被分支。

求解P6对应的松弛问题,最优解为
x 6 = ( 8 , 2.5 ) , f 6 = − 130 \pmb x_6=(8,2.5),f_6=-130 x6=(8,2.5),f6=130
x 6 \pmb x_6 x6不满足整数条件,但是 f 6 f_6 f6并不小于当前上界 f u b f_{ub} fub,所以该分支是“枯枝”,需要剪枝。

结合P5和P6,下界可以更新为
f l b = − 130 f_{lb}=-130 flb=130

此时,我们发现
f u b = f l b = − 130 f_{ub}=f_{lb}=-130 fub=flb=130
所以该问题的最优解为
x 1 = ( 5 , 4 ) 或 x 5 = ( 7 , 3 ) \pmb x_1=(5,4)或\pmb x_5=(7,3) x1=(5,4)x5=(7,3)
对应的目标函数值为
f ∗ = − 130 f^\ast=-130 f=130

分支定界的全过程可以参考下图。

总的来说,割平面法和分支定界法都是先计算原问题对应的松弛问题,然后判断松弛问题的最优解是否也满足整数约束,如果满足,那么皆大欢喜;反之,割平面法会通过增加约束的方式来改进松弛问题的可行域,以期达到松弛问题最优解亦为原问题最优解的目标;而分支定界法则利用分解技术,将原问题分解为若干个子问题并分别计算,然后基于子问题的求解结果持续更新原问题的上下界,直至两者相等。

代码实现

虽然割平面法和分支定界法的步骤看起来挺多的,但好在,求解器已经帮我们做好了集成的工作,所以我们可以直接调用现成的求解器来求解所遇到的整数规划问题。

基于Python调用ortools求解整数规划问题的代码,和此前介绍的线性规划代码的唯一不同点在于:整数规划中优化变量的定义是solver.IntVar,而线性规划中的定义方式是solver.NumVar。

以下是上一节整数规划问题的求解代码。

from ortools.linear_solver import pywraplp


if __name__ == '__main__':
    # 声明ortools求解器,使用SCIP算法
    solver = pywraplp.Solver.CreateSolver('SCIP')

    # 优化变量
    x1 = solver.IntVar(0, 8, 'x1')
    x2 = solver.IntVar(0, 4., 'x2')

    # 目标函数
    solver.Minimize(-10 * x1 - 20 * x2)

    # 约束条件
    solver.Add(5 * x1 + 8 * x2 <= 60)

    # 模型求解
    status = solver.Solve()

    # 模型求解成功, 打印结果
    if status == pywraplp.Solver.OPTIMAL:
        # 变量最优解
        print('x1: {}, x2: {}'.format(x1.solution_value(), x2.solution_value()))

        # 最优目标函数值
        print('best_f =', solver.Objective().Value())

    else:
        print('not converge.')

运行代码后,可以得到最优解如下。显然,该解和上一节推演的结果是一致的。

x1: 5.0, x2: 4.0
best_f = -129.99999999999997

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/936558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

opencv的haarcascade_frontalface_default.xml等文件

文章目录 GitHub下载在安装好的OpenCV文件夹下寻找opencv-python中获取 GitHub下载 下载地址&#xff1a;https://github.com/opencv/opencv/tree/master/data/haarcascades 在安装好的OpenCV文件夹下寻找 路径如下&#xff1a; 你安装的opencv路径\OpenCV\opencv\build\et…

亮点!视频云存储/安防监控视频智能分析平台睡岗离岗检测

在生产过程中&#xff0c;未经领导允许的擅自离岗、睡岗会带来很多的潜在危害。TSINGSEE青犀推出的视频云存储/安防监控视频智能分析平台得睡岗离岗检测根据AI视频分析技术建立人工智能算法&#xff0c;对视频画面展开分析与识别。自动识别出人员睡岗、离岗、玩手机与抽烟等动作…

十六、pikachu之SSRF

文章目录 1、SSRF概述2、SSRF&#xff08;URL&#xff09;3、SSRF&#xff08;file_get_content&#xff09; 1、SSRF概述 SSRF(Server-Side Request Forgery&#xff1a;服务器端请求伪造)&#xff1a;其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能&…

c++ qt--线程(一)(第八部分)

c qt–线程&#xff08;一&#xff09;&#xff08;第八部分&#xff09; 一.进程&#xff08;Process&#xff09; 在任务管理器中的进程页下&#xff0c;可以看到进程&#xff0c;任务管理器将进程分为了三类&#xff0c;应用、后台进程、window进程 应用&#xff1a; 打开…

MyBatis-Plus 总结

MyBatis-Plus简介 官网&#xff1a;https://baomidou.com/ GitHub&#xff1a;https://github.com/baomidou/mybatis-plus Gitee&#xff1a;https://gitee.com/baomidou/mybatis-plus 简介 MyBatis-Plus &#xff08;简称 MP&#xff09;是一个 MyBatis的增强工具&#x…

【C++入门到精通】C++入门 —— 多态(抽象类和虚函数的魅力)

阅读导航 前言一、多态的概念1. 概念2. 多态的特点 二、多态的定义及实现1. 多态的构成条件2. 虚函数3. 虚函数的重写⭕虚函数重写的两个例外1.协变(基类与派生类虚函数返回值类型不同)2.析构函数的重写(基类与派生类析构函数的名字不同) 4. override 和 final&#xff08;C11 …

SLAM从入门到精通(开始篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多同学喜欢学习linux&#xff0c;但是他们只是把linux当成是一个嵌入式技术在学习&#xff0c;而不是当成工具在使用。平时&#xff0c;要么是自…

appium+python自动化测试

获取APP的包名 1、aapt即Android Asset Packaging Tool&#xff0c;在SDK的build-tools目录下。该工具可以查看apk包名和launcherActivity 2、在android-sdk里面双击SDK-manager,下载buidl-tools 3、勾选build-tools&#xff0c;随便选一个版本&#xff0c;我这里选的是24的版…

YOLOv5、v8改进:CrissCrossAttention注意力机制

目录 1.简介 2. yolov5添加方法&#xff1a; 2.1common.py构建CrissCrossAttention模块 2.2yolo.py中注册 CrissCrossAttention模块 2.3修改yaml文件。 1.简介 这是ICCV2019的用于语义分割的论文&#xff0c;可以说和CVPR2019的DANet遥相呼应。 和DANet一样&#xff0c;…

DBeaver的安装和使用:windows版

DBeaver官网下载地址&#xff1a;https://dbeaver.io/download/ 下载完成后&#xff0c; 进入傻瓜式安装&#xff1a; 这里会进入重复界面&#xff0c;一样点击下一步即可 选择安装目录&#xff0c;尽量不要选C盘&#xff0c; 我的电脑只有c盘&#xff0c; 没办法 等待安装完成…

linux操作系统的权限的深入学习(未完)

1.Linux权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受限制 普通用户&#xff1a;在linux下做有限的事情。 超级用户的命令提示符是“#”&#xff0c;普通用户…

MVSNet 和 PatchMatchNet 的DTU数据集 几个不同之处 一定要注意

文章目录 1 测试集 数据加载不同2 训练集 数量 分辨率不同 1 测试集 数据加载不同 1.MVSNet 的DTU测试数据集和PatchmatchNet测试数据集不一样&#xff1b; 区别在于数据加载&#xff0c;前者 cams文件最后是最小深度和间隔&#xff0c;后者是最小深度和最大深度。 2 训练集 …

layui框架学习(41:表单模块)

之前的文章《layui框架学习》14-16中介绍了通过预设类及部分layui属性设置表单的外观样式&#xff0c;layui中还提供有表单模块以对表单元素进行各类动态化渲染和相关操作&#xff0c;本文学习并记录表单模块form的常用属性、函数及事件的用法&#xff08;如果内容已在之前文章…

时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测

时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测 目录 时序预测 | MATLAB实现SSA-XGBoost(麻雀算法优化极限梯度提升树)时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-XGBoost时间序列预测&#xff0c;麻…

VS警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

1、问题 Microsoft visual studio 2019跑仿真的时候出现该警告&#xff0c;在高级保存选项设置编码为Unicode(UTF-8 无签名)还是会有该警告。 2、解决方法 右键项目&#xff0c;打开属性设置&#xff0c;选中&#xff1a;工程 -> 右键选择"属性" -> C/C ->…

JSON文件读写教程【jsoncpp源码编译】【结尾附三方库下载链接】

目录 1 数据下载(jsoncpp源码)2 文件编译3 测试用例4 下载链接:内容: JSON文件的读取与保存可以使用jsoncpp库来实现,这里介绍该库的下载及编译方法。 1 数据下载(jsoncpp源码) 数据下载:Github地址 图1 github源码示意图 2 文件编译 2.1 点击Download ZIP,下载源码。 …

大数据分析与AI在农业领域的应用

文章目录 数据采集与监测数据分析与预测个性化管理与优化决策支持系统结合物联网技术优势与前景 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;Java知识介绍 ✨文章内容&a…

使用ChatGPT给Python代码写单元测试

先写一个简单的python函数&#xff0c;找chatgpt写单元测试&#xff1a; 有一个python函数&#xff0c;请帮忙写单元测试&#xff0c;函数长这样&#xff1a; def test2(a: list, b: list) -> float:"""计算两个坐标的距离:param a list 格式如&#xff1a…

记一次蓝屏日志

记一次Win 蓝屏日志&#xff1a; &#x1f4f2;引&#xff1a; 虽然说&#xff0c;我是一个在职两年半的程序员&#xff0c;但是对于这个问题其实也和大部分人一样&#xff0c;一脸懵逼&#x1f916; 那是一个风和日丽的早上&#xff0c;w开开心心去上班摸鱼&#x1f41f;&a…

LiteOS qemu realview-pbx-a9 环境搭建与运行

前言 最近打算移植搭建 一些常见的 RTOS 的 qemu 开发学习环境&#xff0c;当前 RT-Thread、FreeRTOS 已经成功运行 qemu&#xff0c;LiteOS 初步验证可以正常 运行 qemu realview-pbx-a9&#xff0c;这里做个记录 首先学习或者研究 RTOS&#xff0c;只是看内核源码&#xff0…