MIP精确算法的关键——确定界

news2024/11/20 3:35:48

目录

1.界是什么?

2. 如何更新上下界

2.1 以分支定界为框架的一系列算法

 2.2 benders分解


MIP精确算法包含,分支定界、分支切割、分支定价还有benders分解等等。前者是以分支定界为框架的一类算法;后者是以分解为框架的一类算法。甚至还包括拉格朗日松弛等等,我觉得除了算法细则需要搞清楚外,更关键的是弄懂界。

因为拉格朗日算法目前不熟,所以下面我具体总结分支定界的一类算法和benders分解算法界的确定原则。

本篇以min问题为例。

1.界是什么?

界包含上界UB,和下界LB。

我们做启发式算法的时候,有时候会被审稿专家提一个问题,就是你这个算法质量没有保证,所以一般我们会提供一个下界作为参考。比如:调度问题中,不相关并行机问题,我们松弛为相同的机器,以工件j在所有机器的最小加工时间min_{i\in I}\left \{ p_{ij} \right \}为工件的加工时间\bar{p},然后叠加就可以得到一个总完工时间,这个就可以作为原问题的下界。

在精确算法中,我们会得到一个UB,和一个LB,不断提升LB,降低UB。当UB=LB的时候,我们就得到了最优解。换句话说,界和终止条件有关。

(1)UB是整数可行解,但我们降低UB的时候,就是找到更好可行解更新。

(2)LB是松弛解,像以分支定界为框架的一系列算法中,主要采用的是线性松弛解,因为约束减少,因此解的质量至少不差于(好于)原问题的解,原问题是min,不差于(好于)就是更小,即LB。

而拉格朗日松弛,采用的是不同于线性松弛的松弛方法,得到的LB更好,通常拉格朗日松弛的解≥线性松弛的解。

2. 如何更新上下界

当我们了解UB和LB了之后,下一个问题是:

(1)用什么来更新?以及

(2)更新的过程怎么保证不丢失信息,确保更新UB和LB之后得到的是精确最优解呢?

2.1 以分支定界为框架的一系列算法

先来说以分支定界为框架的一系列算法:

它的本质是隐枚举,通过剪支的操作来避免全枚举。剪支分为:不可行剪支(线性松弛后可行域变大了还不可行,那可行域是子集的原问题必定也不可行)、最优性剪支(已经是整数解了,没必要分支了)、和定界剪支(因为线性松弛后解更小,当线性松弛后解超过了UB,那肯定不松弛解更超过UB,也就是不会产生更好的解了)。

可以看到定界剪支与界(准确的说是LB)相关,以及我们在求解过程中需要不断更新,和比较UB和LB,因此界很重要。

编程的时候怎么实现呢?

我们需要定义一系列的界,包含全局UB&LB(上面说的都是这个);以及当前节点的UB&LB(为了比较和替换,也是为了更清晰的展示每个点的上下界信息);以及储存在每次迭代过程中UB&LB(比如我们想查看上下界怎么变化,就需要用到它,智能算法中显示全局解随迭代次数变化的迭代曲线一样的意思)。

总结一下,需要用到global_UB,global_LB;node.local_LB,node.local_UB,以及Global_UB_change,Global_LB_change。

后续我们需要对以上变量进行更新,具体的做法是:

(1)首先肯定是要预定义:

global_UB=正无穷,global_LB=原问题线性松弛的解;

node.local_LB=global_LB,node.local_UB=正无穷;

Global_UB_change=[],Global_LB_change = [].

(2)求解每一个叶子节点current_node,会得到它的解current_node.model.ObjVal。

(3)假如是整数解,且该解比之前可行解都好,即current_node.model.ObjVal<global_UB,那么用current_node.model.ObjVal替换global_UB;

假如不是整数解,即小数解,不需要进行任何操作。

# update the LB and UB
if (is_integer == True):
   feasible_sol_cnt += 1  # 整数可行解的计数
   # For integer solution node, update the LB and UB
   current_node.is_integer = True
   current_node.local_LB = current_node.model.ObjVal
   current_node.local_UB = current_node.model.ObjVal
   # if the solution is integer, update the UB of global and update the incumbent
   if (current_node.local_UB < global_UB):  # 整数可行解更优,更min,则更新上界,同时更新当前最好的整数可行解incumbent_node
       global_UB = current_node.local_UB
       incumbent_node = Node.deepcopy_node(current_node)

