分支定界法(matlab实现)

分支定界法(matlab实现)分支定界法背景今天利用 matlab 来实现求解完全整数规划问题和混合整数规划问题的分支定界法 基本理论分支定界法 用以求解整数规划问题的一种方法 求解步骤 求出该整数规划问题对应的原线性规划问题的最优解 若为整数 得到最优解 若不为整数 跳至第 2 步分支 定界 剪枝 不断反复 直到得到整数最优解分支定界法伪代码如下 输入规划问题对应的矩阵 binTreeNode f

分支定界法

背景

基本理论

  • 分支定界法:用以求解整数规划问题的一种方法。
  • 求解步骤:
    首先我们规定求解的整数规划问题为A,相应的线性规划问题为B

  1. 对问题B进行求解
    1. 若B无可行解,则A也无可行解,停止计算
    2. 若B有最优解,且符合整数条件,该最优解为A的最优解,停止计算
    3. 若B有最优解,但不符合整数条件,记它的目标函数值为z*,作为最优值的下界






  2. 找出问题A的一个整数可行解,其目标函数值作为最优解的上界
  3. 进行迭代
    1. 分支,在B的最优解中任选一个不符合整数条件的变量 x j x_j xj,其值为 b j b_j bj,构造两个约束条件, x j ≤ [ b j ] x_j \leq [b_j] xj[bj] x j ≥ [ b j ] + 1 x_j \geq [b_j] + 1 xj[bj]+1,分别加入到问题B中,形成两个子问题 B 1 B_1 B1 B 2 B_2 B2。不考虑整数条件求解这两个子问题。即分支
    2. 定界。对每个后继问题表明其求解的结果,与其他问题进行比较,将最优目标函数值最小者(不包括问题B)作为新的下界,在已符合整数条件的各分支中,找出目标函数值最小者作为新的上界。
    3. 剪枝,将目标函数值不在上界、下界中的分支剪去
    4. 重复1 2 3,直到得到最优解
      注意事项:在对两分支进行分解时,优先选择目标函数值最小的分支进行分解。

分支定界法中,通过定界进而进行剪枝,对分支进行了筛选,使我们仅在一部分可行解中寻求最优解,而不是全部穷举出来再寻找,其求解效率更高。

代码实现

因为分支定界法的求解过程与二叉树结构相同,所以我们利用二叉树这种数据结构来存储每一个线性规划问题的解及对应的目标函数值。

代码如下:

  1. 首先是主函数:
% main.m % 分支定界法 % ----------------------------------------------- % 求解模型: % min z = f * x % A * x <= b % x >= 0,且为整数 % --------------------------------------------------- clear global; clear; clc; global result; % 存储所有整数解 global lowerBound; % 下界 global upperBound; % 上界 global count; % 用以判断是否为第一次分支 count = 1; f = [-40, -90]; A = [8, 7; 7, 20;]; b = [56; 70]; Aeq = []; beq = []; lbnd = [0; 0]; ubnd = [inf; inf]; BinTree = createBinTreeNode({f, A, b, Aeq, beq, lbnd, ubnd}); if ~isempty(result) [fval,flag]=min(result(:,end)); % result中每一行对应一个整数解及对应的函数值 Result=result(flag,:); disp('该整数规划问题的最优解为:'); disp(Result(1,1:end-1)); disp('该整数规划问题的最优值为:'); disp(Result(1,end)); else disp('该整数规划问题无可行解'); end 
  1. 创建二叉树函数
