Branch-and-Bound.

Slides:



Advertisements
Similar presentations
1 第八章 深入探討樹狀結構. 2 目次 8.1 m-way 搜尋樹 8.2 B-tree 8.3 動動腦時間 8.4 練習題解答.
Advertisements

Author : Hyesook Lim, Changhoon Yim, and Earl E. Swartzlander, Jr., Fellow Publisher : IEEE TRANSACTIONS ON COMPUTERS, VOL. 59, NO. 6, JUNE 2010 Presenter.
資料結構(計財系).
Project 2 JMVC code tracing
Linear Programming: Introduction and Duality
Chap4 Tree.
Tree(樹) 什麼是「樹」? 「樹」的範例 「樹」的定義 「樹」的表示法.
Chap5 Graph.
資料結構 第3章 鏈結串列.
Chapter 4 Spanning Trees
Chap5 Graph.
資料結構設計與C++程式應用 Fundamentals of Data Structures and Their Applications Using C++ 第3章 佇列 資料結構設計與C++程式應用.
第8章 圖形結構(Graphs) 8-1 圖形的基本觀念 8-2 圖形的表示法 8-3 圖形的走訪 8-4 擴張樹
哈夫曼编码.
Graph 2 Michael Tsai 2012/5/1 連載: 學生上課睡覺姿勢大全
Graph Theory Graph theory is the study of the properties of graph structures. It provides us with a language with which to talk about graphs.
(Circular Linked Lists)
Chapter 7 圖形與網路 資料結構導論 - C語言實作.
資料結構 第7章 圖形結構.
資料結構–樹(Tree) 綠園.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Chap3 Linked List 鏈結串列.
第一章 直角坐標系 1-1 數系的發展.
Chapter 11 B-tree 11.1 m-way 搜尋樹 11.2 B-tree.
Ch 3 Dynamic Programming (動態規劃).
深度優先搜尋(DFS)與 廣度優先搜尋(BFS)
2-3-4 Tree and how it relates to Red Black Tree
Chapter 2 Basic Concepts in Graph Theory
感謝同學們在加分題建議. 我會好好研讀+反省~
Chap4 Tree.
資料結構 7-1 陣列 7-2 鏈結串列 7-3 堆疊和佇列 7-4 樹狀結構.
資料結構 優點 缺點 1 陣列 (Array) 沒有額外變量 (例head, next,...) 運作/操作較簡單 更新資料時,若要保持順序,需要移動較大量資料 靜態結構Static (宣告時已決定了陣列元素多少,不能在程式執行期間增減元素) 2 隊列Queue (FIFO) 容易更新 加入enqueue:
資料結構使用Java 樹(Tree).
一個基于相鄰區塊相似性和動態次編碼簿的低位元率向量量化 圖像壓縮法
最短路徑 The Shortest Path.
Reference to FUNDAMENTALS OF DATA STRUCTURE IN C++
101北一女中 資訊選手培訓營 深度優先搜尋(DFS)的進階應用 Nan.
挑戰C++程式語言 ──第8章 進一步談字元與字串
資料結構使用Java 第9章 樹(Tree).
蕭志明 老師 Algorithm(演算法) Ext:6779
蕭志明 老師 Algorithm(演算法) /FB:
C qsort.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
Course 8 回溯、分枝與限制 Backtracking, Branch-and-Bound
講師:郭育倫 第3章 基本資料結構 講師:郭育倫
一個基于相鄰區塊相似性和動態次編碼簿的低位元率向量量化 圖像壓縮法
唐常杰 四川大学计算机学院 计算机科学技术系
陣列與結構.
12797: Letters ★★★☆☆ 題組:Problem Set Archive with Online Judge
動畫演示 Node規範了一些基本的方法,像是增加節點、刪除節點、讓節點做一些事、取得第n個節點等等
第7章 資料結構 7-1 陣列 7-2 鏈結串列 7-3 堆疊和佇列 7-4 樹狀結構.
1757: Secret Chamber at Mount Rushmore
主讲人: 吕敏 { } Spring 2016,USTC 算法基础 主讲人: 吕敏 { } Spring 2016,USTC.
資料結構與C++程式設計進階 期末考 講師:林業峻 CSIE, NTU 7/ 15, 2010.
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
一個基于相鄰區塊相似性和動態次編碼簿的低位元率向量量化 圖像壓縮法
All Sources Shortest Path The Floyd-Warshall Algorithm
Advanced Competitive Programming
10791: Minimum Sum LCM ★★★☆☆ 題組:Problem Set Archive with Online Judge
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
Trees 授課者:驕芸.
10303: How Many Trees? ★★☆☆☆ 題組:Contest Archive with Online Judge
Graph 1 Michael Tsai 2012/4/24 連載: 學生上課睡覺姿勢大全
11621 : Small Factors ★★☆☆☆ 題組:Problem Set Archive with Online Judge
JAVA 程式設計與資料結構 第十七章 Tree.
Chapter 16 動態規劃.
微 處 理 機 專 題 – 8051 C語言程式設計 主題:階乘計算
JAVA 程式設計與資料結構 第二十一章 Graph.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
Presentation transcript:

