Salta al contenuto
Note per Studenti Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint

Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint

In questa pagina 6

Una tabella hash (Tabelle hashTabella hash per implementare una mappa: funzione hash = hash code + compression function, bucket array, separate chaining; hash code per numeri e stringhe (polynomial, cyclic shift), division e MAD; load factor, complessità al caso pessimo Theta(n) e medio O(1+lambda), rehashing; esempio svolto con inserimenti e collisioni.Tabelle hash →) è veloce in media solo se i dati non sono scelti da un avversario contro la funzione hash. Con un'unica funzione fissa hh esistono insiemi di chiavi che finiscono tutte nello stesso bucket. Rimedio: scegliere hh a caso da una famiglia, indipendentemente dai dati. Il costo atteso si calcola sulla scelta di hh, non sull'input: vale per ogni insieme di chiavi, come per gli algoritmi randomizzati di Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazioneUn algoritmo randomizzato usa bit casuali indipendenti; la probabilità è sulle scelte dell'algoritmo, mai sull'input (garanzia per ogni input). Las Vegas: sempre corretto, tempo aleatorio (conta il tempo atteso). Monte Carlo: tempo fisso, risposta sbagliata con probabilità limitata; errore unilaterale (RP: accetta solo se x sta nel linguaggio, accetta con prob almeno 1/2) o bilaterale (BPP: giusto con prob almeno 2/3). ZPP = RP ∩ co-RP = Las Vegas con tempo atteso polinomiale. Amplificazione: unilaterale, k ripetizioni indipendenti, errore (1-p)^k ≤ e^(-pk), serve k ≥ ln(1/ε)/p; bilaterale, voto di maggioranza su k esecuzioni, errore binomiale esatto, esponenziale in k (Chernoff, e^(-k/18) per p=2/3) mentre Chebyshev dà solo 8/k. Las Vegas -> Monte Carlo: interrompere a c volte il tempo atteso (Markov, errore ≤ 1/c). Monte Carlo -> Las Vegas: solo se la risposta si verifica in fretta. Esempio: Miller-Rabin, errore ≤ 1/4 per esecuzione.Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazione →. Prerequisiti: 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 →, Linearità del valore atteso e variabili indicatriciLa linearità $E[X+Y]=E[X]+E[Y]$ vale sempre, anche senza indipendenza; con le variabili indicatrici ($E[I_A]=P(A)$) trasforma un conteggio in una somma di probabilità. Applicazioni: attesa del primo successo $1/p$, collezionista di figurine $nH_n$, punti fissi di una permutazione (media $1$), record (media $H_n$), inversioni ($n(n-1)/4$), attesa condizionata, identità di Wald $E[S_N]=E[N]E[X]$.Linearità del valore atteso e variabili indicatrici →.

Catene e costo atteso

Si memorizzano nn chiavi in mm bucket, ognuno con una lista (separate chaining). Il fattore di carico è α=n/m\alpha=n/m. Se hh fosse una funzione veramente casuale (h(x)h(x) uniforme e indipendente per ogni xx, cioè il modello palline e urne) la ricerca di una chiave assente confronterebbe in media α\alpha elementi (la lunghezza media di una lista), una ricerca riuscita 1+n−12m1+\frac{n-1}{2m}. Ma una funzione casuale da un universo UU a [m][m] richiede ∣U∣log⁡2m|U|\log_2 m bit per essere memorizzata: inutilizzabile. Serve una famiglia piccola che dia la stessa garanzia sulle coppie di chiavi, che è tutto ciò che interessa per i confronti.

Famiglie universali

Definizione (famiglia universale). Una famiglia H\mathcal H di funzioni U→[m]U\to[m] è universale se per ogni coppia di chiavi x≠yx\ne y, scegliendo h∈Hh\in\mathcal H uniformemente a caso, Ph(h(x)=h(y))≤1m.P_h\bigl(h(x)=h(y)\bigr)\le\frac1m.

