Esercizio - Hashing perfetto a due livelli su otto chiavi
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 → (hashing perfetto, famiglia ), Momenti e deviazioni - Markov, Chebyshev e mediana randomizzataVar(ΣX_i) = ΣVar + 2ΣCov, e basta l'indipendenza a coppie perché la varianza si sommi. Chebyshev dà code polinomiali (collezionista: P(T ≥ nH_n + cn) ≤ π²/(6c²)); il metodo del secondo momento dà P(X=0) ≤ Var(X)/E[X]². Algoritmo della mediana: campione di n^(3/4) elementi, due estremi d e u a ±√n, ordinamento dei soli elementi tra d e u; fallisce con probabilità ≤ n^(-1/4) ed è Las Vegas con 2n + o(n) confronti.Momenti e deviazioni - Markov, Chebyshev e mediana randomizzata → (disuguaglianza di Markov).
Testo. Si vuole una tabella statica per l'insieme di chiavi con ricerca in due accessi nel caso peggiore. Si usa e la famiglia con , ( funzioni).
- Primo livello ( bucket): con calcolare i bucket e . La funzione si accetta se ?
- Secondo livello: per ogni bucket con usare celle e la funzione ; verificare che non ci siano collisioni.
- Calcolare lo spazio totale e descrivere la ricerca di , di e di una chiave assente, .
- Calcolare esattamente (su tutte le funzioni) la media di al primo livello, confrontarla con il limite , la frazione di funzioni con e la frazione di funzioni di secondo livello senza collisioni sui due bucket.
- Per quale spazio e quanti tentativi in media garantisce la teoria?
Soluzione
1. Primo livello. Si calcola , poi il resto mod e mod :
| mod | mod | ||
|---|---|---|---|
Bucket: (), (), , , , vuoti . : accettata.
2. Secondo livello.
- Bucket , : : ; ; . Posizioni , diverse.
- Bucket , : ; . Posizioni , diverse.
- Ogni bucket singolo usa cella.
3. Spazio e ricerca. Primo livello celle di puntatori più celle di secondo livello (che contengono le chiavi): celle per chiavi, cioè . Ricerca di : , si va al bucket (parametri , ), cella : contiene , trovata. Di : bucket , cella : trovata. Chiave assente : , bucket ; : cella vuota, quindi assente. Se la cella fosse occupata si confronterebbe la chiave memorizzata con quella cercata. In ogni caso due accessi: nel caso peggiore, non solo in media.
4. Calcolo esatto sulla famiglia. L'enumerazione delle funzioni del primo livello dà: media di pari a ; nessuna funzione ha (massimo osservato ), l' ha . Per il secondo livello, sui bucket () e () la frazione di funzioni senza collisioni è e , entrambe come prevede il limite: coppie in collisione attese e Markov. La media di è vicina a : .
5. . Il primo livello ha celle e con probabilità (Markov su ), quindi meno di tentativi; ogni bucket ha successo con probabilità (meno di tentativi); lo spazio è celle. Il tempo di costruzione atteso è operazioni di hashing più le ripetizioni (la somma dei costi dei tentativi sui bucket è ).
Codice di verifica
from collections import Counter
p = 97
S = [5, 17, 29, 41, 48, 62, 73, 90]
def h(a, b, mm, x): return ((a * x + b) % p) % mm
bucket = Counter(h(3, 1, 8, x) for x in S)
print(dict(bucket), sum(c * c for c in bucket.values()))
print([h(2, 1, 9, x) for x in (5, 29, 48)], [h(2, 1, 4, x) for x in (62, 73)], h(3, 1, 8, 100), h(2, 1, 4, 100))
somme = [sum(c * c for c in Counter(h(a, b, 8, x) for x in S).values())
for a in range(1, p) for b in range(p)]
print(len(somme), sum(somme) / len(somme), max(somme), sum(s >= 32 for s in somme), sum(s <= 16 for s in somme) / len(somme))
for B, mi in (([5, 29, 48], 9), ([62, 73], 4)):
ok = sum(len({h(a, b, mi, x) for x in B}) == len(B) for a in range(1, p) for b in range(p))
print(B, ok, (p - 1) * p, ok / ((p - 1) * p))Risultato: {0: 3, 4: 1, 3: 1, 2: 2, 5: 1} 16; [2, 5, 0] [0, 2] 2 3; 9312 14.4948... 30 0 0.8011... (funzioni, media, massimo, quante con somma , frazione con somma ); infine 6526 9312 0.7008... e 7056 9312 0.7577..., cioè le frazioni e del punto 4.
Versione ripasso
- Primo livello (, , ): ; ; ; ; . : accettata (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 →).
- Secondo livello (): bucket con dà posizioni ; bucket con dà . Spazio celle.
- Ricerca. : bucket , cella , trovata; : cella , trovata; : , , cella vuota, assente. Due accessi nel caso peggiore.
- Esatto su funzioni. Media (, ); nessuna funzione con (massimo ); con . Secondo livello senza collisioni: e , entrambe (Markov: coppie attese ).
- Scala. : spazio , meno di tentativi per livello, costruzione attesa .
- Errori tipici. Usare celle (invece di ) al secondo livello; non ripetere il primo livello quando è grande; confondere "due accessi" con "tempo atteso".