分枝定界法可用于解纯整数或混合的整数规划问题。在本世纪六十年代初由 Land Doig 和 Dakin 等人提出的。由于这方法灵活且便于用计算机求解,所以现在它已是解 整数规划的重要方法。目前已成功地应用于求解生产进度问题、旅行推销员问题、工厂 选址问题、背包问题及分配问题等。


分枝定界法

1.定义

对有约束条件的最优化问题(其可行解为有限数)的所有可行解空间恰当地进行系 统搜索,这就是分枝与定界内容。通常,把全部可行解空间反复地分割为越来越小的子 集,称为分枝;并且对每个子集内的解集计算一个目标下界(对于最小值问题),这称 为定界。在每次分枝后,凡是界限超出已知可行解集目标值的那些子集不再进一步分枝,这样,许多子集可不予考虑,这称剪枝。这就是分枝定界法的主要思路。

设有最大化的整数规划问题 A ,与它相应的线性规划为问题 B ,从解问题 B 开始, 若其最优解不符合 A 的整数条件,那么 B 的最优目标函数必是 A 的最优目标函数  的 上界,记作  ;而 A 的任意可行解的目标函数值将是 的一个下界 。分枝定界法就是将 B 的可行域分成子区域的方法。逐步减小 和增大 ,最终求到 。现用下例来 说明:

2.例题解说

例 3 求解下述整数规划:

且为整数

(i)先不考虑整数限制,即解相应的线性规划B,得最优解为:

使用python单纯形表得出:

        objctive        |                   355.88                   |solution        |  4.81  |  1.82  |   0    |   0    |

最优解为:

可见它不符合整数条件。这时 是问题的最优目标函数值 的上界,记作  。而 显然是问题 的一个整数可行解,这时 ,是 的一个下界,记作 , 即

(ii)因为当前均为非整数,故不满足整数要求,任选一个进行分枝。设选 1 x 进行分枝,把可行集分成 2 个子集:

因为 4 与 5 之间无整数,故这两个子集的整数解必与原可行集合整数解一致。这 一步称为分枝。这两个子集的规划及求解如下:

问题

最优解为:

问题

最优解为:

再定界:

(iii)对问题 B1 再进行分枝得问题 B11和 B12 ,它们的最优解为

再定界:,并将剪枝。

(iv)对问题 再进行分枝得问题 ,它们的最优解为

​​​​​​​    无可行解。

 剪枝。

于是可以断定原问题的最优解为:

3.数学建模过程:

分枝定界法求解整数规划(最大化)问题的步骤为:

开始,将要求解的整数规划问题称为问题 A ,将与它相应的线性规划问题称为问 题 B 。

解问题 B 可能得到以下情况之一:

(a) B 没有可行解,这时 A 也没有可行解,则停止.

(b) B 有最优解,并符合问题 A 的整数条件, B 的最优解即为 A 的最优解,则 停止。

(c) B 有最优解,但不符合问题 A 的整数条件,记它的目标函数值为

用观察法找问题 A 的一个整数可行解,一般可取  试探, 求得其目标函数值,并记作。以 ​ ​​​​​​试探, 求得其目标函数值,并记作进行迭代。

建模过程

第一步:分枝,在 B 的最优解中任选一个不符合整数条件的变量 ,其值为 , 以[  ]  表示小于 的最大整数。构造两个约束条件

将这两个约束条件,分别加入问题 B ,求两个后继规划问题 。不考虑整数条件 求解这两个后继问题。

定界,以每个后继问题为一分枝标明求解的结果,与其它问题的解的结果中,找出 最优目标函数值最大者作为新的上界 。从已符合整数条件的各分支中,找出目标函数 值为最大者作为新的下界 ,若无作用 不变。

第二步:比较与剪枝,各分枝的最优目标函数中若有小于 z 者,则剪掉这枝,即 以后不再考虑了。若大于 ,且不符合整数条件,则重复第一步骤。一直到最后得到 = 为止。得最优整数解

4.编程实现

使用python实现分枝定界法算法:

