分枝定界法(Branch-and-Cut)

核心思想
把全部可行解空间反复地分割为越来越小的子集,称为分支;并且对每个子集内的解集计算一个目标下界(对于最小值问题),这称为定界。
在每次分枝后,凡是界限超出已知可行解集目标值的那些子集不再进一步分枝,这样,许多子集可不予考虑,这称剪枝。


简单来讲就是:最优性条件与分而治之:
①设有最大化的整数规划问题A,先解与之相应的线性规划问题B
②若B的最优解符合A的整数条件,该解即为A的解
③若B的最优解不符合A的整数条件,那么B的最优目标函数必是A的最优目标函数Z^{*}的上界,记作\overline{Z}。而A的任意可行解的目标函数值将是Z^{*}的一个下界\underline{Z}  

⑤解整数规划的连续松弛问题(线性规划)来得到该子问题的上界\overline{Z}

④分支定界法就是设置解整数规划的连续松弛问题(线性规划)来得到子问题,将B的可行域分成子区域(称为分支)的方法,通过子问题求解,逐步减小\overline{Z}和增大\underline{Z},最终求到Z^{*}

 优缺点:难于应对大规模问题


基本流程:

标准式,目标函数为最大值

①设整数规划问题为IP,对应松弛的线性规划问题为LP,(LP可理解为删除整数条件后的线性回话问题)。

求解LP,可能得到如下几种情况
LP无可行解,则IP也没有可行解.
LP有最优解切解的各个分量均为整数,即已经为IP问题的最优解,停止计算.
LP有最优解,但不符合IP中的整数条件的要求,设此时的目标数值为\overline{Z} , IP问题的最优目标值为Z^{*},则满足\overline{Z}Z^{*},即松弛的线性规划解\overline{Z}为整数规划解Z^{*}的上界。任意可行解的目标函数值将是Z^{*}的一个下界\underline{Z} (一般取0)


②迭代

分支:在LP的最优解中任选一个不符合整数条件的变量x_{j}(一般选择最大值的非整数分量构造添加约束条件),一般 添加大于x_{j}向上取整,小于x_{j}向下取整,将这两个条件分别加入问题LP,从而将LP拆分为两个子问题LP1LP2. 在松弛整数约束的条件下分别求解LP1LP2.

定界:以每个子问题为一个分支并表明求解结果,与其他问题的解进行比较,找到最优目标函数值的最小者作为新的上界\overline{Z},从符合整数条件的分支中,找出目标函数值的最大者作为新的下界\underline{Z} 

剪枝:各分支的最优目标函数值中若存在小于下界\underline{Z},则剪去该分支,如果大于且不符合整数条件,则重复分支步骤,直到最优目标函数值为止,得到最优整数解。

 


 算法


 

