# 2020q3 Homework3 (dict)
contributed by < ` JulianATA ` >
## Xor Filter 論文與實作
* 在看論文的同時,就順手實作了程式碼。
* 全部程式碼大約 300 行。
* 論文閱讀+實作時間大約 11 小時。
* 程式碼通過Valgrind/Cppcheck
* 程式碼: 目前更新在 dict 專案當中,改進後將建立獨立 repository
* [xor_filter.h](https://github.com/JulianATA/dict/blob/master/xor_filter.h)
* [xor_filter.c](https://github.com/JulianATA/dict/blob/master/xor_filter.c)
* 所實作的程式碼中,使用到以下基本資料結構。
* stack: 基於 [lab0-c](https://github.com/sysprog21/lab0-c) 的程式碼改寫而成。
* 以下解說將搭配程式碼實作時候遇到困難與思考。
### 什麼是 Xor Filter ?
不論是 Xor Filter 或是 Bloom Filter 都是在不走訪全部元素的情況下,預測元素是否存在一個集合內。 具體的流程如下:
```graphviz
digraph R{
node [shape=record]
Equivalent [shape=diamond]
Element->{FingerprintHash Hash0 Hash1 Hash2}
{Hash0 Hash1 Hash2}->FingerprintSet
FingerprintSet->{Fingerprint0 Fingerprint1 Fingerpirnt2}
{Fingerprint0 Fingerprint1 Fingerpirnt2}->Xor
{FingerprintHash Xor}->Equivalent
Equivalent->{True False}
}
```
* 輸入元素到 Xor Filter
* 會作 4 次 Hash
* Hash0/1/2
* FingerprintHash
* 將 Hash0/1/2 分別作為 Index 放入 FingerprintSet ( 在論文中以 B 表示 )
* 得到 Fingerpint0/1/2
* 將三者作 Xor
* 將得到的 Fingerprint 與 FingerprintHash 作比對
* 相等就預測元素於集合內
在使用上,Xor Filter 相當簡單。困難的點在於如何建立 Xor Filter 。
### 建立 Xor Filter
* 原文: [Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters](https://arxiv.org/abs/1912.08258)
論文中的 Algorithm2 就是在建立整個 Xor Filter 的過程, Algorithm3 則是建立中最重要的環節,測試 Hash Function 0/1/2。
首先看 Algorithm2
```
Algorithm 2 Construction
Require: set of keys S
Require: a fingerprint function
repeat
pick three hash functions h 0 , h 1 , h 2 at random, independently from the fingerprint function
until map(S, h 0 , h 1 , h 2 ) returns success with a stack σ (see Algorithm 3)
B ← an array of size ⌊1.23 · |S |⌋ + 32 containing k-bit values (uninitialized)
assign(σ , B, h 0 , h 1 , h 2 ) (see Algorithm 4)
return the array B and the hash functions h 0 , h 1 , h 2
```
流程如下:
* 重複抽取三個 Hash function, 直到 Alogrithm3 測試成功
* 配置 Fingerprint Set B 空間
* 將 Stack 中的 Fingerprint 配置至 Fingerprint Set B 中。
* 即可獲得上述的 Xor Filter 流程中的 Fingerprint Set 與 Hash function 0/1/2
* 建立成功
> 實際上 Hash Funciton 0/1/2 取得的值比較類似 Index , 後面會解釋。
> 根據論文中的描述 Hash Function 0/1/2 需要具備以下性質:
>> Hash functions from U to integers in
>> $[0, \lfloor \frac{c}{3} \rfloor), [\lfloor \frac{c}{3}\rfloor, \lfloor \frac{2c}{3}\rfloor),[\lfloor \frac{2c}{3} \rfloor, c)$ respectively.
>
> [name=Julian Fang]
接下來,看一下 Algorithm3
```
Algorithm 3 Mapping Step (map)
Require: set of keys S, k-bit integer-valued hash functions h 0 , h 1 , h 2 .
let c ← ⌊1.23 · |S |⌋ + 32
H ← an array of size c containing a set of keys (values from S), initially empty
for all x in S do
append x to H [h 0 (x)]
append x to H [h 1 (x)]
append x to H [h 2 (x)]
end for
Q ← initially empty queue
for i = 0 to |H | do
if the set H [i] contains a single key then add i to Q endif
end for
σ ← initially empty stack
while queue Q is not empty do
remove an element i from the queue Q
if the set H [i] contains a single key then
let x be the sole value in the set H [i]
push the pair (x, i) on the stack σ
for j = 0 to 2 do
remove x from the set H [h j (x)]
if the set H [h j (x)] contains a single key then add h j (x) to Q endif
end for
end if
end while
return success and the stack σ if |σ | = |S |, else return failure
```
* 首先定義以下變數
* $S$ ( Set ): 所有元素的集合。
* $|S|$ : 集合中元素的數量。
* $c$ ( Capacity ): 整個 FingerprintSet B 的 大小,論文中為 $\lfloor{1.23\times|S|}\rfloor+32$。
* 實作上,我取最接近論文中的 3 的倍數作為 $c$ 。
* $H$ :一個暫時的 Fingerprint Set。
* $Q$ :紀錄 Element 與 index 用的。
* 我在實作上,沒有使用到 $Q$
* $\sigma$ :紀錄 Element 與 index 用的。
* 首先,所有elements 透過 Hash function 0/1/2 得到 index 0/1/2
* 並透過 index 存入 $H$ 中對應的 Set。
* 將所有 $H$ 中的 Set 掃過,當 Set 中 element 數量為 1 的時候, 存入 $Q$ 。
* 當$Q$ 中仍有元素的時候,作以下迴圈:
* 移除一個 $Q$ 中的元素。
* 將此元素與其 index,放入 stack $\sigma$
* 移除所有 $H$ 中的元素
* 當 Set 中 element 數量為 1 的時候, 存入 $Q$ 。
* 結束迴圈。
* 如果 Stack 中的元素數量等於 $|S|$
* 成立,則透過 Hash Function 0/1/2 建立 Filter
* 不成立,重新抽取 Hash Function 0/1/2
這個部份在做什麼呢? 在於確立找到 Hash Function 0/1/2 具有以下特性
* 所有於 Set $S$ 中的元素 $e_0$
* 透過 Hash Function 0/1/2 得到 index $i_{00}$, $i_{01}$, $i_{02}$
* 所有於 Set $S$ 中的元素 $e_1$
* 透過 Hash Function 0/1/2 得到 index $i_{10}$, $i_{11}$, $i_{12}$
* 只要於 Set 內,$e_0\neq e_1$則保證
* {$i_{00}$, $i_{01}$, $i_{02}$} $\neq${$i_{10}$, $i_{11}$, $i_{12}$}
* 可能部份相同,但不會出現完全一樣的情況。
## Xor Filter/Bloom Filter 效能比較
###### tags: `Cprogramming`