from scipy.optimize import linprog
import numpy as np
from math import floor, ceil
import copyclass Node(object):def __init__(self, x_bounds=[], freeze_var_list=[], index=0, upper_or_lower=0):self._x_bounds = x_boundsself._freeze_var_list = freeze_var_listself._index = indexself._upper_or_lower = upper_or_lowerprint("创建节点: {}".format(index))print('')def freeze_var(self, index, val):self._x_bounds[index][0] = valself._x_bounds[index][1] = valself._freeze_var_list.append(index)def set_lp_res(self, res):self._res = ress = ""for l in range(len(self._res['x'])):if l in self._freeze_var_list:s += "[" + str(self._res['x'][l]) + "]"else:s += " " + str(self._res['x'][l])print("x: ", s)def check_integer_val_solved(self, m):return True if m == len(self._freeze_var_list) else Falseclass BbAlgorithm(object):def __init__(self, c, a_ub, b_ub, x_b, integer_val):self.c = cself.a_ub = a_ubself.b_ub = b_ubself.x_b = x_bself._integer_val = integer_valself.best_solution = float('inf')self.best_node = Noneself.nodes = []self.nodes_solution = []def solve_lp(self, cur_x_b):return linprog(self.c, A_ub=self.a_ub, b_ub=self.b_ub, bounds=cur_x_b)def check_fessible(self, res):if res['status'] == 0:return Trueelif res['status'] == 2:return Falseelse:raise ("问题无界")def add_node(self, node):res = self.solve_lp(node._x_bounds)if self.check_fessible(res) and res['fun'] < self.best_solution:node.set_lp_res(res)self.nodes_solution.append(res['fun'])self.nodes.append(node)if node.check_integer_val_solved(len(self._integer_val)):self.best_solution = res['fun']self.best_node = nodeprint("----------------当前解决方案-------------------")print("x: ", node._res['x'])print("z: ", node._res['fun'])print("---------------------------------------------------\n")print("==> 将节点添加到树列表: ", node._index)print("==> 当前节点: ", self.nodes_solution)print("")return Trueelse:print("==> 节点不可行: ", node._index)print("==> 当前节点: ", self.nodes_solution)print("")return Falsedef del_higher_val_node(self, z_s):del_list = []for i in range(len(self.nodes_solution)):if self.nodes_solution[i] >= z_s:del_list.append(i)s = ""for i in del_list:s += " " + str(self.nodes[i]._index)print("删除节点: ", s)self.nodes = list(np.delete(self.nodes, del_list))self.nodes_solution = list(np.delete(self.nodes_solution, del_list))print("当前节点: ", self.nodes_solution)print("")def del_item(self, index):print("删除节点: ", self.nodes[index]._index)self.nodes = list(np.delete(self.nodes, index))self.nodes_solution = list(np.delete(self.nodes_solution, index))print("当前节点: ", self.nodes_solution)print("")def check_bounds(self, temp_x_b, index, u_or_l):if u_or_l == 1:if self.x_b[index][0] is not None and temp_x_b[index][0] is None:return Falseelif self.x_b[index][0] is None and temp_x_b[index][0] is not None:return Trueelif self.x_b[index][0] is not None and temp_x_b[index][0] is not None:return False if(self.x_b[index][0] > temp_x_b[index][0]) else Trueelif u_or_l == 2:if self.x_b[index][1] is not None and temp_x_b[index][1] is None:return Falseelif self.x_b[index][1] is None and temp_x_b[index][1] is not None:return Trueelif self.x_b[index][1] is not None and temp_x_b[index][1] is not None:return False if(self.x_b[index][1] < temp_x_b[index][1]) else Trueelse:print("界限误差")exit()def run(self):print("####################### 开始 B & B #####################\n")node_count = 0node = Node(copy.deepcopy(self.x_b), [], node_count)node_count += 1res = self.solve_lp(self.x_b)lower = floor(res['x'][self._integer_val[0]])upper = lower + 1lower_node = Node(copy.deepcopy(self.x_b), [], node_count, 1)lower_node.freeze_var(self._integer_val[0], lower)self.add_node(lower_node)node_count += 1upper_node = Node(copy.deepcopy(self.x_b), [], node_count, 2)upper_node.freeze_var(self._integer_val[0], upper)self.add_node(upper_node)node_count += 1while len(self.nodes) > 0:index = np.argmin(self.nodes_solution)x_b = self.nodes[index]._x_boundsfreeze_list = self.nodes[index]._freeze_var_listres = self.nodes[index]._resfreeze_var_index = len(freeze_list)lower = floor(res['x'][self._integer_val[freeze_var_index]])upper = lower + 1lower_node = Node(copy.deepcopy(x_b), copy.deepcopy(freeze_list), node_count, 1)lower_node.freeze_var(self._integer_val[freeze_var_index], lower)self.add_node(lower_node)node_count += 1upper_node = Node(copy.deepcopy(x_b), copy.deepcopy(freeze_list), node_count, 2)upper_node.freeze_var(self._integer_val[freeze_var_index], upper)self.add_node(upper_node)node_count += 1self.del_item(index)self.del_higher_val_node(self.best_solution)print("############################################################")print("")print("######################### 最佳解决方案 #######################")print(self.best_node._res)if __name__ == "__main__":integer_val = [0,1]c = [-40, -90]A = [[9, 7], [7, 20]]b = [56,70]x_bounds = [[0, None] for _ in range(len(c))]bb_algorithm = BbAlgorithm(c, A, b, x_bounds, integer_val)bb_algorithm.run()