if (is_integer == False):
   # For integer solution node, update the LB and UB also
   current_node.is_integer = False
   current_node.local_UB = global_UB
   current_node.local_LB = current_node.model.ObjVal

(可以看到每个点current_node的下上界信息也进行了更新,是为了展示各个节点的上下界情况。整数节点,上下界相等,都为current_node.model.ObjVal;非整数节点,上界为global_UB,下界为本身(因为是松弛解))。

(4)因为我们在分支的时候,把所有的子节点(一系列模型)放在队列Queue中 ,因此我们探测这些叶子节点的信息,来更新全局下界(是所有叶子节点解的最小值)>>>>(是保证不缺失信息的关键)。

注意:上界UB可以用更好的可行解信息来代替,但是下界LB不能,下界LB要全部探测所有节点方可确定。

# update the global LB, explore all the leaf nodes
temp_global_LB = np.inf
for node in Queue:
    node.model.optimize()
    if (node.model.status == 2):
        if (node.model.ObjVal <= temp_global_LB and node.model.ObjVal <= global_UB):
            temp_global_LB = node.model.ObjVal  # 下界是剩余节点集合Q中节点对应的LP中obj的最小值

(5)更新全局LB和UB,更新界的迭代信息列表Global_UB_change,Global_LB_change

global_LB = temp_global_LB
Global_UB_change.append(global_UB)
Global_LB_change.append(global_LB)

可以看到,全局UB直接更新(出现好的就更新,类似于我们说的贪婪更新),而下界LB是探测所有。 然后把每次迭代过程中的全局UB和LB放在界的迭代列表Global_UB_change,Global_LB_change中,因为我们在先前已经比较过了,因此LB一定是增大(因为我们不断添加界,相当于可行域变小,所以即使探测所有节点,解一定是变大的,不会出现更小的情况),UB一定是减小的。

(6)当所有节点都探测完毕,别忘了再更新下全局上下界和界的迭代信息列表。

# all the nodes are explored, update the LB and UB
incumbent_node.model.optimize()
global_UB = incumbent_node.model.ObjVal
global_LB = global_UB
Gap = round(100 * (global_UB - global_LB) / global_LB, 2)
Global_UB_change.append(global_UB)
Global_LB_change.append(global_LB)

我们知道分支切割,和分支定价是在分支定界的基础上进行的,界的更新过程差不多。区别是分支数的样子。

 2.2 benders分解

benders分解的初衷是因为原模型中含有两类变量,复杂变量和简单变量。它们之间具有耦合关系,所以我们想的是把它们拆开,复杂变量和简单变量分开,分成两个问题/模型,即我们说的主问题和子问题。但分开后的两个模型之间要建立一定的联系,才能和原模型等价。具体的做法是加约束(可行割和最优割),即缺失的信息。也就是说原模型等价于主问题+一系列的割。这些割是不断添加的,因此benders分解被也称为行生成。

所以我们可以看到,benders分解的关键在于,如何分解为主问题和子问题。以及界是如何更新的。

本篇我们主要谈界的更新,benders算法中界主要和算法终止条件有关。以下谈具体思路。

假设复杂变量是y,简单变量是x。

(1)则主问题MP是只看y,无视/忽略x(x相关的信息,即x对y的影响反映在不断添加的割上),目标函数是min(fy+q),其中q是原始模型中目标函数min(fy+cx)中关于x的部分cx的下界;

(2)子问题SP是给了一个具体的y_bar后关于x的模型,目标函数是min(cx)。

以下是关于UB和LB的详细说明:

(1)因为子问题是给一个具体的y_bar后求解的得到x值的模型,因此该解必定是原问题的一个可行解,也就是子问题给出了一个上界UB=fy+Q(y)。

注:子问题的Q(y)其实子问题对偶问题的目标函数值。当子问题对偶问题最优,即子问题最优,目标函数值是相同的。