È la probabilità di collisione di una funzione casuale ideale, richiesta solo per le coppie.

Teorema (catene). Sia H\mathcal H universale, S⊆US\subseteq U un insieme di nn chiavi e hh scelta a caso. Per una chiave xx il numero atteso di chiavi di S∖{x}S\setminus\{x\} nel suo bucket è al più n−1m\frac{n-1}m se x∈Sx\in S e nm\frac nm se x∉Sx\notin S. Quindi ricerca, inserimento e cancellazione costano in media O(1+α)O(1+\alpha).

Dimostrazione. Gli indicatori Iy=1I_y=1 se h(y)=h(x)h(y)=h(x), con y∈S∖{x}y\in S\setminus\{x\}: E[Iy]≤1mE[I_y]\le\frac1m per la definizione. Per la linearità (Linearità del valore atteso e variabili indicatriciLa linearità $E[X+Y]=E[X]+E[Y]$ vale sempre, anche senza indipendenza; con le variabili indicatrici ($E[I_A]=P(A)$) trasforma un conteggio in una somma di probabilità. Applicazioni: attesa del primo successo $1/p$, collezionista di figurine $nH_n$, punti fissi di una permutazione (media $1$), record (media $H_n$), inversioni ($n(n-1)/4$), attesa condizionata, identità di Wald $E[S_N]=E[N]E[X]$.Linearità del valore atteso e variabili indicatrici →), senza alcuna ipotesi di indipendenza, E[∑yIy]≤n−1mE[\sum_yI_y]\le\frac{n-1}m. Con la chiave stessa la lista ha 1+n−1m1+\frac{n-1}m elementi. □\square

Lista più lunga. Se LL chiavi cadono nello stesso bucket, ci sono (L2)\binom L2 coppie in collisione; il numero atteso di coppie in collisione è ≤(n2)1m\le\binom n2\frac1m. Con m=nm=n per Markov P(lista≥L)≤(n−1)/2L(L−1)/2=n−1L(L−1)P(\text{lista}\ge L)\le\frac{(n-1)/2}{L(L-1)/2}=\frac{n-1}{L(L-1)}, che per L=2nL=2\sqrt n vale circa 14\frac14. La sola universalità garantisce quindi liste massime O(n)O(\sqrt n); per il Θ(ln⁡n/ln⁡ln⁡n)\Theta(\ln n/\ln\ln n) del modello ideale servono famiglie con più indipendenza (fuori programma).

La famiglia ((ax+b) mod p) mod m((ax+b)\bmod p)\bmod m

Teorema (costruzione). Siano pp un primo con p≥∣U∣p\ge|U|, chiavi U={0,…,p−1}U=\{0,\dots,p-1\} e, per a∈{1,…,p−1}a\in\{1,\dots,p-1\}, b∈{0,…,p−1}b\in\{0,\dots,p-1\}, ha,b(x)=((ax+b) mod p) mod m.h_{a,b}(x)=\bigl((ax+b)\bmod p\bigr)\bmod m. La famiglia H={ha,b}\mathcal H=\{h_{a,b}\}, di p(p−1)p(p-1) funzioni, è universale.