输出结果:

####################### 开始 B & B #####################创建节点: 0创建节点: 1x:  [4.0] 2.0999999999901706
==> 将节点添加到树列表:  1
==> 当前节点:  [-348.99999999911535]创建节点: 2x:  [5.0] 1.5714285714280996
==> 将节点添加到树列表:  2
==> 当前节点:  [-348.99999999911535, -341.4285714285289]创建节点: 3x:  [4.0][2.0]
----------------当前解决方案-------------------
x:  [4. 2.]
z:  -340.0
---------------------------------------------------==> 将节点添加到树列表:  3
==> 当前节点:  [-348.99999999911535, -341.4285714285289, -340.0]创建节点: 4==> 节点不可行:  4
==> 当前节点:  [-348.99999999911535, -341.4285714285289, -340.0]删除节点:  1
当前节点:  [-341.4285714285289, -340.0]删除节点:   3
当前节点:  [-341.4285714285289]############################################################
创建节点: 5==> 节点不可行:  5
==> 当前节点:  [-341.4285714285289]创建节点: 6==> 节点不可行:  6
==> 当前节点:  [-341.4285714285289]删除节点:  2
当前节点:  []删除节点:
当前节点:  []##################################################################################### 最佳解决方案 #######################con: array([], dtype=float64)fun: -340.0message: 'The solution was determined in presolve as there are no non-trivial constraints.'nit: 0slack: array([6., 2.])status: 0success: Truex: array([4., 2.])