(2)再来考虑主问题,因为忽略了x,也就是对问题进行了松弛,并没有把x对y的影响全部加回来,即约束少,可行域变大(本质是松弛),因此解不弱于原来模型的解,即主问题给出了一个下界LB=fy+q。

(3)当上界UB=下界LB时,fy+Q(y)=fy+q,也就是Q(y)=q。因此判断原问题是否最优的方法是:查看主问题的q取值和子问题的Q(y)取值是否相同。

a) 当子问题最优时,即得到了一个可行解,UB=min{UB, fy+Q(y)};

b) 添加割后求解主问题,得到的就是LB。

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

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

相关文章

Springboot学习笔记——1

Springboot学习笔记——1 一、快速上手Springboot1.1、Springboot入门程序开发1.1.1、IDEA创建Springboot项目1.1.2、官网创建Springboot项目1.1.3、阿里云创建Springboot项目1.1.4、手工制作Springboot项目 1.2、隐藏文件或文件夹1.3、入门案例解析1.3.1、parent1.3.2、starte…

嵌入式软件架构基础设施设计方法

大家好&#xff0c;今天分享一篇嵌入式软件架构设计相关的文章。 软件架构这东西&#xff0c;众说纷纭&#xff0c;各有观点。在我看来&#xff0c;软件架构是软件系统的基本结构&#xff0c;包含其组件、组件之间的关系、组件设计与演进的规则&#xff0c;以及体现这些规则的基…

Nginx高级 第一部分:扩容

Nginx高级 第一部分&#xff1a;扩容 通过扩容提升整体吞吐量 1.单机垂直扩容&#xff1a;硬件资源增加 云服务资源增加 整机&#xff1a;IBM、浪潮、DELL、HP等 CPU/主板&#xff1a;更新到主流 网卡&#xff1a;10G/40G网卡 磁盘&#xff1a;SAS(SCSI) HDD&#xff08;机械…

【C/C++笔试练习】——常量指针和指针常量、结构体内存分配、统计输入的字母个数、排序子序列、倒置字符串

文章目录 C/C笔试练习1.常量指针和指针常量&#xff08;1&#xff09;常量指针和指针常量的定义&#xff08;2&#xff09;判别常量指针和指针常量&#xff08;3&#xff09;常量指针和指针常量的特性 2.结构体内存分配&#xff08;4&#xff09;计算结构体大小&#xff08;5&a…

【计算机】CPU,芯片以及操作系统概述

1.CPU 什么是CPU? CPU&#xff08;Central Processing Unit&#xff09;是计算机系统的运算和控制核心&#xff0c;是信息处理、程序运行的最终执行单元&#xff0c;相当于系统的“大脑”。 CPU的工作流程&#xff1f; CPU 的工作流程分为以下 5 个阶段&#xff1a;取指令…

C++ -- 学习系列 关联式容器 set 与 map

一 关联式容器是什么&#xff1f; c 中有两种容器类型&#xff1a;关联式容器与序列式容器&#xff08;顺序容器&#xff09; 关联式中的容器是按照关键字来存储与访问的&#xff0c;序列式容器&#xff08;顺序容器&#xff09;则是元素在容器中的相对位置来存储与访问的。…

C++标准模板(STL)- 类型支持 ()

对象、引用、函数&#xff08;包括函数模板特化&#xff09;和表达式具有称为类型的性质&#xff0c;它限制了对这些实体所容许的操作&#xff0c;并给原本寻常的位序列提供了语义含义。 附加性基本类型及宏 实现定义的空指针常量 NULL 定义于头文件 <clocale> 定义于…

2.类与对象 拜访对象村

2.1 椅子大战 在图形接口画出正方形、圆形与三角形。当用户选点图形时&#xff0c;图形需要顺时针转360并依据形状的不同播放播放不同的AIF文件。胜者可以坐上名贵宝椅。 面向过程&#xff1a; rotate(shapeNum) {//旋转360 } playSound(shapeNum) {//查询播放哪个AIF文件//播…

嵌入式Linux应用开发-驱动大全-同步与互斥②

