• 沒有找到結果。

隨機算法

N/A
N/A
Protected

Academic year: 2022

Share "隨機算法"

Copied!
55
0
0

加載中.... (立即查看全文)

全文

(1)

隨機算法

by HNO2

Credit by boook, qazwsxedcrfvtg14

(2)

大綱

• 什麼是隨機算法

• 數學工具複習

• 隨機算法例子

• 隨機算法實作

(3)

什麼是隨機算法

(4)

什麼是隨機算法?

• 是一種使用隨機函數或隨機數字的演算法。

• 相對於確定性演算法:給定特定輸入,每次執行時演算法的所 有步驟都會一樣,輸出也會一樣。

(5)

為什麼、何時要用隨機

• 隨機算法通常簡單很多,

實作起來比較方便

• 有些困難的問題

(例如 NP-complete 問題)

用隨機算法可以在一定時間 和錯誤率內,得到不錯的答案

(6)

用隨機的後果

• 影響正確率 ─ Monte Carlo Algorithms

• 可能程式不總是正確

→ 讓程式錯誤的機率特別低

• 影響執行時間 ─ Las Vegas Algorithms

• 執行時間不固定

→ 讓程式期望執行的時間不長

(7)

舉個栗子

• 你有一個長度為 N 的 01 字串,其中只有一個位置是 1。你想 要知道那個 1 在字串的哪個位置。

• 兩種隨機算法:

• 隨機挑選一個位置並輸出(Monte Carlo Algorithm)

• 每次隨機挑選字串中的一個位置,如果不是 1,那就再挑一次,直到挑 對為止(Las Vegas Algorithm)

• 以上兩種作法當然都不如直接掃過整個字串,等一下會給大家看 隨機算法比較好的例子。

(8)

數學工具複習

(9)

數學工具

• 既然會用到隨機,自然和機率脫離不了關係。

• 怎麼計算機率和期望值對分析隨機算法很重要!

(10)

計算隨機正確率

(11)

計算期望值

• 期望值 = (每次可能結果 × 出現機率) 的總和

• 例如有一顆六面的骰子,上面分別寫著 1~6 點,那投一顆骰子出現點 數的期望值是 ⅙ * (1 + 2 + 3 + 4 + 5 + 6) = 3.5

• 期望值可以線性相加

• 例如一次投 10 顆骰子,他們點數總和的期望值會是 3.5 * 10 = 35

(12)

隨機算法例子

(13)

例題 – 多項式相乘的結果

• 給你兩個 N 次多項式 A(x),B(x) 和一個 2N 次多項式 C(x)

,請問 A × B = C 是否成立?

(14)

例題 – 多項式相乘的結果

• 一個簡單的想法:每次代不同的 x=k 值進去,如果 A(k)B(k)≠C(k) 就判定相乘結果錯誤。

如果帶很多個值進去都一樣就判定相乘結果正確。

• 在正確答案是 Yes 的時候不會錯,但是在正確答案是 No 的時 候可能會錯

• 如果答案是 No 的話,答錯的機率會是多少呢?

(15)

例題 – 多項式相乘的結果

• 事實上可以證明,A(x)B(x)≠C(x) 卻有 A(k)B(k) = C(k) 的 k 不會超過 2N 個!

證明

• 因此我們可以選定一個大範圍的數字(例如 [0, 1000N)),從 裡面隨機挑幾個數字檢查,讓錯誤率很低

• 挑一個數字錯的機率最多只有 1/500

(16)

例題 – 矩陣相乘的結果

• 給定三個大小為 N 的 N × N 矩陣 A、B、C,請問 A × B = C 是否成立?(N <= 1000)

• 直接做是 O(N3),能不能更快一點?

(17)

例題 – 矩陣相乘的結果

• 讓 R 是一個隨機的 N × 1 的矩陣,那麼只需要檢查

• ((A×B))=(C)

((A×B)×R)=(C×R) (A×(B×R))=(C×R)

• 可以證明如果 R 的值域大小是 d,那 A×B≠C 卻有 (A×(B×R))=(C×R) 的機率最多是 1/d。證明

• 每次檢查時間複雜度是 O(N2)

(18)

例題 – 成雙成對

• 給出一個 N 個數字的序列 a1, a2, …, aN

現在有 Q 個詢問,每次詢問會給出 l, r,請問 al, …, ar 中是否每種數字都出現偶數次?

• N <= 1,000,000

• Q <= 1,000,000

