Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
aa:lab:5 [2023/11/12 16:28] dmihai |
aa:lab:5 [2025/11/01 11:48] (current) codrut_eduard.bicu |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Notații asimptotice ====== | + | ===== Analiza Probabilistă în Hashing ===== |
| - | <note important>Solutii:[[https://drive.google.com/file/d/1FZro37pN3XaHOAZUK2ttSy1VR1yKMz83/view?usp=sharing]]</note> | + | În acest laborator vom explora comportamentul probabilist al hashing-ului și fenomenele care apar din cauza coliziunilor. |
| + | Vom lucra pe două exemple simple care ilustrează concepte teoretice importante: | ||
| - | $ \Theta(f(n)) = \{ g: \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\ |\ | + | * **Paradoxul zilelor de naștere** — probabilitatea unei coliziuni într-un spațiu finit de valori; |
| - | \begin{array}{l} | + | * **Problema colecționarului de cupoane** — timpul așteptat până acoperim toate cazurile posibile. |
| - | \exists c_1, c_2 \in \mathbb{R}^+\cr | + | |
| - | \exists n_0 \in \mathbb{N} | + | |
| - | \end{array}\ | + | |
| - | such\ that\ \forall\ n \ge n_0,\ \ c_1f(n) \le g(n) \le c_2f(n) \}$ | + | |
| - | {{:aa:lab:theta_fn.png|}} | + | ---- |
| - | $ O(f(n)) = \{ g: \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\ |\ | + | ==== Context ==== |
| - | \begin{array}{l} | + | |
| - | \exists c \in \mathbb{R}^+\cr | + | |
| - | \exists n_0 \in \mathbb{N} | + | |
| - | \end{array}\ | + | |
| - | such\ that\ \forall\ n \ge n_0,\ \ | + | |
| - | 0 \le g(n) \le cf(n) \}$ | + | |
| - | {{:aa:lab:o_fn.png|}} | + | În hashing, fiecare element este atribuit aleatoriu unui dintre cele ( k ) sloturi. |
| + | Problemele pe care le studiem astăzi au aplicații directe în analiza performanței tabelelor hash. | ||
| - | $ \Omega(f(n)) = \{ g: \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\ |\ | + | ---- |
| - | \begin{array}{l} | + | |
| - | \exists c \in \mathbb{R}^+\cr | + | |
| - | \exists n_0 \in \mathbb{N} | + | |
| - | \end{array}\ | + | |
| - | such\ that\ \forall\ n \ge n_0,\ \ | + | |
| - | 0 \le cf(n) \le g(n) \}$ | + | |
| - | {{:aa:lab:omega_fn.png|}} | + | === Exemplul 1: Paradoxul zilelor de naștere === |
| - | $ o(f(n)) = \{ g: \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\ |\ | + | Scenariu: avem ( n ) persoane și ( k = 365 ) zile posibile. |
| - | \begin{array}{l} | + | Dorim să aflăm probabilitatea ca cel puțin două persoane să aibă aceeași zi de naștere. |
| - | \forall c \in \mathbb{R}^+\cr | + | |
| - | \exists n_0 \in \mathbb{N} | + | |
| - | \end{array}\ | + | |
| - | such\ that\ \forall\ n \ge n_0,\ \ | + | |
| - | 0 \le g(n) \le cf(n) \}$ | + | |
| - | $ \omega(f(n)) = \{ g: \mathbb{R}^{+} \rightarrow \mathbb{R}^{+}\ |\ | + | Formula teoretică este: |
| - | \begin{array}{l} | + | |
| - | \forall c \in \mathbb{R}^+\cr | + | |
| - | \exists n_0 \in \mathbb{N} | + | |
| - | \end{array}\ | + | |
| - | such\ that\ \forall\ n \ge n_0,\ \ | + | |
| - | 0 \le cf(n) \le g(n) \}$ | + | |
| - | ===== Syntactic sugars ====== | + | $$ |
| + | P(\text{coliziune}) = 1 - \frac{k!}{(k-n)! \, k^n} | ||
| + | $$ | ||
| - | Notațiile asimptotice sunt adesea folosite pentru a ne referi la funcții arbitrare cu o anumită creștere. Pentru simplitate, putem scrie //expresii aritmetice// astfel: | + | Codul de mai jos simulează fenomenul: |
| - | $ f(n) = \Theta(n) + O(\log(n)) $ | + | <file python paradoxul_nasterilor.py> |
| + | import random | ||
| - | Care trebuie citită: $math[\exists g \in \Theta(n)] și $math[\exists h \in O(\log(n))] a.î. $math[f(n) = g(n) + h(n),\ \forall n \in \mathbb{R}^{+}]. | + | def paradox_zile_nastere(trials=10000, grup=23, zile=365): |
| + | """Estimează probabilitatea ca două persoane să aibă aceeași zi de naștere.""" | ||
| + | count = 0 | ||
| + | for _ in range(trials): | ||
| + | zile_aleatoare = [random.randint(1, zile) for _ in range(grup)] | ||
| + | if len(zile_aleatoare) != len(set(zile_aleatoare)): | ||
| + | count += 1 | ||
| + | return count / trials | ||
| - | Putem de asemenea scrie //ecuații//: | + | for n in [10, 20, 23, 30, 40, 50]: |
| + | p = paradox_zile_nastere(grup=n) | ||
| + | print(f"Grup de {n} persoane → Probabilitate ≈ {p:.3f}") | ||
| + | </file> | ||
| - | $ \Theta(n^2) = O(n^2) + o(n)$ | + | **Întrebări:** |
| + | 1. Pentru ce valoare a lui ( n ) probabilitatea depășește 0.5? | ||
| + | 2. Cum se aseamănă acest fenomen cu coliziunile dintr-o tabelă hash? | ||
| - | Care ar trebui citite: $math[\forall f \in \Theta(n^2),\ \exists g \in O(n^2)] și $math[\exists h \in o(n)] a.î. $math[f(n) = g(n) + h(n),\ \forall n \in \mathbb{R}^{+}]. | + | ---- |
| - | Observați că ecuațiile nu sunt simetrice și ar trebui citite de la stânga la dreapta. De exemplu: | + | === Exemplul 2: Problema colecționarului de cupoane === |
| - | $\Theta(n) = O(n)$ | + | Scenariu: avem ( n ) cupoane distincte. |
| + | La fiecare pas tragem unul aleator (uniform). | ||
| + | Dorim să aflăm câte extrageri sunt necesare în medie până le avem pe toate. | ||
| - | Deși e adevărat că, pentru orice funcție $math[\Theta(n)] există o funcție egală în $math[O(n)], putem vedea că există funcții în $math[O(n)] pentru care nu există niciun corespondent în $math[\Theta(n)]. | + | Rezultatul teoretic: |
| + | $$ | ||
| + | E[T] = n H_n = n(1 + \tfrac{1}{2} + \tfrac{1}{3} + \dots + \tfrac{1}{n}) | ||
| + | $$ | ||
| - | Ca regulă, fiecare notație asimptotică din stânga unui egal, ar trebui citită ca o funcție **cuantificată universal** ($math[\forall f]) din acea clasă, iar fiecare notație asimptotică din dreapta unui egal ar trebui citită ca o funcție **cuantificată existențial** ($math[\exists g]) din clasa respectivă. | + | Simulare: |
| - | $\left(\frac{\omega(n^2)}{\Theta(n)}\right) = \Omega(n) + o(n)$ | + | <file python cupoane.py> |
| + | import random | ||
| - | $math[\forall f \in \omega(n^2)\ and\ | + | def colector_cupoane(n, incercari=500): |
| - | \forall g \in \Theta(n),\ \exists h \in \Omega(n)] și $math[\exists j \in o(n)] a.î. | + | """Returnează numărul mediu de extrageri până la colectarea tuturor cupoanelor.""" |
| - | $math[\left(\frac{f(n)}{g(n)}\right) = | + | total = 0 |
| - | h | + | for _ in range(incercari): |
| - | (n) + j(n),\ \forall n \in \mathbb{R}^{+}] | + | colectate = set() |
| + | pasi = 0 | ||
| + | while len(colectate) < n: | ||
| + | colectate.add(random.randint(0, n-1)) | ||
| + | pasi += 1 | ||
| + | total += pasi | ||
| + | return total / incercari | ||
| + | for n in [10, 50, 100]: | ||
| + | estimat = colector_cupoane(n) | ||
| + | print(f"n = {n}: medie ≈ {estimat:.2f}") | ||
| + | </file> | ||
| - | ===== Exerciții ===== | + | **Întrebări:** |
| - | <note> | + | 1. Cum crește numărul așteptat de extrageri odată cu ( n )? |
| - | În continuare, aveti un {{:aa:lab:lab5notatii.pdf|}} pentru a va ajuta la rezolvări. | + | 2. Ce analogie există între această problemă și procesul de „umplere” a tuturor sloturilor într-o tabelă hash? |
| - | </note> | + | |
| - | 1. Dați exemple de câte o funcție din următoarele clase de complexitate: | + | ---- |
| - | * $ O(n)$ | + | ==== Rezumat ==== |
| - | * $ \Omega(log(n))$ | + | |
| - | * $ \Theta(n^2)$ | + | |
| - | * $ \omega(\frac{1}{n})$ | + | |
| - | * $ o(3^n)$ | + | |
| - | 2. Pentru fiecare din perechile de mai jos, dați un exemplu concret de constante pentru care inegalitățile implicate în definiția clasei de complexitate sunt adevărate: | + | * Hashing-ul se poate analiza folosind concepte probabiliste simple. |
| - | + | * Paradoxul zilelor de naștere arată cât de rapid apar coliziunile. | |
| - | * $ log(n) \in o(\sqrt n)$ | + | * Problema colecționarului de cupoane arată cât de lent se „umple” complet un spațiu finit. |
| - | * $ 100n^2 \in O(2^n)$ | + | |
| - | * $ 0.001n^3 \in \Omega(20 \sqrt n)$ | + | |
| - | * $ 10n \in \Theta(n)$ | + | |
| - | * $ n \in \Theta(10n)$ | + | |
| - | + | ||
| - | 3. Găsiți două funcții $ f$ și $ g$, astfel încât: | + | |
| - | + | ||
| - | * $ f(n) = O(g^2(n))$ | + | |
| - | * $ f(n) = \omega(\log(g(n)))$ | + | |
| - | * $ f(n) = \Omega(f(n)\cdot g(n))$ | + | |
| - | * $ f(n) = \Theta(g(n)) + \Omega(g^2(n))$ | + | |
| - | + | ||
| - | + | ||
| - | 4. Verificați valoarea de adevăr a următoarelor propoziții: | + | |
| - | + | ||
| - | * $ \sqrt{n} \in O(\log{n})$ | + | |
| - | * $ \log{n} \in O(\log{(\log{n})})$ | + | |
| - | * $ n \in O(\sqrt{n}\cdot\log{n})$ | + | |
| - | * $ n + \log{n} \in \Theta(n)$ | + | |
| - | * $ \log{(n\cdot \log{n})}\in\Theta(\log{n})$ | + | |
| - | * $ \sqrt{n}\in\omega(\log{n})$ | + | |
| - | + | ||
| - | + | ||
| - | ==== Exerciții - syntactic sugars ==== | + | |
| - | + | ||
| - | + | ||
| - | 5. Aduceți următoarele la o formă simplă (o clasă de complexitate ce depinde de o anume funcție): | + | |
| - | + | ||
| - | * $ \frac{O(n\sqrt{n})}{\Theta(n)} = \ldots$ | + | |
| - | * $ \frac{\Theta(n)}{O(\log(n))} = \ldots$ | + | |
| - | 6. Demonstrați/infirmați următoarele propoziții: | + | |
| - | + | ||
| - | * $ f(n) = \Omega(\log(n)) \land g(n)=O(n) \implies f(n)=\Omega(\log(g(n))$ | + | |
| - | * $ f(n) = \Omega(\log(n)) \land g(n)=O(n) \implies f(n)=\Theta(\log(g(n))$ | + | |
| - | * $ f(n) = \Omega(g(n)) \land g(n)=O(n^2) \implies \frac{g(n)}{f(n)}=O(n)$ | + | |