嵌入式Linux应用开发-驱动大全-同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1.3.4.1…

pyqt5使用经验总结

pyqt5环境配置注意&#xff1a; 安装pyqt5 pip install PyQt5 pyqt5-tools 环境变量-创建变量名&#xff1a; 健名&#xff1a;QT_QPA_PLATFORM_PLUGIN_PATH 值为&#xff1a;Lib\site-packages\PyQt5\Qt\plugins pyqt5经验2&#xff1a; 使用designer.exe进行设计&#xff1…

Maven - MacOS 快速安装

配置信息 Maven 版本&#xff1a;3.6.3Maven 地址&#xff1a;Index of /dist/maven/maven-3IDEA&#xff1a;2023 Tips&#xff1a;Maven 版本最好不要超过 3.8.0&#xff0c;最新版 Maven 会不兼容一些配置信息。上面的 Maven 地址里可以选择自己想下载的版本&#xff08;这…

【源码】hamcrest 源码阅读及空对象模式、模板方法模式的应用

文章目录 前言1. 类图概览2. 源码阅读2.1 抽象类 BaseMatcher2.1 接口 Description提炼模式&#xff1a;空对象模式 2. 接口 Description 与 SelfDescribing 配合使用提炼模式 模板方法 后记 前言 hamcrest &#xff0c;一个被多个测试框架依赖的包。听说 hamcrest 的源码质量…

【maven】idea中基于maven-webapp骨架创建的web.xml问题

IDEA中基于maven-webapp骨架创建的web工程&#xff0c;默认的web.xml是这样的。 <!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name…

go语法入门2

字符串 使用双引号或反引号引起来的任意个字符。它是字面常量。 func main() {var a "abc\n测试" // \n换行fmt.Println(a) } abc 测试func main() {var a "abc\n\t测试" \\换行后在tabfmt.Println(a) } abc测试func main() {var a abc测试 …

CppCheck静态代码检查工具教程【Windows和Linux端】

目录 1、背景 2、特性介绍 2.1、检查结果 2.2、检查范围 2.3、支持的检查规则&#xff08;列举一些&#xff09;: 2.4、自定义规则 3、linux 端 4、windows 端 1、背景 最近调研了几款 c/c 代码静态检查工具&#xff0c;包括 cppcheck、cpplint、cppdepend、splint、ts…

cmip6数据处理之降尺度

专题一 CMIP6中的模式比较计划 1.1 GCM介绍全球气候模型&#xff08;Global Climate Model, GCM&#xff09;&#xff0c;也被称为全球环流模型或全球大气模型&#xff0c;是一种用于模拟地球的气候系统的数值模型。这种模型使用一系列的数学公式来描述气候系统的主要组成部分…

分享Arduino环境下加速下载 第三方库或芯片包

Content 问题描述问题解决 问题描述 众所周知&#xff0c;由于网络的问题&#xff0c;导致Arduino里面的包下载速度非常慢&#xff0c;甚至下了非常久&#xff0c;最后也还是出现下载失败的情况。 有的人打开了加速器&#xff0c;但是也依旧是速度非常慢&#xff0c;为什么呢…

OpenGLES:绘制一个混色旋转的3D圆柱

一.概述 上一篇博文讲解了怎么绘制一个混色旋转的立方体 这一篇讲解怎么绘制一个混色旋转的圆柱 圆柱的顶点创建主要基于2D圆进行扩展&#xff0c;与立方体没有相似之处 圆柱绘制的关键点就是将圆柱拆解成&#xff1a;两个Z坐标不为0的圆 一个长方形的圆柱面 绘制2D圆的…

【列表渲染+收集表单数据+过滤器+内置指令+自定义指令】

列表渲染收集表单数据过滤器内置指令自定义指令 1 列表渲染1.1 基本列表1.2 key的作用与原理1.3 列表过滤1.4 列表排序1.5 Vue监测数据改变的原理 2 收集表单数据3 过滤器4 内置指令4.1 v-text指令4.2 v-html指令4.3 v-cloak指令4.4 v-once指令4.5 v-pre指令 5 自定义指令 1 列…