(19)

例題 – 成雙成對

• XOR 好性質:

• X ⊕ Y ⊕ Z ⊕ Y ⊕ X ⊕ Z = 0

• XOR 不夠好性質:

• 1 ⊕ 2 ⊕ 3 = 0

• 也就是說,如果答案是 Yes 的話 XOR 起來一定是 0,反之不 一定成立

• 對於序列中每一種數字,隨機映射到 [0, 2k) 的一個正整數

• 對於每一筆詢問,檢查區間 XOR 是不是 0

• 每次錯誤率 1 / 2k 證明

(20)

例題 – 成堆成堆

• 給出一個 N 個數字的序列 a1, a2, …, aN

現在有 Q 個詢問,每次詢問會給出 l, r,請問 al, …, ar 中是否每種數字都出現 K 的倍數次?

• N <= 1,000,000

• Q <= 1,000,000

(21)

例題 – 成堆成堆

• 設計一個 Hash function:加法

• 改成在模 p 底下做事情避免溢位,其中 p 是一個大質數

• 單筆詢問答錯機率: 1/p

• 證明和前面幾題很像,可以自己試試看!

1 1 1 1 1 1 1

x x -2x x x -2x x

1 1 2 1 3 1 2 2 2 3

x x y -2x z x y -2y y z

(22)

例題 – 長度為 8 的簡單路

• 給 N 點 M 邊的有向圖,並給出兩點 S 和 T

• 請找一條 S 到 T 且含頭尾恰經過 8 個點的簡單路徑

簡單路徑:路徑中不存在兩個相同的點

• 8 <= N <= 100, 1 <= M <= 2000

(23)

例題 – 長度為 8 的簡單路

• 也就是說不含頭尾一共 6 個點 → O(n^6)

• 問題在簡單路徑上,不然就可以?

• 為什麼不是簡單路徑就可以做

(24)

例題 – 長度為 8 的簡單路

• 考慮 dp[i][j] 代表是否有可能從 S 恰好走 j 步到 i。

• 初始條件為 dp[S][0] = True,最後檢查 dp[T][7] = True 即可。

(25)

例題 – 長度為 8 的簡單路

• 那如果現在點上面有顏色呢?

• 給 N 點 M 邊的有向圖,並給出兩點 S 和 T。

圖上除了 S 和 T 之外每個點 i 都被塗上了顏色 Ci。 請找一條 S 到 T 且含頭尾恰經過 8 個點的簡單路徑,

並在路上蒐集滿 6 種不同的顏色。

• 1 <= N <= 100, 1 <= M <= 2000, 0 <= Ci <= 5

(26)

例題 – 長度為 8 的簡單路

• 考慮 dp[i][bitmask] 代表是否有可能從 S 走到 i,且恰好 蒐集了 bitmask 這個集合的顏色。

• 初始條件為 dp[S][0] = True,最後檢查 dp[T][26-1] = True 即可。

• 時間複雜度 O(2kM),k 是顏色數量

(27)

例題 – 長度為 8 的簡單路

(28)

例題 – 長度為 8 的簡單路

(29)

例題 - 最近點對

• 給定 N 個二維平面上面的點,請找出距離最近的兩個點。

• 這裡的距離是指直線距離

• 1 <= N <= 105

(30)

例題 - 最近點對

(31)

d/2~d d/2~d d/2~d d/2~d d/2~d d/2~d

0~d/2 0~d/2 0~d/2

d/2~d d/2~d

0~d/2 某個點 0~d/2

d/2~d d/2~d

0~d/2 0~d/2 0~d/2

d/2~d d/2~d d/2~d d/2~d d/2~d d/2~d

例題 - 最近點對

(32)

• 5.找到更近的最近點對:

• 更新 r = 新的最近點對 / 2

• 回到步驟三重來

例題 - 最近點對

(33)

例題 - 最近點對

(34)

Hash

• 目的:將一筆資料用一個函數壓縮起來,當要判斷兩筆資料是否 相同時,就判斷兩筆資料分別壓縮後的結果是否相同。

• 壓縮的函數不能有隨機成份

• 壓縮過程中會失去一些資訊,因此可能會有兩個不同的物品被 壓縮後產生一樣的結果。

(35)

Hash

• 如果有兩筆資料 A, B ,以及壓縮函數 f

• 錯誤的機率:

• f(A) != f(B),但 A = B。 => 不可能