Branch-and-Bound

Branch-and-Bound 作用 特點 ‧用來改良回溯演算法。 ‧使用狀態空間樹來解決問題。 ‧不限制要怎麼走訪整棵樹。(回溯法有限制) ‧只用來解決最佳化問題。

使用 Branch-and-Bound 修剪法之最佳優先搜尋 ‧除了使用 bound 值來決定一個節點是不是 promising 之外,  還必須加以比較每個子節點的 bound 值,然後挑選具有  最佳 bound 值的子節點進行走訪。 ‧此方式通常會比事先決定的順序 (如 DFS) 更早到達代表  最佳解的節點。這也是 BFS 的簡易修正版。

BFS (廣度優先搜尋)

BFS Algorithm void breadth_first_tree_search ( tree T ) { queue_of_node Q ; //宣告一個先進先出的佇列 node u , v ; initialize ( Q ) ; //初始時將佇列清空 v = root of T ; //走訪根節點 visit v ; enqueue( Q, v ) ; //將根節點存入佇列尾端 while ( ! empty ( Q ) ) { //當佇列中有節點時 dequeue ( Q, v ) ; //從佇列前端取出一個節點 v for ( each child u of v ) { visit u ; //走訪 v 的每個子節點 u enqueue ( Q , u ) ; //每走訪一個子節點 u 就將它 } //放到佇列中 }

BFS 演算法走訪樹的範例 放入 1 1 取出 1 2 3 4 取出 2 3 4 5 6 7 取出 3 4 5 6 7 8 9 取出 4 5 10 11 12 取出 5 6 7 8 9 10 11 12 取出 6 7 8 9 10 11 12 13 14 取出 7 8 9 10 11 12 13 14 取出 8~11 12 13 14 15 16 取出 12 13 14 15 16 取出 13~16

Branch-and-Bound 以 BFS 走訪法來解0-1背包問題 n=4,W=16 i Pi wi Pi/wi 1 $40 2 $20 $30 5 $6 3 $50 10 $5 4 $10 $2 將物品依照單位重量獲益比 (Pi / Wi )值由大到小排序。 狀態空間樹的每個節點內部有三個數字,由上而下為: 全部獲益 ( 即 profit ) 全部重量 ( 即 weight ) 獲益上限值 ( 即 bound )

nonpromising 策略 (1) 由樹的根節點往下走到第 i 層節點時,若已經沒空間 設 weight = 在第 i 層節點所累積的物品總重量 若 weight  W 則此節點一定是 nonpromising 。 背包載重限制

nonpromising 策略(續) (2) 從貪婪法則的觀點來找出一個較不明顯的判斷 promising 與否的方法。 總重量 第 i+1 層到 k-1 層節點為止的總重量。 因為到第 k 層就爆了。 第 1 到 i 層節點的總獲益值 可以分配給 第 k 個物品 的容量 第 i 層節點 的最大獲益 上限值。 第 k 個物品 單位重量的 獲益 前 k-1 個物品的 總獲益

branch-and-bound 以 BFS 走訪法產生的樹 profit weight bound 目前最佳值 maxprofit = 0 40 40 70 70 70 70 90 90 70 70 90 90 90 90 90 90

Breadth-first branch-and-bound Algorithm void breadth_first_branch_and_bound ( state_space_tree T , number& best ) { queue_of_node Q ; //宣告一個佇列用來擺放欲走訪的節點 node u , v ; initialize ( Q ) ; //啟始時將佇列清空 v = root of T ; enqueue ( Q , v ) ; //走訪 root 節點,並將它加入佇列尾端 best = value ( v ) ; //初始化目前最佳值 while ( ! empty ( Q ) ) { dequeue ( Q , v ) ; //從佇列前端取出一個節點 v for ( each child u of v ) { //走訪 v 的每個子節點 u if ( value ( u ) is better than best ) best = value ( u ) ; //若找到更好的結果就更新目前最佳值 if ( bound( u ) is better than best ) enqueue( Q , u ) ; //若一個節點是 promising 就把它加入佇列 } //尾端,以待下一層走訪時使用 }

演算法中的節點結構 struct node { int level ; //該節點在樹中的層級 int profit ; //目前累積的利益值 int weight ; //目前累積的物品重量值 }

使用Branch-and-bound之廣度優先搜尋法來解決0-1背包問題 問題:給定 n 個物件及其個別 weight 與 profit 值 (皆為正整數)。 給定 W 值。在總重量不超過 W 的條件下,找出一組物件 使其總獲益是最大的。 輸入:正整數 n 和 W。 陣列 w 與 p (索引均由 1 到 n,且根據p[i]/w[i]由大到小 排序過)。 輸出:正整數 maxprofit (即最大獲益)。 本演算法只找出最大獲益值,若想要輸出被挑選的物品編號,可 以自行修改。

Algorithm (續) void knapsack2 ( int n , const int p[] , const int w[] , int W , int& maxprofit ) { queue_of_node Q ; //宣告一個要存放欲走訪節點的佇列 node u , v ; initialize ( Q ) ; //初始時將佇列清空 v.level = 0 ; v.profit = 0 ; v.weight = 0 ; //將根節點初始化,並走訪它 maxprofit = 0 ; //初始化目前最佳值 enqueue ( Q , v ) ; //將根節點加入佇列尾端 while ( ! empty ( Q ) ) { //只要佇列中還有節點未走訪,就一直做下去 dequeue ( Q , v ) ; //從佇列前端取出欲走訪子節點的父節點 u.level = v.level + 1 ; //將 u 設成 v 的下一層子節點其中之一 u.weight = v.weight + w[ u.level ] ; //將 u 設成拿取下一層物品的子節點 u.profit = v.profit + p[ u.level ] ; if ( u.weight <= W && u.profit > maxprofit ) //若背包沒有爆掉,且獲 maxprofit = u.profit ; //得利益值大於最佳值,則更新它 if ( bound ( u ) > maxprofit ) enqueue ( Q , u ) ; //檢查 u 是否 promising u.weight = v.weight ; u.profit = v.profit ; //將 u 設成不拿取下一層物品 if ( bound ( u ) > maxprofit ) enqueue ( Q , u ) ; //的子節點,並檢查它 } //是否 promising }

Algorithm (續) float bound ( node u ) //回傳值就是 u 的 bound 值,呼叫者再把該值和目前最 { index j , k ; //佳值進行比較,以決定 u 是否為 promising int totweight ; float result ; if ( u.weight >= W ) return 0 ; //背包爆掉則傳回 bound = 0 else { result = u.profit ; //先把 bound 值初設為到 u 節點為止的總共獲益值 j = u.level + 1 ; totweight = u.weight ; while ( j <= n && totweight + w[j] <= W ) { totweight = totweight + w[j] ; //盡可能多拿取一些物品 result = result + p[j] ; //直到物品都拿光或是背包 j ++ ; //爆掉為止 } k = j ; if ( k <= n ) result = result + (W-totweight)*(p[k]/w[k]) ; //加上第 k 個 return result ; //物品的部份利益 下一頁

使用 Branch-and-bound 修剪法之最佳優先搜尋 profit weight bound 目前最佳值 maxprofit = 0 40 40 90 70 70 總共走訪了 11個節點, 最佳值=90 90 70 70 上一頁 90 90 下一頁

Best-first Branch-and-bound Algorithm void best_first_branch_and_bound ( state_space_tree T , number& best ) { priority_queue_of_node PQ ; //使用優先權佇列來存放欲走訪的節點 node u , v ; initialize ( PQ ) ; v = root of T ; //先走訪根節點,並初設目前最佳值 best best = value ( v ) ; insert ( PQ , v ) ; //將根節點插入優先權佇列中 while ( ! empty ( PQ ) ) { //只要優先權佇列中還有未走訪節點就繼續做 remove ( PQ , v ) ; //取出佇列中優先權 (即 bound) 最高的節點 if ( bound ( v ) is better than best ) //若它仍然還是 promising 則往 for ( each child u of v ) { //下層走訪它的每個子節點 if ( value ( u ) is better than best ) best = value ( u ) ; //更新最佳值 if ( bound ( u ) is better than best ) insert ( PQ , u ) ; //若 u 為 promising,則將 } // 它插入佇列中 }

使用 Branch-and-bound 並以最佳優先搜尋法來解決0-1背包問題 狀態空間樹中的節點結構 struct node { int level ; //節點在樹中的層級 int profit ; //到目前為止的總獲利值 int weight ; //到目前為止的總重量值 float bound ; //節點的最大獲利能力值 }

Algorithm (續) void knapsack3 ( int n , const int p[] , const int w[] , int W , int& maxprofit ) { priority_queue_of_node PQ ; node u , v ; initialize ( PQ ) ; v.level = 0 ; v.profit = 0 ; v.weight = 0 ; maxprofit = 0 ; v.bound = bound ( v ) ; //走訪根節點,並將它加入優先權佇列中 insert ( PQ , v ) ; while ( ! empty ( PQ , v ) ) { remove ( PQ , v ) ; //將 bound 值最高的節點取出來 if ( v.bound > maxprofit ) { //如果它仍然是 promising 就往下層展開 u.level = v.level + 1 ; u.weight = v.weight + w[ u.level ] ; u.profit = v.profit + p[ u.level ] ; //先走訪左子節點 if ( u.weight <= W && u.profit > maxprofit ) maxprofit = u.profit ; //更新最佳值

Algorithm (續) u.bound = bound ( u ) ; if ( u.bound > maxprofit ) //若左子節點 promising,則加 insert ( PQ , u ) ; //入優先權佇列中 u.weight = v.weight ; u.profit = v.profit ; //走訪右子節點 if ( u.bound > maxprofit ) //若右子節點 promising,則加 } bound 函式同 Algorithm 6.1,請自行參考。

優先權佇列變化圖 (0,0) (0,0) 115 (1,2) (1,1) (1,2) 115 82 40 40 (2,1) (2,1) (2,2) (1,2) 115 98 82 (2,2) (2,2) (1,2) (3,2) 70 70 98 82 80 (3,3) (3,3) (1,2) (3,2) 98 82 80 90 (1,2) : 82 < 90 nonpromising 70 90 70 (1,2) (3,2) 82 80 (3,2) : 80 < 90 nonpromising (3,2) 80 90 90

售貨員旅行問題 V1 V2 V4 V3 V3 V5 此相鄰矩陣代表了 所有頂點間皆有邊線 相連的圖 左圖的最佳旅程 10 7 V4 V3 V3 7 2 V5 此相鄰矩陣代表了 所有頂點間皆有邊線 相連的圖 左圖的最佳旅程 若城市數目很多,且是高度連結的,那麼使用回溯法會產 生太多旅行路線。因此改用branch-and-bound。

具有5個頂點的售貨員旅行問題的對應展開樹

計算狀態樹中每個節點的bound值 在這個問題中求的 bound 值是由該節點繼續往下層節點走訪 個節點才是 promising。 在任意旅程中,從每個頂點離開時,應採用其發出之最短邊 線: V1 minimum ( 14, 4, 10, 20 ) = 4 V2 minimum ( 14, 7, 8, 7 ) = 7 V3 minimum ( 4, 5, 7, 16 ) = 4 => 4+7+4+2+4=21 V4 minimum ( 11, 7, 9, 2 ) = 2 一個旅程的長度下限 V5 minimum ( 18, 7, 17, 4 ) = 4 就是這些最小值的總 和,但不代表真有這 條路徑,可能不存在

計算狀態樹中每個節點的bound值(續) V1 14 (已固定不能變動) V2 minimum ( 7 , 8 , 7 ) = 7 V3 minimum ( 4 , 7 , 16 ) = 4 V4 minimum ( 11 , 9 , 2 ) = 2 V5 minimum ( 18 , 7 , 17 , 4 ) = 4 bound 值 = 14+7+4+2+4 = 31

計算狀態樹中每個節點的bound值(續) V1 14 (已固定不能變動) V2 7 (已固定不能變動) V3 minimum ( 7 , 16 ) = 7 V4 minimum ( 11 , 2 ) = 2 V5 minimum ( 18 , 4 ) = 4 bound 值 = 14+7+7+2+4 = 34

狀態樹與 Bound 值 最佳解 = 無限大 37 31 31 31 31 30 30 31 31 5, 4

Algorithm 使用 Branch-and-bound 及最佳搜尋法來解決售貨員旅行問題 狀態樹中的節點結構 struct node { int level ; //節點在樹中的層級 ordered set path ; //到該節點為止的旅程路徑 number bound ; //該節點的旅程下限值 }

Algorithm (續) 問題:在一有向權重圖中找出一條最佳旅程。weight 必須為 非負整數。 由 1 到 n ,W[i][j] 代表由第 i 個頂點連到第 j 個頂點之 weight )。 該圖中的頂點數,n 。 輸出:變數 minlength,其值為一條最佳旅程的長度。 變數 opttour,其值為一條最佳旅程。

Algorithm (續) void travel2 ( int n , const number W[][] , ordered_set& opttour , number& minlength ) { priority_queue_of_node PQ ; node u , v ; initialize ( PQ ) ; v.level = 0 ; v.path = [1] ; // 令頂點 1 為起點 (即根節點) v.bound = bound( v ) ; //計算根節點的 bound 值 minlength = 無限大 ; //初始化最佳值 insert ( PQ , v ) ; while ( ! empty ( PQ ) ) { remove ( PQ , v ) ; //取出下一個要展開的節點 if ( v.bound < minlength ) { //如果它仍然是 promising u.level = v.level + 1 ; //開始計算它所有下一層節點 for ( all i such that 2 <= i <= n && i is not in v.path ) { u.path = v.path ; put i at the end of u.path ; //將 u 的路徑寫入

Algorithm (續) if ( u.level == n - 2 ) { //如果 u 在倒數兩層就直接處理 put index of only vertex not in u.path at the end of u.path ; //將最後一頂點加入路徑 put 1 at the end of u.path ; //把頂點 1 加入 if ( length ( u ) < minlength ) { minlength = length ( u ) ; //更新最佳值 opttour = u.path ; //更新最佳路徑 } else { //還不到旅程的終點 u.bound = bound ( u ) ; //計算 bound 值 if ( u.bound < minlength ) //若 promising insert ( PQ , u ) ; //放入優先權佇列中 } }