Python整数规划—分枝定界法相关推荐

  1. Python 实现整数线性规划:分枝定界法(Branch and Bound)

    今天做作业,要实现整数线性规划的分枝定界法算法.找了一些网上的博客,发现都很屎,感觉自己写的这个比较清楚.规范,所以在此记录.如有错误,请指正. from scipy.optimize import ...

  2. 【数学建模入门】整数规划求最优解|分枝定界法求最优解

    文章目录 整数规划 分枝定届法 `intprog` `branchbound` 整数规划 intprog() function [x,fval,status] = intprog(f,A,B,I,Ae ...

  3. python混合整数线性规划_Python 实现整数线性规划:分枝定界法(Branch and Bound)...

    今天做作业,要实现整数线性规划的分枝定界法算法.找了一些网上的博客,发现都很屎,感觉自己写的这个比较清楚.规范,所以在此记录.如有错误,请指正. from scipy.optimize import ...

  4. 分枝定界法的一般步骤

    分枝定界法的一般步骤 设有最大化的整数规划问题A ,与它相对应的松弛问题为 B. (1)先不考虑原问题的整数约束,求解相应的松弛问题.用图解法或单纯形法求得最优解,记为 . (2)若求得的最优解 刚好 ...

  5. 分枝定界法解0/1背包问题

    分枝定界法解0/1背包问题 关键词:分支定界.0-1背包 分枝定界法简介 分枝定界法按照树形结构来组织解空间,展开节点后,有两种策略: 策略一.把节点加入 FIFO 队列当中: 策略二.把节点加入到堆 ...

  6. 分枝定界法求哈密尔登回路问题的由表及里

    刻苦努力的奋斗,终于有了学习成果,虽然写出的仅仅是非常拙略,功能单一的,简单的小程序代码,但不失为在代码学习的进步.总算是有了含有自己智慧在其中的结晶.其实这段代码能够顺利完成,虽然是独立完成,但终究 ...

  7. 分支定界 matlab,使用MATLAB实现分枝定界法求解整数规划的详细资料说明

    分支定界法是一种求解离散最优化问题的计算分析方法.它是由Land Doig和Dakin等人在20世纪60年代初提出的.分支定界法可求纯整数或混合整数线性规划问题,求解方法由分支和定界组成." ...

  8. 整数规划之分枝定界法

    整数规划之分枝界定法 引子: 题目分析: 这个整数规划问题相当于是在简单的线性规划问题上增加了决策变量为整数的限制条件.如果没有这个限制条件,那我们用linprog函数很容易解决如下 >> ...

  9. 【cartographer】(2)分枝定界算法

    分枝定界方法 分枝定界法(branch and bound)是一种求解整数规划问题的最常用算法,是一种搜索与迭代的方法. 通俗说法: 分枝定界算法始终围绕着一颗搜索树进行的,主要流程就是分枝+定界. ...

最新文章

  1. 梯度下降到底是什么?
  2. 【转】老程序猿给新程序猿的13点建议
  3. java在线聊天项目0.4版本 制作服务端接收连接,客户端连接功能 新增客户端窗口打开时光标指向下边文本域功能,使用WindowListener监听WindowAdapter...
  4. MVC高级编程-目录
  5. 29个人,耗时84天,硬刚Python,实验结果如下。
  6. rabbitmq实战_RabbitMQ 实战系列之:消息传递
  7. java容器类继承_JAVA容器 - weslie - OSCHINA - 中文开源技术交流社区
  8. Linux常见的发行版SUSE、Ubuntu、RedHat、CentOS、Fedora的联系和区别
  9. html做在线预览pdf文件,html中在线预览pdf文件之pdf在线预览插件
  10. Aqua Comms携手Ciena 测试海底光缆网络150Gbps波长传输
  11. 讲解如何在HTML中添加背景图片?
  12. 华为供应链的“危”与“机”
  13. 基于React+antd的后台管理模板(可预览)
  14. EBS 个性化:个性化设置界面
  15. U大师U盘启动盘克隆制作工具
  16. xshell 免费版
  17. 服务器主板准系统怎么拆,主板准系统及电源装箱步骤完成_技嘉 GA-B85M-D3V_主板评测-中关村在线...
  18. WPF 创建秒表 计时器
  19. 4转自 饮水思源 bbs.sjtu.edu.cn·[FROM: 202.120.25.97]
  20. MIPS常见指令汇总

热门文章

  1. Linux虚拟内存交换空间,Linux 添加 Swp 虚拟内存交换空间
  2. 【图像融合】基于DCT域实现多焦点图像融合含Matlab源码
  3. PHP使用phpword生成word文档
  4. 最右App:架构演进之路
  5. java向窗口添加菜单_Java基础之创建窗口——向窗口中添加菜单(Sketcher)
  6. python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
  7. 使用VsCode进行ROS程序调试
  8. 硬盘坏了不用怕,20块钱能修好
  9. winsever服务系统基础教程(随堂笔记)
  10. 数据增广albumentations用法 -借例 hw3 食物分类-