Dimostrazione. Fissate x≠yx\ne y. Si pone r=(ax+b) mod pr=(ax+b)\bmod p e s=(ay+b) mod ps=(ay+b)\bmod p. (1) r≠sr\ne s: altrimenti a(x−y)≡0(modp)a(x-y)\equiv0\pmod p, impossibile perché pp è primo e né aa né x−yx-y sono multipli di pp. (2) La mappa (a,b)↦(r,s)(a,b)\mapsto(r,s) è una biiezione tra le p(p−1)p(p-1) coppie (a,b)(a,b) e le p(p−1)p(p-1) coppie ordinate (r,s)(r,s) con r≠sr\ne s (si risolve il sistema lineare in Zp\mathbb Z_p: a=(r−s)(x−y)−1a=(r-s)(x-y)^{-1}, b=r−axb=r-ax), quindi scegliere (a,b)(a,b) a caso equivale a scegliere (r,s)(r,s) a caso con r≠sr\ne s. (3) Si ha collisione se r≡s(modm)r\equiv s\pmod m. Per ogni rr i valori s≠rs\ne r con s≡r(modm)s\equiv r\pmod m sono al più ⌈p/m⌉−1≤p−1m\lceil p/m\rceil-1\le\frac{p-1}m (i valori di [0,p−1][0,p-1] nella stessa classe di resto di rr sono al più ⌈p/m⌉\lceil p/m\rceil, tolto rr stesso). Dunque le coppie in collisione sono al più p⋅p−1mp\cdot\frac{p-1}m su p(p−1)p(p-1): probabilità ≤1m\le\frac1m. □\square

Esempio (p=17p=17, m=5m=5, a=3a=3, b=4b=4). h(x)=((3x+4) mod 17) mod 5h(x)=((3x+4)\bmod17)\bmod5.

xx 3x+43x+4 mod 1717 mod 55
22 1010 1010 00
55 1919 22 22
88 2828 1111 11
99 3131 1414 44
1212 4040 66 11
1515 4949 1515 00

Collidono 22 e 1515 (bucket 00) e 88 e 1212 (bucket 11): su 66 chiavi in 55 bucket è inevitabile (principio dei cassetti). Verifica esaustiva con tutte le p(p−1)p(p-1) funzioni: per p=7p=7, m=3m=3 la coppia (1,2)(1,2) collide in 1010 funzioni su 4242 (0,2380{,}238) e il caso peggiore su tutte le coppie è 521=0,238≤13\frac5{21}=0{,}238\le\frac13; per p=17p=17, m=5m=5 il caso peggiore è 21136=0,154≤15\frac{21}{136}=0{,}154\le\frac15. Il limite 1m\frac1m non è stretto ma regge sempre.

Per chiavi più grandi di pp (stringhe, interi a 6464 bit) si usa pp primo maggiore dell'universo, per esempio il primo di Mersenne 261−12^{61}-1 nel codice sotto. La variante con a∈{0,…,p−1}a\in\{0,\dots,p-1\} e senza il  mod m\bmod m finale è a coppie indipendente: (h(x),h(y))(h(x),h(y)) è uniforme su Zp2\mathbb Z_p^2, quindi vale anche P(h(x)=i, h(y)=j)=1/p2P(h(x)=i,\,h(y)=j)=1/p^2.

Hashing perfetto (statico, due livelli)

Per un insieme fisso SS di nn chiavi si vuole una ricerca in tempo O(1)O(1) nel caso peggiore con spazio O(n)O(n).

Algoritmo (due livelli).

  1. Primo livello. Si sceglie h∈Hh\in\mathcal H con m=nm=n bucket; il bucket ii contiene nin_i chiavi. Si ripete finché ∑ini2≤4n\sum_in_i^2\le4n.
  2. Secondo livello. Per ogni bucket con ni≥1n_i\ge1 si sceglie hih_i da una famiglia universale su mi=ni2m_i=n_i^2 celle, ripetendo finché è priva di collisioni sulle nin_i chiavi del bucket.
  3. Ricerca di xx: si calcola i=h(x)i=h(x) e si guarda la cella hi(x)h_i(x) del bucket ii: due accessi.

