Michael Tsai 2013/10/17
超級電腦排程問題
需要交給超級電腦的工作若干
每樣工作有選定的開始與結束時間
如何選出一組可以執行的工作 ( 執行時 間不重疊 ), 使這些工作的數量最大 ?
時間
4
問題定義
集合
每一個工作有開始時間及結束時間
每個工作執行時間為
可以選兩個工作 , 其中一個工作的結束時間和 另外一個工作的開始時間一樣
當和可以被同時選入
工作已經照結束時間排好了 :
�
��
��
��
��
��
�先請出神聖的 dynamic pr ogramming 尚方寶劍
定義子問題 :
為完成後 , 開始前的所有工作集合
要找出中的最大可執行集合 , 假設其中包含
所以假設為的最佳解 , 則
S
��
S
��
�
�S
��Dynamic programming 尚方寶劍
Optimal Substructure:
證明中包含與的最佳解 ( 即欲證明為之最佳解 , 或為 之最佳解 )
S
��
�
�S
���
��
�
��
�
��最佳解�
�� 最佳解?Optimal Substructure
假設不是的最佳解 , 則表示有一使
但如果這樣
則此解之工作數目為 , 表示不是最佳解 ( 矛 盾 )
因此為的最佳解
S
��
�
�S
���
��
�
��
�
��最佳解�
�� 最佳解?�
��
�
��′
有 Optimal substructure, 可以用 DP 解 !
代表最佳解的工作數目
則
k 是我們的選擇 ( 不知道選哪一個 )
接著使用 top-down or bottom-up 方法填表即可
if
if
等等 , 我們需要用到尚方寶劍嗎 ?
如果我們可以證明我們知道呢 ?
Greedy Algorithm
某些問題 , 我們可以知道怎麼做選擇 !
此稱為 greedy choice
如果 greedy choice 為 optimal choice, 再加 上 optimal substructure, 我們就可以非常快 速的得到解 !
Greedy choice
�
��
S
��
�
�S
��不需要考慮所有的選擇 !
只需要直接解選擇之後的 subproblem!
怎麼做出選擇 ? ( 創造力 )
每次都選最早開始的工作
每次都選花最少時間的工作
每次都選跟其他最少衝突的工作
1
2 3
反例
反例
反例
Greedy choice
正確的 greedy choice( 之一 ): 選最早結束的 .
原因 : 越早結束 , 後面就越多時間讓其他工作執行 .
因為原本已經照排序好了 , 每次我們都選
接下來只需考慮結束以後才開始的所有工作
因為其他的結束時間 ,
�
1�
1�
��
�
�
�
證明 greedy choice 是正確的 !
定理 : 在某 subproblem 中的完成時間最早 , 則的某些最佳解 ( 如果有很多個 ) 中一定有
證明 : 假設是的某個最佳解 , 裡面完成時間 最早的是 .
1. 如果就是 , 則得證 .
2. 如果不是 , 則
所以可以把中的換成 .
更換後工作數目不變 , 和一樣多 , 因 此為另外一個最佳解 , 得證 .
�
��
� 其他的結論 : 有時候並不需要 DP!
DP 可以用 , 但是慢很多 . ( 殺雞不用尚方寶 劍 )
Greedy algorithm 通常使用 top-down 的方法 :
1. 根據目前知道的事情選出最好的選擇
2. 繼續解用了這個選擇之後的 subproblem
3. 重複以上一直到 subproblem 可以直接解掉
重點 : 請確定 ( 要證明 )greedy choice 一定 會出現在最佳解裡面 !!!
來個 pseudo-code
Recursive_Activity_Selector(s,f,k,n) m=k+1
while m<=n and s[m]<f[k]
m=m+1 if m<=n
return Recursive_Activity_Selector(s,f,m, n)
else
return
Θ(�)
選完 greedy choice 以後只剩下
一個 recursive call 在最後 : tail recursive f: 存結束時間的陣列
k: 目前要解的 subproblem 為
n: 總共有幾個 task (problem size)
來個 pseudo-code
Greedy_Activity_Selector(s,f) n=s.length
A={}
k=1
for m=2 to n if s[m]>=f[k]
A=
k=m
return A
Θ(�)
什麼問題可以使用 greedy algorit hm 來解 ?
1. 如果做出一個 choice 之後 , 可以找到剩下 要解的單一個 subproblem ( 定義好 subprobl em)
2. 有 greedy property. ( 必須證明最佳解裡面 一定有 greedy choice)
3. 有 optimal substructure ( 必須證明大問題 的最佳解裡面有小問題的最佳解 )
1.999. 決定要怎麼做 greedy choice.
0-1 背包問題
某店面有 n 個物品
各價值
小偷有一個可以裝 W 這麼重的背包
請問要偷走哪些東西可以使小偷拿走的東西總 價值最高 ?
fractional 背包問題
某店面有 n 個物品
各價值
小偷有一個可以裝 W 這麼重的背包
可以拿走”部分物品” ( 切物品的一部分 )
請問要偷走哪些東西可以使小偷拿走的東西總 價值最高 ?
背包問題的 optimal substructure
��� �
� 不比 W 重的最佳解拿掉
此為不比 W- 重 ,
使用除了外的物品的最佳解 定理 :
證明 : ( 適用於 0-1 & fractional 背包問 題 )1. 假設右邊的不是最佳解的話 ,
2. 則可以找到一最佳解 , 價值更高且不比 W- 重 . 3. 此解加上以後也還沒有超過 W,
4. 而且此解加上後總價值比左邊的價值還高 ( 矛盾 )
Fractional 背包問題的 greedy choice
把物品按照單位重量的價值來排序 ( 也就是 )
1. 選出單位重量價值最高的 (greedy choice).
2. 如果可用重量 (W) 比物品重量小 , 則把背包填滿 , 把物品多餘的部分捨棄 .
3. 如果可用重量比物品重量大 , 則繼續解子問題 : 可 用重量剩下 W- , 把已放入的物品從物品集合中去除 .
證明 fractional 背包問題有 greedy property
其實就是要證明 , ( 某些 ) 最佳解裡面有 greedy choice
通常使用的方法 :
1. 假設可以拿到最佳解 .
2. 最佳解裡面如果已經有 greedy choice 的話 , 則得證 .
3. 最佳解裡面如果沒有 greedy choice 的話 , 則想辦法 把最佳解裡面的一些東西和 greedy choice 互換 . 結 果發現這個新解跟 greedy choice 一樣好 ( 也是一個 最佳解 ) 或者發現這個新解更好 ( 矛盾 , 所以最佳 解裡面不可能沒有 greedy choice)
證明 fractional 背包問題有 greedy property
1. 假設可以拿到可用重量為 W 最佳解 . 假設為單位重量價 值最高者 ( 或其中之一 ).
2. 如果 , 則將最佳解之所有東西都換成 .
3. 如果 , 則將最佳解中的物品按照單位重量價值排序,取 其中重之最高價值物品 ( 可能包含部分 ) 與剩餘之交換 .
4. 因為為單位重量價值最高者 , 因此作了以上交換以後得 到之解 , 總價值只可能上升或相等 . 但原來已經為最 佳解 , 因此總價值只可能相等
5. 交換過後的解也是最佳解
因此至少很多種最佳解中其中幾種裡面有 greedy choic e.
此一 greedy choice 不適用於 0-1 背包問 題 !
反例 :
10 20 30
50
$6
0 $10 0
$12
$6 $5 0$4 單位重量價值
總價值
50 30 20
50 10 20
$22 0
$16 0
50 10 30
$18 0
最佳解 , 但是沒有 greedy choice!
注意 : 但是這不代表這個問 題一定沒有 greedy
property! 只是表示這個 greedy choice 不是正確的 !
因為如果有空間沒有用到 , 就會使單位重量的價值下 降 !!
Huffman codes
a b c d e f
出現次數 45k 13k 12k 16k 9k 5k
Fixed- length codewor d
000 001 010 011 100 101
Variable- length codewor d
0 101 100 111 1101 1100
總共需要 224 Kb 總共需要 300 Kb
越不常出現的字 , codeword 應該越長 ! 再省
25%
Prefix code
定義 : 某個 code 中 , 沒有任何一個 codeword 是另 外一個 codeword 的 prefix, 則稱為 prefix code.
Encode: “abc””0 101 100”
Decode: “0 101 100””abc”
使用右邊的 decoding tree, 走到 leaf 就解出一個字母
Prefix code 就不會有混淆的狀況 產生 .
例 : a=001 b=00 c=1
那看到 001 是 “ a” or “bc”?
注意 : 此非 binary search tree!
a
c b d
f e
0 1
0 1
0 1
0 1
0 1
如何產生最佳的 code 呢 ?
想要產生一棵 decode tree, 使得檔案大小能 最小 .
檔案大小 (cost):
Full binary tree
每個 non-leaf node 都有兩個 children
一個 optimal code 畫成的 decode tree 一定是 full binary tree.
a
c b d
f e
0 1
0 1
0 1
0 1
0 1
Huffman 發明了一種使用 greedy algorithm 產生 opt imal prefix code 的方法 , 稱為 Huffman Code
f:5 e:9 d:16 c:12 b:13 a:45 1
0 4 1
2
0 5 1 3
0 0 1
5 0 5
1 0 100
1
Pseudo-code
Huffman(C) n=|C|
Q=C
for i=1 to n-1
allocate a new node z z.left=Extract_Min(Q) z.right=Extract_Min(Q)
z.freq=z.left.freq+z.right.freq Insert(Q,z)
return Extract_Min(Q)
在 Priority Queue Q 插入 z:
在 Priority Queue Q 拿出 item:
起始 Priority queue:
證明最佳解裡面一定有 greedy choice
定理 : 假設所有的字都在集合 C 裡面 . 每個字 出現 的頻率為 c.freq. 假設 x 和 y 為 C 中頻率最低的 . 則一定有一組最佳的 code 是使得 x 和 y 的 codeword 長度一樣且只有最後一個 bit 不同 .
證明 :
1. 假設有 T 代表任一的最佳 code. 在其中假設 a 和 b 在 T 中為 depth 最大且為 sibling 的兩個字元 . 我 們可以假設 .
2. 因為” x 和 y 為 C 中頻率最低的” , 所以 .
e
3. 如果 x.freq=b.freq, 則 x.freq=a.freq=y.f req=b.freq. 如此的話可以直接得證 ( 可以 把 x 和 a 交換 , y 和 b 交換 , 則得到另一 op timal code, x 和 y 的 codeword 長度一樣且 只有最後一個 bit 不同 )
4. 如果 , 則先將 a, x 交換 ( 得到 T’), 再將 y , b 交換 ( 得到 T’’)
y
a b
x y
x b
a b
x y
a
T T’ T’’
+ +
類似方法可得到 , 因此 . 但因 T 已為最佳解 , 所以只可能 , 也是最佳解 ( 得證 )
y
a b
x y
x b
a
證明題目有 optimal substructure
�
�
′= �− { � , � } ∪ {� }
z 為一新字元 , z.freq=x.freq+y.freq
最佳解為 T’
z T’
x y
T 為 C 之最佳解
證明題目有 optimal substructure
�
�
′= �− { � , � } ∪ {� }
最佳解為 T’z T’
T
x y
T 為 C 之最佳解
則有 T’’ 為 C 之最佳 解
假設不是的話
將 x,y 替換成 z
得到T’’’
矛盾 !