分支界定( BRANCH-AND-BOUND)
分支定界法(branch and bound)是一種求解整數規劃問題的最常用算法。這種方法不但可以求解純整數規劃,還可以求解混合整數規劃問題。分支定界法是一種搜索與叠代的方法,選擇不同的分支變量和子問題進行分支。
通常,把全部可行解空間反復地分割為越來越小的子集,稱為分枝;並且對每個子集內的解集計算一個目標下界(對於最小值問題),這稱為定界。在每次分枝後,凡是界限超出已知可行解集目標值的那些子集不再進一步分枝,這樣,許多子集可不予考慮,這稱剪枝。這就是分枝定界法的主要思路。
分支定界法求解整數規劃的一般步驟:
設有最大化的整數規劃問題A ,與它相對應的松弛問題為 B。
(1)先不考慮原問題的整數約束,求解相應的松弛問題。用圖解法或單純形法求得最優解,記為
(2)若求得的最優解 剛好就是整數解,則該整數解就是原整數規劃問題的最優解;否則,對原問題進行分枝尋求整數最優解。
(3)分枝。根據對變量重要性的了解,在最優解中選擇一個不符合整數約束條件的xj ,其值為bj ,以[bj]表示小於bj 的最大整數。構造兩個約束條件: x≤ [bj]和 x≥[bj]+1分別加入原LP問題形成兩個子問題,因為[bj] 與[bj]+1之間無整數,故這兩個子集內的整數解必定與原可行解集合整數解一致,這一步稱為分枝。
(4)定界。首先判斷各個子問題是否存在整數解。若存在,找出目標函數值最大對應的整數解,設為Z*,則A問題的整數解目標函數Z≥Z*
(5)若存在大於Z*的子問題則需分枝。第(4)步中若不存在整數解,也需繼續分枝尋找整數解,並從目標函數值最大對應的子問題先分枝。
(6)若所有子問題的目標值都小於等於Z*,則不需繼續分枝,Z*所對應的整數解即為最優解。
分支定界法求背包問題:
問題:一個容量為10的集裝箱,有重量分別為4,8,5的貨物,如何才能裝最多:
FIFO算法:
1.首先定義best=0
2. 第一層,4被選擇,此時的best修改成4,加入到隊列中;0<best 計算0節點的最大期望,13>best,加入到隊列中。
3.第二層,8被選擇,12>10,截枝;4=best,加入到隊列中;8>best, 加入到隊列,修改best=8,0節點的最大期望小<best,截枝;
4.第三層,修改best即可。
paython代碼:
import numpy as np capacity = 10 # 背包的容量是10 goods = [4, 8, 5] # 貨物重量 best = 0 # 最優重量 expect = sum(goods) # 期望值 queue = [0] # 記錄每層的節點 layer = 0 # 記錄層數 while layer < np.size(goods)-1: # 取出該層的所有節點,作為下層的父節點 expect = expect - goods[layer] # 修改期望值 parents = np.array(queue) nowParents = parents + goods[layer] temp_best = np.max(np.where(nowParents > capacity, 0, nowParents)) # 更新best if best < temp_best: best = temp_best # 選擇候選集, 截枝操作 nowParents = np.hstack((nowParents, parents)) temp_queue = [] for i in nowParents: if i + expect > best: temp_queue.append(i) queue = temp_queue layer = layer + 1 # 最後一層,計算最優值 parents = np.array(queue) nowParents = parents + goods[layer] nowParents = np.hstack((nowParents, parents)) best = np.max(np.where(nowParents > capacity, 0, nowParents)) print(best)
參考:https://www.cnblogs.com/shixisheng/p/6034779.html
https://www.cnblogs.com/sage-blog/p/3917836.html
https://blog.csdn.net/zack_liu/article/details/78370537
分支界定( BRANCH-AND-BOUND)