Analisi. Secondo livello: con mi=ni2m_i=n_i^2 il numero atteso di coppie in collisione è ≤(ni2)1ni2<12\le\binom{n_i}2\frac1{n_i^2}<\frac12, quindi per Markov P(almeno una collisione)<12P(\text{almeno una collisione})<\frac12: servono in media meno di 22 tentativi. Primo livello: ∑ini2=n+2C\sum_in_i^2=n+2C con CC = numero di coppie in collisione, perché ni2=ni+2(ni2)n_i^2=n_i+2\binom{n_i}2 e ∑ni=n\sum n_i=n. Con m=nm=n: E[C]≤(n2)1n=n−12E[C]\le\binom n2\frac1n=\frac{n-1}2, quindi E[∑ni2]≤n+(n−1)=2n−1E[\sum n_i^2]\le n+(n-1)=2n-1. Per Markov P(∑ni2≥4n)≤2n−14n<12P(\sum n_i^2\ge4n)\le\frac{2n-1}{4n}<\frac12: anche qui meno di 22 tentativi. Lo spazio è n+∑ni2≤5nn+\sum n_i^2\le5n: lineare.

Esempio (p=97p=97, S={5,17,29,41,48,62,73,90}S=\{5,17,29,41,48,62,73,90\}, n=m=8n=m=8). Primo livello h(x)=((3x+1) mod 97) mod 8h(x)=((3x+1)\bmod97)\bmod8: 5↦16↦05\mapsto16\mapsto0; 29↦88↦029\mapsto88\mapsto0; 48↦145 mod 97=48↦048\mapsto145\bmod97=48\mapsto0; 62↦187 mod 97=90↦262\mapsto187\bmod97=90\mapsto2; 73↦220 mod 97=26↦273\mapsto220\bmod97=26\mapsto2; 41↦124 mod 97=27↦341\mapsto124\bmod97=27\mapsto3; 17↦52↦417\mapsto52\mapsto4; 90↦271 mod 97=77↦590\mapsto271\bmod97=77\mapsto5. Bucket: 0:{5,29,48}0:\{5,29,48\}, 2:{62,73}2:\{62,73\}, 3:{41}3:\{41\}, 4:{17}4:\{17\}, 5:{90}5:\{90\}, gli altri vuoti. ∑ni2=9+4+1+1+1=16≤32\sum n_i^2=9+4+1+1+1=16\le32. Secondo livello con hi(x)=((2x+1) mod 97) mod mih_i(x)=((2x+1)\bmod97)\bmod m_i: bucket 00 ha m0=9m_0=9 e le posizioni (11 mod 9, 59 mod 9, 97 mod 97 mod 9)=(2,5,0)(11\bmod9,\ 59\bmod9,\ 97\bmod97\bmod9)=(2,5,0), tutte diverse; bucket 22 ha m2=4m_2=4 e 62↦125 mod 97=28↦062\mapsto125\bmod97=28\mapsto0, 73↦147 mod 97=50↦273\mapsto147\bmod97=50\mapsto2. I bucket singoli usano una cella. Spazio totale 8+9+4+1+1+1=248+9+4+1+1+1=24 celle per 88 chiavi.

Filtri di Bloom

Definizione (filtro di Bloom). Un vettore di mm bit, inizialmente 00, e kk funzioni hash h1,…,hk:U→[m]h_1,\dots,h_k:U\to[m]. Inserimento di xx: si pongono a 11 i bit h1(x),…,hk(x)h_1(x),\dots,h_k(x). Interrogazione di xx: si risponde "presente" se tutti i kk bit sono 11, "assente" altrimenti.

Nessun falso negativo: un elemento inserito ha i suoi kk bit a 11 per sempre. Può esserci un falso positivo: un elemento mai inserito i cui kk bit sono stati posti a 11 da altri. Non si possono cancellare elementi (si userebbe un vettore di contatori). Occupa mm bit indipendentemente dalla lunghezza delle chiavi.