% createBinTreeNode.m % 构建二叉树,每一结点对应一解 function BinTree = createBinTreeNode(binTreeNode) global result; global lowerBound; global upperBound; global count; if isempty(binTreeNode) return; else BinTree{1} = binTreeNode; BinTree{2} = []; BinTree{3} = []; [x, fval, exitflag] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, binTreeNode{7}); if count == 1 % upperBound = 0; % 初始下界为空 lowerBound = fval; count = 2; end if ~IsInRange(fval) return; end if exitflag == 1 flag = []; % 寻找非整数解分量 for i = 1 : length(x) if round(x(i)) ~= x(i) flag = i; break; end end % 分支 if ~isempty(flag) lowerBound = max([lowerBound; fval]); OutputLowerAndUpperBounds(); lbnd = binTreeNode{6}; ubnd = binTreeNode{7}; lbnd(flag, 1) = ceil(x(flag, 1)); % 朝正无穷四舍五入 ubnd(flag, 1) = floor(x(flag, 1)); % 进行比较,优先选择目标函数较大的进行分支 [~, fval1] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd); [~, fval2] = linprog(binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7}); if fval1 < fval2 % 创建左子树 BinTree{2} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd}); % 创建右子树 BinTree{3} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7}}); else % 创建右子树 BinTree{3} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, lbnd, binTreeNode{7}}); % 创建左子树 BinTree{2} = createBinTreeNode({binTreeNode{1}, binTreeNode{2}, binTreeNode{3}, ... binTreeNode{4}, binTreeNode{5}, binTreeNode{6}, ubnd}); end else upperBound = min([upperBound; fval]); OutputLowerAndUpperBounds(); result = [result; [x', fval]]; return; end else % 剪枝 return; end end 
  1. 判断目标函数值是否在上下界范围中
% IsInRange.m % 判断分支问题的解是否在上下界的范围中,若不在,剪去 function y = IsInRange(fval) global lowerBound; global upperBound; if isempty(upperBound) & fval >= lowerBound y = 1; else if (fval >= lowerBound & fval <= upperBound) y = 1; else y = 0; end end 
  1. 打印输出上下界
% 打印输出上下界 function y = OutputLowerAndUpperBounds() global lowerBound; global upperBound; disp("此时下界、上界分别为"); disp(lowerBound); if isempty(upperBound) disp(' 无上界') else disp(upperBound); end end 

计算实例

在这里插入图片描述

  • 计算结果如下:
    在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/201196.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午9:52
下一篇 2026年3月20日 上午9:52


相关推荐

  • IDEA注释详解_idea自定义注释模板

    IDEA注释详解_idea自定义注释模板目录目录生成类注释生成类注解模板生成方法注释生成方法注解模板最近从eclipse转idea了,第一步当然是配置快捷键,模板等。但是!发生了一件贼蛋疼的事情,竟然一直找不到正确添加方法注释的方法!最后自己摸索到了,在此详细记录,供大家参考。测试版本为ideaformac,可能快捷键不同,但是设置等肯定是相同的12生成类注释打开PreferencesEditor-&gt;Fileand…

    2026年4月19日
    5
  • 微软面试题–三个灯泡–三个开关

    微软面试题–三个灯泡–三个开关这是一道微软用来测试应聘者的试题 它主要考察受训者的逻辑思维和判断能力 同时也给受训者一些关于问题解决方法上的启示 游戏规则和程序 1 有两个房间 一间房里有三盏灯 另一间房有控制着三盏灯的三个开关 这两个房间是分割开的 从一间里不能看到另一间的情况 2 现在要求受训者分别进这两房间一次 然后判断出这三盏灯分别是由哪个开关控制的 3 有什么办法呢 相关讨论 1 请受

    2026年3月27日
    2
  • 最新版idea2017+kemulator搭建J2ME开发环境「建议收藏」

    最新版idea2017+kemulator搭建J2ME开发环境「建议收藏」要求32位电脑,没有的话装个虚拟机。实际中发现kemulator的调试功能只有在32位条件下才能运行

    2022年7月16日
    28
  • 冯诺依曼体系结构「建议收藏」

    冯诺依曼体系结构「建议收藏」目录冯诺依曼体系结构简介数据流向存储分级举例说明数据的流动过程冯诺依曼体系结构简介我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。计算机本质上是有输入,并且经过计算机的计算,将结果显示到某种显示输出上,就可以称为计算机。输入单元:键盘,网卡,磁盘,话筒…输出单元:显示器,网卡,磁盘,音响…存储器没有特殊说明一般指的是物理内存。中央处理器(CPU):含有运算器和控制器等运算器在进行运算的时候无外乎两种情况,一种是算术运算,一种逻辑运算。控制器主要能够用来

    2025年8月12日
    4
  • nginx反向代理数据库端口安全吗(nginx反向代理80端口)

    nginx反向代理数据库端口使用场景如下:当数据库在服务器A并且处于外网无法直接访问时,此时同局域网下只有服务器B提供对外访问,客户能访问b却无法访问A的情况下,由于两台服务器处于同局域网,并且服务器A有端口是开放的,可以在服务器B内进行nginx反向代理安装nginx首先在服务器b内,安装nginx(docker化的也可以)如果是docker的nginx需要进入docker内的nginxdockerexec-it容器idbash一般nginx的配置文件在e

    2022年4月9日
    48
  • 关于tempdb的一些注意事项

    关于tempdb的一些注意事项

    2021年11月25日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号