分枝定界是一种求解整数线性规划问题的常用方。该方的基本思想是将整数线性规划问题不断分解成子问题,然后对每个子问题进行求解,直到得到最优解。 Python 实现整数线性规划的分枝定界,可以基于 Python 的优化库 `PuLP`。以下是一个简单的示例代码: ```python from pulp import * # 定义整数线性规划问题 prob = LpProblem("Integer Linear Programming", LpMinimize) # 添加变量 x1 = LpVariable("x1", lowBound=0, cat='Integer') x2 = LpVariable("x2", lowBound=0, cat='Integer') # 添加目标函数 prob += 3*x1 + 4*x2 # 添加约束条件 prob += 2*x1 + x2 >= 3 prob += x1 + 2*x2 >= 3 # 求解 prob.solve() # 输出结果 print("Status:", LpStatus[prob.status]) print("Minimum value:", value(prob.objective)) print("Optimal solution:") for v in prob.variables(): print(v.name, "=", v.varValue) ``` 以上代码是一个简单的整数线性规划问题的求解示例,其中定义了两个变量 `x1` 和 `x2`,并添加了目标函数和两个约束条件。通过 `prob.solve()` 方进行求解,并输出最优解及对应的变量取值。 分枝定界的实现,可以通过递归地将当前问题分解成两个子问题,并对子问题进行求解,直到得到最优解。在每次分解时,需要对当前解的上下界进行计算,并通过 `prob +=` 方添加上下界约束条件。具体实现可以参考以下示例代码: ```python from pulp import * # 定义整数线性规划问题 prob = LpProblem("Integer Linear Programming", LpMinimize) # 添加变量 x1 = LpVariable("x1", lowBound=0, cat='Integer') x2 = LpVariable("x2", lowBound=0, cat='Integer') # 添加目标函数 prob += 3*x1 + 4*x2 # 添加初始约束条件 prob += 2*x1 + x2 >= 3 prob += x1 + 2*x2 >= 3 def solve_branch_and_bound(prob): # 求解当前问题 prob.solve() # 获取当前解的上下界 upper_bound = value(prob.objective) lower_bound = upper_bound # 分解问题并求解 for v in prob.variables(): # 向上取整 upper_value = int(v.varValue) + 1 # 向下取整 lower_value = int(v.varValue) # 分解为两个子问题 prob1 = LpProblem("Integer Linear Programming", LpMinimize) prob2 = LpProblem("Integer Linear Programming", LpMinimize) # 添加变量 x1 = LpVariable("x1", lowBound=0, cat='Integer') x2 = LpVariable("x2", lowBound=0, cat='Integer') # 添加目标函数 prob1 += 3*x1 + 4*x2 prob2 += 3*x1 + 4*x2 # 添加约束条件 for c in prob.constraints: prob1 += c prob2 += c # 添加上下界约束条件 if v.name == 'x1': prob1 += x1 >= upper_value prob2 += x1 <= lower_value elif v.name == 'x2': prob1 += x2 >= upper_value prob2 += x2 <= lower_value # 求解子问题 prob1.solve() prob2.solve() # 计算上下界 if value(prob1.objective) < value(prob2.objective): upper_bound = min(upper_bound, value(prob1.objective)) else: upper_bound = min(upper_bound, value(prob2.objective)) lower_bound = max(lower_bound, value(prob1.objective), value(prob2.objective)) # 判断是否达到最优解 if upper_bound == lower_bound: return upper_bound # 分解子问题并求解 for v in prob.variables(): # 向上取整 upper_value = int(v.varValue) + 1 # 向下取整 lower_value = int(v.varValue) # 分解为两个子问题 prob1 = LpProblem("Integer Linear Programming", LpMinimize) prob2 = LpProblem("Integer Linear Programming", LpMinimize) # 添加变量 x1 = LpVariable("x1", lowBound=0, cat='Integer') x2 = LpVariable("x2", lowBound=0, cat='Integer') # 添加目标函数 prob1 += 3*x1 + 4*x2 prob2 += 3*x1 + 4*x2 # 添加约束条件 for c in prob.constraints: prob1 += c prob2 += c # 添加上下界约束条件 if v.name == 'x1': prob1 += x1 >= upper_value prob2 += x1 <= lower_value elif v.name == 'x2': prob1 += x2 >= upper_value prob2 += x2 <= lower_value # 判断是否需要继续分解 if min(value(prob1.objective), value(prob2.objective)) > upper_bound: continue # 递归求解子问题 if value(prob1.objective) <= value(prob2.objective): upper_bound = min(upper_bound, solve_branch_and_bound(prob1)) else: upper_bound = min(upper_bound, solve_branch_and_bound(prob2)) return upper_bound # 求解 optimal_value = solve_branch_and_bound(prob) # 输出结果 print("Minimum value:", optimal_value) print("Optimal solution:") for v in prob.variables(): print(v.name, "=", v.varValue) ``` 以上代码实现了整数线性规划的分枝定界,其中 `solve_branch_and_bound` 方用于递归地分解问题并求解。在每次分解时,都会计算当前解的上下界,并根据上下界约束条件进行分解。通过递归求解子问题,最终得到最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值