Teorema (falsi positivi). Dopo nn inserimenti, con kk funzioni indipendenti e uniformi,

  • un bit specifico è ancora 00 con probabilità (1−1m)kn≈e−kn/m\bigl(1-\frac1m\bigr)^{kn}\approx e^{-kn/m};
  • un elemento non inserito è un falso positivo con probabilità f≈(1−e−kn/m)kf\approx\Bigl(1-e^{-kn/m}\Bigr)^k.
  • Per m,nm,n fissati ff è minima per k=mnln⁡2k=\frac mn\ln2, e vale allora f=2−k=(0,6185)m/nf=2^{-k}=(0{,}6185)^{m/n}.

Dimostrazione. Un bit non viene toccato da una data scelta con probabilità 1−1m1-\frac1m, e ci sono knkn scelte indipendenti (da cui il primo punto, con (1−1m)kn≈e−kn/m(1-\frac1m)^{kn}\approx e^{-kn/m}). Sia q=e−kn/mq=e^{-kn/m} la frazione attesa di bit a 00. L'elemento è un falso positivo se tutti i suoi kk bit sono 11: ≈(1−q)k\approx(1-q)^k (le posizioni nel filtro sono quasi indipendenti; la formula esatta sulla posizione dei bit è un po' più grande ma la differenza è trascurabile per mm grande). Per ottimizzare si scrive k=−mnln⁡qk=-\frac mn\ln q e ln⁡f=kln⁡(1−q)=−mn ln⁡q ln⁡(1−q).\ln f=k\ln(1-q)=-\frac mn\,\ln q\,\ln(1-q). Il prodotto ln⁡qln⁡(1−q)\ln q\ln(1-q) è simmetrico in q↔1−qq\leftrightarrow1-q e ha l'unico punto di massimo in q=12q=\frac12, dove vale ln⁡22\ln^22. Quindi ff è minimo per q=12q=\frac12, cioè per e−kn/m=12e^{-kn/m}=\frac12, k=mnln⁡2k=\frac mn\ln2, e ln⁡f=−mnln⁡22\ln f=-\frac mn\ln^22, cioè f=2−(m/n)ln⁡2=(0,6185)m/nf=2^{-(m/n)\ln2}=(0{,}6185)^{m/n}. Con kk ottimo metà dei bit è a 11. □\square

Dimensionamento. Dal f=2−kf=2^{-k} ottimo si ricava mn=log⁡2(1/f)/ln⁡2=1,44log⁡2(1/f)\frac mn=\log_2(1/f)/\ln2=1{,}44\log_2(1/f) bit per elemento: 4,794{,}79 per f=10%f=10\%, 9,599{,}59 per 1%1\%, 14,3814{,}38 per 0,1%0{,}1\%. Ogni bit in più per elemento moltiplica i falsi positivi per 0,61850{,}6185.

Esempio (n=1000n=1000, m=10 000m=10\,000). Con k=7k=7 (mnln⁡2=6,93\frac mn\ln2=6{,}93): f=(1−e−0,7)7=0,00819f=(1-e^{-0{,}7})^7=0{,}00819; una simulazione con 200 000200\,000 interrogazioni dà 0,00810{,}0081 e una frazione di bit a 11 pari a 0,5030{,}503 (attesa 0,5030{,}503). Con k=3k=3 sarebbe 0,01740{,}0174, con k=5k=5 0,00940{,}0094, con k=8k=8 0,00850{,}0085: il minimo è piatto e un kk intero vicino a 6,936{,}93 basta.

m/nm/n kk ottimo (intero) ff
44 33 0,1470{,}147
88 66 0,02160{,}0216
1010 77 0,00820{,}0082
1212 88 0,00310{,}0031
1616 1111 0,000460{,}00046

Uso tipico: filtro davanti a un archivio lento, che si interroga solo se il filtro risponde "presente".

Fingerprint

