カッコウフィルタ
$ カッコウフィルタの仕組みを教えて,ブルームフィルタは知っています
カッコウフィルタは、ブルームフィルタと同様に、ある要素が集合に含まれているかを高速かつ省スペースで判定するための確率的データ構造です。ブルームフィルタをご存知とのことですので、その知識を基にカッコウフィルタの仕組みと、ブルームフィルタとの主な違いを解説します。
カッコウフィルタの基本的な仕組み:「托卵」で場所を確保
カッコウフィルタは、「カッコウハッシュ」というハッシュテーブルのアルゴリズムを応用したものです。 その名前は、他の鳥の巣に卵を産み、元の卵を押し出してしまうカッコウの托卵行動に由来します。
主な構成要素は以下の通りです。
ハッシュテーブル: データを格納するための複数の「バケット」を持つ配列です。
フィンガープリント: 要素そのものではなく、要素から生成された短いハッシュ値(指紋)を格納します。これにより省スペースを実現しています。
2つのハッシュ関数: 1つの要素に対して、格納先の候補となる2つのバケットを計算するために使用します。
要素の挿入プロセス:
1. 2つの候補位置を計算: 新しい要素を挿入する際、2つの異なるハッシュ関数を使って、テーブル内の2つの候補バケットを計算します。
2. 空きスロットに格納: どちらかのバケットに空きスロットがあれば、そこに要素のフィンガープリントを格納します。
3. 「托卵」の実行: もし両方のバケットが埋まっている場合、どちらか一方のスロットに既にあるフィンガープリントを追い出します。
4. 連鎖的な移動: 追い出されたフィンガープリントは、自身のもう一方の候補バケットへ移動しようと試みます。もしその移動先も埋まっていれば、さらにそこにいるフィンガープリントを追い出します。この「追い出し」が連鎖的に発生することがあります。
5. リハッシュ: この追い出しの連鎖が一定回数以上続くと、テーブルが満杯に近いと判断され、テーブルの拡張(リハッシュ)が必要になる場合があります。
要素の検索:
検索は非常に高速です。対象の要素から2つの候補バケットを計算し、どちらかのバケットに一致するフィンガープリントが存在するかどうかを確認するだけです。
$ バケットの選択はどのように行われる?
はい、カッコウフィルタにおけるバケットの選択は、非常に巧妙かつ効率的な方法で行われます。この仕組みは「部分キーカッコウハッシング (Partial-key Cuckoo Hashing)」と呼ばれ、カッコウフィルタの大きな特徴である「要素の削除」と「追い出しの連鎖」を可能にするための鍵となります。
結論から言うと、2つの候補バケットは、元のデータとフィンガープリント(データの指紋)から計算され、特に2つ目のバケットは1つ目のバケット位置とフィンガープリントのハッシュ値の排他的論理和(XOR)を使って導き出されます。
具体的なバケット選択のアルゴリズム
ある要素 x を挿入する際の、2つの候補バケット i1 と i2 の計算方法は以下の通りです。
1. フィンガープリントを生成する
まず、要素 x から短いハッシュ値であるフィンガープリント f を計算します。
f = fingerprint(x)
2. 1つ目の候補バケット i1 を計算する
次に、元の要素 x 全体をハッシュ関数に通し、1つ目の候補バケットのインデックス i1 を計算します。
i1 = hash(x)
3. 2つ目の候補バケット i2 を計算する
ここが最も重要な部分です。i1 と、フィンガープリント f のハッシュ値を**排他的論理和(XOR)**で計算します。
i2 = i1 XOR hash(f)
なぜXOR(排他的論理和)を使うのか?
このXORを使った計算方法には、非常に大きなメリットがあります。それは**「可逆性」**です。
XORには A XOR B = C ならば A XOR C = B となる性質があります。これをバケットの計算式に当てはめてみましょう。
i2 = i1 XOR hash(f)
この式は、以下のように変形できます。
i1 = i2 XOR hash(f)
これは何を意味するのでしょうか?
追い出し(托卵)の効率化: カッコウフィルタでは、あるバケットからフィンガープリント f を追い出す際、その f が次に行くべき「もう一方の候補バケット」を計算する必要があります。 ブルームフィルタと違い、カッコウフィルタは元の要素 x を保存していません。 しかし、このXORの仕組みを使えば、追い出されたフィンガープリント f 自身と、**それが「今いた場所」のインデックス(i1 または i2)**さえ分かれば、元の要素 x を知らなくても、もう一方の候補バケットを即座に計算できるのです。
この巧妙な仕組みにより、カッコウフィルタは元のデータを保持することなく、フィンガープリントだけで効率的な「追い出し」の連鎖を実現し、高い空間効率を保ちながら要素の挿入や削除を可能にしているのです。
わかった気がする