• f(A) = f(B),但 A != B。 => 錯誤的機率

• 日常生活中的例子:SHA256、MD5 等。

(36)

Hash

• 譬如:

• f(x) = x % 2

• 所以我們會認為:

• 1 != 2, 因為 1 = f(1) != f(2) = 0

• 2 = 2, 因為 0 = f(2) = f(2) = 0

• 但是我們會認為:

• 4 = 2, 因為 0 = f(4) = f(2) = 0

(37)

f(A) = f(B),但 A != B

• 好的 hash function 要滿足「碰撞」

的機率足夠小,也就是以下機率要足夠低:

f(A) = f(B),但 A != B

(38)

Hash 的安全性

• 對於一個 Hash function f(x) 有三種安全性:

• Preimage resistance:

• 知道 f(x) 還原出 x

• Second preimage resistance:

• 在知道 x 和 f(x) 的情況下,找到另一組 y -> f(y) = f(x)

• Collision resistance:

• 找到一對 a, b 使得 f(a) = f(b)

• 不是所有應用都需要這三種安全性,視需求而定

(39)

Hash 的安全性 - 生日悖論

• 一個房間要多少人,則兩個人的生日相同的機率大於 50%?

23人

• 有 n 個人,每人都隨機地從 N 個特定的數中選擇出來一個數

• p(n) = 有兩個人選擇了同樣的數字。

• 這個機率有多大?

• 可以證明只需要大概 sqrt(N) 個人,有兩個人選到同一個數字 的機率就超過 50%。詳細說明

(40)

Rolling hash

• 一個簡單有效的 Hash function,又稱 RK 算法 (Rabin- Karp Algorithm/Rabin fingerprint)

• 核心

(41)

Rolling hash - 如果 C = 10

• S = 21334531

• M = 10000000000000000000000000000000000000000000

• H(1) = 2

• H(2) = 21

• H(3) = 213

• H(4) = 2133

• H(5) = 21334

• H(6) = 213345

• H(7) = 2133453

• H(8) = 21334531

(42)

Rolling hash

• 假設我們現在想要知道某一個區間的字串 [l,r] 的 Hash 值。

• 除了照定義以外有什麼好的方法嗎?

(43)

Rolling hash

• 可以把 Rolling Hash 想像成一個前高後低三角形

• H(1) = 2

• H(2) = 21

• H(3) = 213

• H(4) = 2133

• H(5) = 21334

(44)

Rolling hash

• 首先先預處理好字串每個前綴的 Rolling hash

(45)

Rolling hash

• 要刪除前面的字元

• S = 12345

• H(S) = 12345

• 12345 – 12000

= 345

(46)

Rolling hash

• 這樣之後就能直接算出任意一段的 Hash 值(參考程式碼)

• S = 21334

• H(1) = 2

• H(2) = 21

• H(3) = 213

• H(4) = 2133

• H(5) = 21334

• H(3~4)

= H(4) – H(2) * 100 = 33

(47)

隨機算法實作

(48)

如何產生隨機的數字

• 隨機算法的核心

• 大家都會(?)

rand()

srand(time(0))

• 這樣足夠安全嗎?

(49)

哪裡不安全

(50)

Note: 實際跑出來的值會因作業系統有所變化,在筆者筆電上跑出來的值分別是 500106.1 和 333232.2

(51)

不要直接使用 rand()

• random_shuffle() 可能使用 rand() 作為隨機數產生器。

rand() 的回傳範圍是 [0, RAND_MAX],而 RAND_MAX 只保證 最小是 32767!

• rand() 還有其他缺點,可以看這個影片

• 解決方法:

• rand() 很多次後將結果拼接成比較大的數字(不建議)

• 用其他亂數產生器,如 mt19937

• 追求更快效率 → 自己寫亂數

(52)

使用 mt19937

(53)

自己設計 random function

(54)

自己設計 random function

(55)

結束!

謝謝大家 OwO

參考文獻

相關文件

進行 18 以內的加法和減法口算 學生須透過口算解主要以圖像闡述的應用 題,並以橫式作記錄。.. 加法和減法的直式在學習單位 1N4

錯排數

自己設計 random function 自己設計 random function... 自己設計 random function 自己設計

自己設計 random function.. 自己設計

自己設計 random function.. 自己設計

• 在線 (online):程式/演算法 必須對前一個詢問或操作做出

• 在線 (online):程式/演算法 必須對前一個詢問或操作做出

RMQ(Range minimum