Definizione (fingerprint). Una fingerprint di bb bit di un oggetto grande xx è ϕ(x)=h(x)∈{0,1}b\phi(x)=h(x)\in\{0,1\}^b con hh scelta a caso; si usa ϕ(x)=ϕ(y)\phi(x)=\phi(y) come test (probabilistico) per x=yx=y. Se x=yx=y le fingerprint coincidono sempre; se x≠yx\ne y possono coincidere per caso (errore unilaterale, Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazioneUn algoritmo randomizzato usa bit casuali indipendenti; la probabilità è sulle scelte dell'algoritmo, mai sull'input (garanzia per ogni input). Las Vegas: sempre corretto, tempo aleatorio (conta il tempo atteso). Monte Carlo: tempo fisso, risposta sbagliata con probabilità limitata; errore unilaterale (RP: accetta solo se x sta nel linguaggio, accetta con prob almeno 1/2) o bilaterale (BPP: giusto con prob almeno 2/3). ZPP = RP ∩ co-RP = Las Vegas con tempo atteso polinomiale. Amplificazione: unilaterale, k ripetizioni indipendenti, errore (1-p)^k ≤ e^(-pk), serve k ≥ ln(1/ε)/p; bilaterale, voto di maggioranza su k esecuzioni, errore binomiale esatto, esponenziale in k (Chernoff, e^(-k/18) per p=2/3) mentre Chebyshev dà solo 8/k. Las Vegas -> Monte Carlo: interrompere a c volte il tempo atteso (Markov, errore ≤ 1/c). Monte Carlo -> Las Vegas: solo se la risposta si verifica in fretta. Esempio: Miller-Rabin, errore ≤ 1/4 per esecuzione.Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazione →).

Quanti bit. Con nn oggetti distinti e fingerprint a bb bit non devono esserci due collisioni: è il compleanno con 2b2^b urne (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 →), e per l'union bound P(una collisione tra i n)≤(n2)2−b<n22b+1.P(\text{una collisione tra i }n)\le\binom n2 2^{-b}<\frac{n^2}{2^{b+1}}. Per n=106n=10^6 documenti e probabilità di errore ≤10−3\le10^{-3} serve 2b≥10122⋅10−3=5⋅10142^b\ge\frac{10^{12}}{2\cdot10^{-3}}=5\cdot10^{14}, cioè b=49b=49 bit (b=48b=48 dà 0,00180{,}0018). Con b=64b=64 l'errore è 2,7⋅10−82{,}7\cdot10^{-8}; con b=32b=32 la collisione è praticamente certa.

Fingerprint di una stringa. Per s=s0s1…sℓ−1s=s_0s_1\dots s_{\ell-1} e pp primo si sceglie x∈Zpx\in\mathbb Z_p a caso e si pone ϕ(s)=∑isixi mod p\phi(s)=\sum_is_ix^i\bmod p (valutazione in xx del polinomio che ha come coefficienti i caratteri). Se s≠ts\ne t della stessa lunghezza ℓ\ell, ϕ(s)−ϕ(t)\phi(s)-\phi(t) è un polinomio non nullo di grado <ℓ<\ell che ha al più ℓ−1\ell-1 radici in Zp\mathbb Z_p, quindi P(ϕ(s)=ϕ(t))≤ℓ−1pP(\phi(s)=\phi(t))\le\frac{\ell-1}p (lemma di Schwartz-Zippel in una variabile, Union bound e verifica randomizzata - identità polinomiali e prodotti di matriciSpazi discreti richiamati; inclusione-esclusione (con le troncate di Bonferroni) e union bound Pr[unione] ≤ somma, valido senza indipendenza e stretto quando gli eventi sono rari (collisioni: C(n,2)/m). Principio delle decisioni differite: si fissa tutto tranne una scelta casuale e si limita la probabilità su quella. Lemma di Schwartz-Zippel: un polinomio non nullo di grado totale d, valutato in un punto di S^n scelto uniformemente, si annulla con prob ≤ d/|S| (induzione sul numero di variabili); test di identità polinomiale con errore unilaterale, ripetuto (d/|S|)^k. Freivalds: per verificare AB=C si controlla A(Br)=Cr con r in {0,1}^n in tempo O(n^2), errore ≤ 1/2 (stretto), 2^-k con k prove. Fingerprint: due stringhe di n bit si confrontano con a mod p per un primo casuale p ≤ M, errore ≤ n/π(M).Union bound e verifica randomizzata - identità polinomiali e prodotti di matrici →). Per ℓ=106\ell=10^6 e p=261−1p=2^{61}-1: ≤4,3⋅10−13\le4{,}3\cdot10^{-13}.

