Esercizio - Dimensionamento di un filtro di Bloom e fingerprint di documenti
Teoria: Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprintHashing con catene e costo atteso 1+alfa; famiglie universali (probabilità di collisione al più 1/m) e costruzione h(x)=((ax+b) mod p) mod m con dimostrazione; hashing perfetto a due livelli (spazio lineare, ricerca O(1) nel caso peggiore); filtri di Bloom: falsi positivi (1-e^(-kn/m))^k e k ottimo (m/n) ln 2; fingerprint di stringhe e numero di bit necessari.Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint → (filtri di Bloom, fingerprint), Palline e urne - compleanno, carico massimo e approssimazione di PoissonModello palline e urne (m palline, n urne, scelte indipendenti e uniformi): paradosso del compleanno con soglia sqrt(2 n ln 2), urne vuote attese n e^(-m/n), carico massimo ln n / ln ln n con dimostrazione (first moment e union bound), approssimazione di Poisson con il fattore e sqrt(m), potere delle due scelte (ln ln n / ln 2).Palline e urne - compleanno, carico massimo e approssimazione di Poisson → (collisioni).
Testo. Un crawler deve ricordare indirizzi già visitati con un filtro di Bloom, accettando una frazione di falsi positivi (pagine ritenute già viste ma nuove) del .
- Quanti bit per elemento e quanti bit totali servono, e quale ? Quanti byte? Confrontare con la memorizzazione di chiavi da bit.
- Calcolare il tasso di falsi positivi esatto per con questo .
- Con bit calcolare il ottimo intero e il tasso di falsi positivi; con idem.
- Dimostrare che il che minimizza è .
- Fingerprint. Si vogliono identificare documenti con una fingerprint di bit, con probabilità di una collisione tra due documenti qualsiasi . Quanti bit? E per confrontare due stringhe di lunghezza con la fingerprint polinomiale modulo qual è la probabilità di errore massima?
- Verificare con una simulazione il tasso di falsi positivi del punto 2 (modello idealizzato: ogni elemento accende bit uniformi).
Soluzione
1. Dimensionamento. Il tasso ottimo è , quindi bit byte KiB. Il ottimo è , quindi . Le chiavi da bit occupano byte: il filtro è volte più piccolo.
2. Tasso esatto. Con :
Il minimo è a con , appena sopra l' per l'arrotondamento di ; chi vuole stare sotto l' aggiunge un po' di bit ().
3. Altri rapporti. Con : ottimo reale e (con : ; : ; : ). Con : reale , il minimo intero è con (: ; : ). Il minimo è piatto: scostarsi di uno da ottimo costa pochissimo.
4. Ottimizzazione. Sia (frazione di bit a ): allora e . Bisogna massimizzare su . È simmetrica () e si annulla in (dove i due termini sono uguali), che per simmetria è un estremo; a si ha e dentro: è un massimo, con . Quindi , e . Con ottimo metà dei bit è a .
5. Fingerprint. Il numero di coppie è e ognuna collide con probabilità : per l'union bound . Si vuole : , , quindi (con : ; : ; : ). Per due stringhe di lunghezza la fingerprint con uniforme in : la differenza è un polinomio non nullo di grado , che ha al più radici in (un polinomio di grado ne ha al più ), quindi .
6. Simulazione. Con , e interrogazioni di elementi non inseriti (modello idealizzato): : (formula ); : (formula ); : (formula ). La frazione di bit a con è (attesa ). La simulazione conferma la formula entro l'errore statistico ().
Codice di verifica
import numpy as np
from math import ceil, log, log2, exp
n = 10 ** 5
m = ceil(n * log2(100) / log(2)) # 958506
f = lambda m, k, n=n: (1 - (1 - 1 / m) ** (k * n)) ** k
print(m, m / 8, [round(f(m, k), 5) for k in (5, 6, 7, 8, 10)])
print([round(f(10 * n, k), 5) for k in (3, 6, 7, 8)], [round(f(8 * n, k), 5) for k in (5, 6, 7)])
print([10 ** 12 / 2 ** (b + 1) for b in (48, 49, 64)], 999999 / (2 ** 61 - 1))
rng = np.random.default_rng(9)
for k in (6, 7, 10):
bit = np.zeros(m, dtype=bool)
bit[rng.integers(0, m, size=(n, k)).ravel()] = True # ogni elemento accende k bit
q = rng.integers(0, m, size=(300_000, k)) # interrogazioni di elementi nuovi
print(k, bit.mean(), bit[q].all(axis=1).mean())Risultato: 958506 119813.25 [0.01109, 0.01014, 0.01004, 0.01053, 0.013], [0.01741, 0.00844, 0.00819, 0.00846] [0.02168, 0.02158, 0.02293] e [0.00178, 0.00089, 2.7e-08] 4.3e-13 (limiti per e fingerprint di stringhe), poi tre righe con la frazione di bit a e il tasso osservato (-).
Versione ripasso
- Dimensionamento (, ): bit/elemento, bit ( byte, KiB), ; chiavi da bit: byte ( volte di più) (Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprintHashing con catene e costo atteso 1+alfa; famiglie universali (probabilità di collisione al più 1/m) e costruzione h(x)=((ax+b) mod p) mod m con dimostrazione; hashing perfetto a due livelli (spazio lineare, ricerca O(1) nel caso peggiore); filtri di Bloom: falsi positivi (1-e^(-kn/m))^k e k ottimo (m/n) ln 2; fingerprint di stringhe e numero di bit necessari.Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint →).
- Tasso esatto con quel : dà . Con : , (: ); con : , .
- Ottimo. , ; è simmetrica, massima in con valore : , , metà dei bit a .
- Fingerprint. ; e : , (: ; : ). Stringhe di lunghezza con , : errore (polinomio non nullo di grado , al più radici).
- Simulazione (modello ideale, interrogazioni): dà ; bit a con : .
- Errori tipici. Usare non intero senza arrotondare; confondere (bit totali) con ; dimenticare che il filtro non ha falsi negativi ma non supporta la cancellazione.