python
import random
from math import log

P = (1 << 61) - 1                       # primo di Mersenne, maggiore di ogni chiave

def scegli_hash(m):
    """Un elemento a caso della famiglia h(x) = ((a x + b) mod P) mod m."""
    a, b = random.randrange(1, P), random.randrange(P)
    return lambda x: ((a * x + b) % P) % m

class Bloom:
    def __init__(self, m, k):
        self.m, self.bits = m, bytearray(m)
        self.h = [scegli_hash(m) for _ in range(k)]   # k funzioni indipendenti
    def aggiungi(self, x):
        for h in self.h:
            self.bits[h(x)] = 1
    def contiene(self, x):                            # False: certamente assente
        return all(self.bits[h(x)] for h in self.h)   # True: forse presente

if __name__ == "__main__":
    n, eps = 10_000, 0.01
    m = round(n * log(1 / eps) / log(2) ** 2)         # m/n = 1,44 log2(1/eps)
    k = round(m / n * log(2))
    f = Bloom(m, k)
    dentro = [random.getrandbits(60) for _ in range(n)]
    for x in dentro:
        f.aggiungi(x)
    falsi = sum(f.contiene(random.getrandbits(60)) for _ in range(100_000))
    print(m, k, all(f.contiene(x) for x in dentro), falsi / 100_000)

Con n=10 000n=10\,000 e ε=1%\varepsilon=1\% il programma usa m=95 851m=95\,851 bit e k=7k=7 e osserva una frequenza di falsi positivi di circa 0,00980{,}0098 (quattro esecuzioni: da 0,00950{,}0095 a 0,01010{,}0101), senza nessun falso negativo.

Domande d'esame

  1. Dimostra che la famiglia ((ax+b) mod p) mod m((ax+b)\bmod p)\bmod m è universale. Per x≠yx\ne y la mappa (a,b)↦(r,s)(a,b)\mapsto(r,s) è una biiezione sulle coppie con r≠sr\ne s; per ogni rr ci sono al più ⌈p/m⌉−1≤p−1m\lceil p/m\rceil-1\le\frac{p-1}m valori s≠rs\ne r con s≡r(modm)s\equiv r\pmod m; quindi la probabilità è ≤1m\le\frac1m.
  2. Una tabella con n=2000n=2000 chiavi in m=1000m=1000 bucket e hash universale: lunghezza attesa della lista di una chiave presente? Al più 1+n−1m=2,9991+\frac{n-1}m=2{,}999, per linearità degli indicatori di collisione.
  3. Perché nell'hashing perfetto il secondo livello usa ni2n_i^2 celle e il primo si accetta se ∑ni2≤4n\sum n_i^2\le4n? Con ni2n_i^2 celle le coppie in collisione attese sono <12<\frac12, quindi un tentativo riesce con probabilità >12>\frac12; E[∑ni2]≤2n−1E[\sum n_i^2]\le2n-1 e per Markov ∑ni2<4n\sum n_i^2<4n con probabilità >12>\frac12; spazio totale ≤5n\le5n.
  4. Un filtro di Bloom con m/n=10m/n=10 bit per elemento: kk ottimo e tasso di falsi positivi? k=10ln⁡2=6,93→7k=10\ln2=6{,}93\to7 e f=(1−e−0,7)7=0,0082f=(1-e^{-0{,}7})^7=0{,}0082.

Versione ripasso

Esercizi su questo argomento

Teoria collegata