Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sd-ca:teme:tema2-2020 [2020/03/26 19:42]
gabriel_danut.matei
sd-ca:teme:tema2-2020 [2020/04/11 12:07] (current)
gabriel_danut.matei
Line 1: Line 1:
 +====== Tema 2 - Count-distinct problem ======
 +
 +** Responsabili:​ **
 +  *[[lucaistrate@gmail.com|Luca Istrate]]
 +  *[[matei.danut.dm@gmail.com|Dănuţ Matei]]
 +
 +** Data publicării : 26 martie, ora: 21:00 **
 +
 +** Deadline: 17 aprilie, ora 23:55 **
 +
 +== Modificări şi actualizări == 
 +  * **27 martie, ora 01:30** - adăugat clarificari in sectiunea **Introducere**
 +  * **27 martie, ora 21:05** - adăugat **checker** in **enunt** si pe **vmchecker**
 +  * **27 martie, ora 23:40** - modificat fisier **Makefile** din **checker**
 +  * **29 martie, ora 16:00** - adăugat precizari in **cerinta II** legate de **dimensiunea Hashtable-ului**
 +  * **29 martie, ora 18:40** - adăugat corectare in **cerinta III** legata de **definitia lui m**
 +  * **29 martie, ora 19:30** - modificat fisier **check.sh** din **checker**;​ acum partea de **valgrind** are comportamentul corect pentru toate cerintele
 +  * **3 aprilie, ora 19:10** - reformulat **cerinta III** pentru a o face mai usor de inteles
 +  * **11 aprilie, ora 12:05** - actualizat **deadline**
 +
 +
 <​hidden>​ <​hidden>​
-====== Count-distinct problem ======+  * **26 martie, ora 21:00** - adăugat **checker** 
 +</​hidden>​ 
 +===== Obiective ​===== 
 + 
 +În urma realizării acestei teme: 
 +  * veţi învăţa să lucraţi cu Dictionare  
 +  * vă veţi familiariza cu rezolvarea unei probleme reale prin structuri de date din ce in ce mai eficiente  ​
  
 ===== Introducere ===== ===== Introducere =====
  
 **Problema estimarii cardinalitatii** (a numararii elementelor distincte) este, in esenta, gasirea numarului de elemente unice dintr-o colectie de elemente care se pot repeta. **Problema estimarii cardinalitatii** (a numararii elementelor distincte) este, in esenta, gasirea numarului de elemente unice dintr-o colectie de elemente care se pot repeta.
 +<note important>​
 +Pentru cerintele **I** si **II**, vom rezolva o problema si mai restrictiva:​ gasirea **numarului de aparitii** pentru fiecare element. Pentru cerinta **III**, vom vedea ca acest lucru e mai greu realizabil cand vine vorba de volume mari de date si, de aceea, ne vom rezuma la **gasirea numarului de elemente distincte**.</​note>​
 +
 +
 +**Conceptual,​ ne referim la:**
 +
 +INPUT:
 +
 +''​1,​ 34, 2, 2, 2, 3''​
 +
 +OUTPUT:
 +
 +**Pentru cerintele I si II:**
 +
 +''​1 - 1''​
 +
 +''​2 - 3''​
 +
 +''​3 - 1''​
 +
 +''​34 - 1''​
 +
 +**Pentru cerinta III:**
 +
 +''​Exista 4 elemente distincte''​
  
-Pentru primele doua subpuncte, vom rezolva o problema si mai restrictiva:​ gasirea ​**numarului de aparitii** pentru fiecare element. Pentru restul, vom vedea ca acest lucru e mai greu realizabil cand vine vorba de volume mari de date si, de aceea, ne vom rezuma la gasirea numarului de elemente distincte.+<note warning>**Fiecare** dintre cele **3** cerinte se va implementa intr-un **fisier separat**.</​note>​
  
-===== I. Vector de frecventa =====+===== I. Vector de frecventa ​- 25p =====
  
 La intrare se dau numere intre **0** si **2000000**. Gasiti numarul de aparitii ale fiecarui element, utilizand un **vector de frecventa**. La intrare se dau numere intre **0** si **2000000**. Gasiti numarul de aparitii ale fiecarui element, utilizand un **vector de frecventa**.
Line 14: Line 66:
 Un vector de frecventa este un vector care are pe pozitia **i** //numarul de aparitii// ale elementului **i**. Un vector de frecventa este un vector care are pe pozitia **i** //numarul de aparitii// ale elementului **i**.
  
-{{:../​figures/​out/​freq.png| ​Vector de frecventa}}+{{:sd-ca:teme:freq.png|}}
  
 //Se garanteaza ca numarul de aparitii ale oricarui element este mai mic decat **256**.// //Se garanteaza ca numarul de aparitii ale oricarui element este mai mic decat **256**.//
  
-===== II. Hashtable cu open addressing =====+===== II. Hashtable cu open addressing ​- 25p =====
  
 La intrare se dau siruri de caractere. Gasiti numarul de aparitii ale fiecarui sir folosind un Hashtable cu politica de rezolvare a conflictelor de tip **open addressing** prin **linear probing**. La intrare se dau siruri de caractere. Gasiti numarul de aparitii ale fiecarui sir folosind un Hashtable cu politica de rezolvare a conflictelor de tip **open addressing** prin **linear probing**.
Line 24: Line 76:
 Aceasta politica presupune ca, in momentul in care bucketul unde trebuie realizata insertia este deja ocupat, //se va cauta secvential o pozitie libera incepand cu bucketul urmator//. Aceasta politica presupune ca, in momentul in care bucketul unde trebuie realizata insertia este deja ocupat, //se va cauta secvential o pozitie libera incepand cu bucketul urmator//.
  
-{{:../​figures/​out/​hash1.png| ​Adaugare}}+{{:sd-ca:teme:hash1.png|}}
  
 Evident, daca si aceasta pozitie este ocupata, vom cauta prima pozitie libera in continuare. Evident, daca si aceasta pozitie este ocupata, vom cauta prima pozitie libera in continuare.
  
-{{:../​figures/​out/​hash2.png| ​Adaugare cu cautare de loc liber}}+{{:sd-ca:teme:hash2.png|}}
  
 Daca se va ajunge la finalul listei de bucketuri, se va continua de la inceput. Daca se va ajunge la finalul listei de bucketuri, se va continua de la inceput.
  
-{{:../​figures/​out/​hash3.png| ​Cautarea continua circular}}+{{:sd-ca:teme:hash3.png|}}
  
-//Se garanteaza existenta a cel putin unui bucket liber in momentul fiecarei operatii de insertie.//+//Se garanteaza existenta a cel putin unui bucket liber in momentul fiecarei operatii de insertie.// ​**Pentru a satisface aceasta conditie, o idee ar fi ca dimensiunea Hashtable-ului sa fie egala cu numarul de siruri existente in fisierul de intrare.**
  
 Evident, daca in momentul unei operatii de selectie nu gasim cheia in bucketul in care ne-am astepta, vom continua cautarea secvential, aplicand un procedeu similar cu cel din momentul insertiei. Evident, daca in momentul unei operatii de selectie nu gasim cheia in bucketul in care ne-am astepta, vom continua cautarea secvential, aplicand un procedeu similar cu cel din momentul insertiei.
  
-//Se garanteaza ca lungimea maxima a oricarui este maxim **100** de caractere.//​+//Se garanteaza ca lungimea maxima a oricarui ​sir este maxim **100** de caractere.//​
  
 //Se garanteaza ca numarul de aparitii ale oricarui element este mai mic decat **256**.// //Se garanteaza ca numarul de aparitii ale oricarui element este mai mic decat **256**.//
  
-===== III. Estimatori probabilistici =====+===== III. Estimatori probabilistici ​- 30p =====
  
 In cerintele anterioare am observat ca putem calcula cu exactitate numarul de elemente distincte (si numarul lor de aparitii) retinand, intr-un fel sau altul, fiecare element unic (ca pozitie intr-un vector, respectiv ca cheie intr-un hashtable). Din pacate, in aplicatiile din lumea reala, //aceasta strategie nu este sustenabila//​. In cerintele anterioare am observat ca putem calcula cu exactitate numarul de elemente distincte (si numarul lor de aparitii) retinand, intr-un fel sau altul, fiecare element unic (ca pozitie intr-un vector, respectiv ca cheie intr-un hashtable). Din pacate, in aplicatiile din lumea reala, //aceasta strategie nu este sustenabila//​.
Line 59: Line 111:
  
 In ilustrarea functionarii algoritmului **HyperLogLog**,​ vom incepe de la o serie de principii simple pe care le vom pune cap la cap, ajungand la descrierea algoritmului final. In ilustrarea functionarii algoritmului **HyperLogLog**,​ vom incepe de la o serie de principii simple pe care le vom pune cap la cap, ajungand la descrierea algoritmului final.
 +
 +<note important>​Sectiunile 1 si 2 sunt prezentate pentru a intelege de ce functioneaza HyperLogLog. Pentru a rezolva tema, trebuie sa implementati **doar algoritmul final (descris in sectiunea 3)**.</​note>​
  
 ==== 1. Probabilistic counting ==== ==== 1. Probabilistic counting ====
Line 70: Line 124:
 Similar, probabilitatea ca numarul sa inceapa cu **3** biti **0** este **1/8**. Astfel, pentru a intalni un numar care sa inceapa cu **3** biti **0**, //va trebui sa generam, in medie, **8** numere//. Similar, probabilitatea ca numarul sa inceapa cu **3** biti **0** este **1/8**. Astfel, pentru a intalni un numar care sa inceapa cu **3** biti **0**, //va trebui sa generam, in medie, **8** numere//.
  
-{{:../​figures/​out/​probcount1.png| ​Probabilitatea de a generea 3 0 consecutivi}}+{{:sd-ca:teme:probcount1.png|}}
  
-Privind aceasta observatie in sens invers, daca am generat numere aleatoare si secventa cea mai lunga de **0** de la inceputul oricarui numar a fost de lungime **3**, atunci avem urmatoarele ​posibilitati:​ - am generat //cel putin **8** numere// - am avut noroc si a trebuit sa generam //mai putin de 8 numere//+Privind aceasta observatie in sens invers, daca am generat numere aleatoare si secventa cea mai lunga de **0** de la inceputul oricarui numar a fost de lungime **3**, atunci avem doua posibilitati:​ 
 + 
 +- am generat //cel putin **8** numere// 
 + 
 +- am avut noroc si a trebuit sa generam //mai putin de 8 numere//
  
 Evident, pentru valori mici precum **2** sau **3** biti consecutivi,​ exista o sansa semnificativa sa generam numarul mai rapid (chiar din prima incercare), dar cu cat valorile devin mai mari, cu atat scade aceasta sansa. Evident, pentru valori mici precum **2** sau **3** biti consecutivi,​ exista o sansa semnificativa sa generam numarul mai rapid (chiar din prima incercare), dar cu cat valorile devin mai mari, cu atat scade aceasta sansa.
Line 82: Line 140:
 ==== 2. LogLog ==== ==== 2. LogLog ====
  
-Daca vrem sa imbunatatim performanta algoritmului nostru va trebui sa: - Atenuam efectul negativ al generarii rapide unui numar cu multi biti de **0** initiali - Oferim estimari //mai granulare// decat **puterile lui 2**+Daca vrem sa imbunatatim performanta algoritmului nostru va trebui sa:
  
-{{:../figures/from_internet/​2n_table.png| ​Pentru puteri mari intervalul estimarii devine prea lat}}+- Atenuam efectul negativ al generarii rapide unui numar cu multi biti de **0** initiali 
 + 
 +- Oferim estimari ​//mai granulare// decat **puterile lui 2** 
 + 
 +{{:​sd-ca:​teme:​2n_table.png|}}
  
 O idee de rezolvare a primei probleme este sa impartim numerele in mai multe **bucketuri**. Cea mai usoara modalitate de a face acest lucru este sa impartim fiecare numar in 2 parti: //prima parte// va fi folosita pentru a determina bucketul, iar //a doua// va fi folosita ca pana acum. O idee de rezolvare a primei probleme este sa impartim numerele in mai multe **bucketuri**. Cea mai usoara modalitate de a face acest lucru este sa impartim fiecare numar in 2 parti: //prima parte// va fi folosita pentru a determina bucketul, iar //a doua// va fi folosita ca pana acum.
  
-{{:../​figures/​from_internet/​buckets.png| ​Calculare bucket-urilor}}+{{:sd-ca:teme:buckets.png|}}
  
 Singura diferenta fata de metoda precedenta este ca acum vom face maximul de zerouri consecutive //pentru fiecare bucket// si nu pentru toate numerele. Singura diferenta fata de metoda precedenta este ca acum vom face maximul de zerouri consecutive //pentru fiecare bucket// si nu pentru toate numerele.
Line 96: Line 158:
 ==== 3. HyperLogLog ==== ==== 3. HyperLogLog ====
  
-Pentru a aduce algoritmul ​in forma finalava trebui sa mai facem cateva ajustari matematice la procedeul descris anterior.+Recapituland ce am prezentat ​in sectiunile precedentein cadrul algoritmului HyperLogLog avem 3 etape:
  
-In primul randvom folosi o medie similara ​cu **media armonica** in loc de cea geometrica.+**1)** stabilim numarul total de bucketuri **m**apoi initializam ​cu 0 un vector ​**M** de dimensiune **m**. 
 +<note important>​Alegerea lui m este diferita de la caz la caz. In contextul problemei curente, puteti sa folositi valoarea m = $2^{11}$, insa exista si alte variante posibile.</​note>​
  
-In al doilea rand, vom utiliza un **factor de atenuare** alfa, pentru ​a imbunatati eroarea ​de aproximare.+**2)** pentru ​fiecare numar citit de la intrare:
  
-{{:​../​figures/​from_internet/​estimare.png| Estimarea finala}}+- ii calculam hash-ul cu o functie de hash pentru numere intregi
  
-**E** reprezinta //estimarea finala//+- pe baza primilor $\log_2(m)$ biti din hash determinam bucketul in care se afla (din cele $m$ bucketuri posibile); notam numarul bucketului cu **j**
  
-**m** reprezinta //numarul total de bucketuri//+- calculam numarul de biti 0 initiali din restul hash-ului; notam acest numar cu **x**
  
-**Z** reprezinta //media//calculata dupa urmatoarea formula:+- M[j] = max(M[j]x)
  
-{{:​../​figures/​from_internet/​media.png| Media}}+**3)** agregam valorile din toate bucketurile
  
-**alfa_m** reprezinta //factorul de atenuare//, calculat in functie de **m** dupa urmatoarea formula: 
  
-{{:../​figures/​from_internet/​alfa.png| Factorul de atenuare}}+In sectiunea precedenta, am mentionat ca pentru a agrega valorile din fiecare bucket, folosim media geometrica. Pentru a implementa HyperLogLog,​ vom folosi in locul ei urmatorea medie:
  
-==== Referinte ====+{{:​sd-ca:​teme:​media.png|}}
  
-  ​https:​%%//​%%en.wikipedia.org/​wiki/​Count-distinct_problem +Ca exemplu, pentru bucketul evidentiat cu verde, ​**j = 6**, iar **M[j] = 2**
-  ​https:​%%//​%%www.omnicoreagency.com/​youtube-statistics +
-  ​https:​%%//​%%en.wikipedia.org/​wiki/​HyperLogLog +
-  ​https:​%%//​%%en.wikipedia.org/​wiki/​Linear_probing +
-  ​https:​%%//​%%stackoverflow.com/​questions/​12327004/​how-does-the-hyperloglog-algorithm-work+
  
 +{{:​sd-ca:​teme:​buckets.png|}}
  
  
-</hidden>+Avand aceasta medie **Z**, raspunsul final **E** (numarul de elemente distincte intalnite) va fi dat de urmatorea formula: 
 + 
 +{{:​sd-ca:​teme:​estimare.png|}} 
 + 
 +Explicatie:​ 
 + 
 +**m**, ca si pana acum, este numarul total de bucketuri folosite 
 + 
 +**$\alpha_m$** reprezinta //factorul de atenuare//, calculat in functie de **m** dupa urmatoarea formula: 
 + 
 +{{:​sd-ca:​teme:​alfa.png|}} 
 + 
 + 
 +//Pentru ultima cerinta, citirea se va face dintr-un fisier al carui nume este primit ca parametru.//​ 
 + 
 +=== Precizări === 
 +<note warning>​Rezolvati cerintele I si II utilizand structura de date ceruta. Nerespectarea acestui lucru va aduce la anularea punctajului pentru cerinta respectiva.</note> 
 + 
 +<note important>​Având în vedere ca a 3-a parte a temei presupune implementarea unei structuri de date probabilistice,​ checkerul ofera punctajul daca raspunsul vostru se incadreaza intr-o marja de eroare de 10% fata de raspunsul corect.</​note>​ 
 + 
 +=== Checker === 
 +{{:​sd-ca:​teme:​2-distinct-count.zip|CHECKER}}  
 + 
 +Temele vor fi trimise pe [[https://​elf.cs.pub.ro/​vmchecker/​ui/#​SD|vmchecker]].  
 +**Atenție!** Temele trebuie trimise în secțiunea **Structuri de Date (CA)**. 
 + 
 +Arhiva trebuie să conțină:​ 
 +  * surse 
 +  * fișierul Makefile **din arhiva cu checkerul** 
 +  * fișier **README** care să conțină detalii despre implementarea temei 
 + 
 +=== Punctaj === 
 + 
 +<note warning>​**Atentie!** O temă care nu compilează va primi 0 puncte.</​note>​ 
 + 
 +  - 80p teste 
 +  - **Fiecare** test este verificat cu valgrind. Dacă un test are memory leaks, nu va fi punctat. 
 +  - 20p README + comentarii/​claritate cod (ATENȚIE! Fișierul README trebuie făcut explicit, cât să se înțeleagă ce ați făcut în sursă, dar fără comentarii inutile și detalii inutile). 
 +  - Se acordă 20% din punctajul obținut pe teste, ca bonus pentru coding style. De exemplu, pentru o temă care obține maxim pe teste, se pot obține 20p bonus dacă nu aveți erori de coding style. Pentru o temă ce trece 18 teste din 20, se pot obține 18p dacă nu aveți erori de coding style. 
 +  - O temă care obține 0p pe vmchecker este punctată cu 0. 
 +  - Temele au deadline hard. Prin urmare, o temă trimisă dupa deadline este punctată cu 0. 
 +<note warning>​**Nu copiați!** Toate soluțiile vor fi verificate folosind o unealtă de detectare a plagiatului. În cazul detectării unui astfel de caz, atât plagiatorul cât și autorul original (nu contează cine e) vor primi punctaj 0 pe **toate temele**! 
 + 
 +De aceea, vă sfătuim să nu vă lăsați rezolvări ale temelor pe calculatoare partajate (la laborator etc), pe mail/liste de discuții/​grupuri etc.</​note>​  
 + 
 +===FAQ=== 
 + ​**Q:​** Ce functii de hashing trebuie sa folosesc in tema, la cerintele II si III? \\ \\ 
 + ​**A:​** Puteti folosi orice functii doriti. Un exemplu ar fi cele din laborator. 
 + 
 + ​**Q:​** La cerinta II functia mea de hashing nu imi genereaza deloc coliziuni. E ok? \\ \\ 
 + ​**A:​** E in regula, insa codul care trateaza posibilitatea coliziunilor **trebuie sa existe**. 
 + 
 + ​**Q:​** In enuntul cerintei III sunt mentionate functiile matematice log si pow, insa checkerul nu permite folosirea functiilor matematice. Cum rezolvam problema asta \\ \\ 
 + ​**A:​** Pentru a-l calcula pe **m** care e de forma $2^k$, puteti folosi shiftarea pe biti, adica <​code>​int m = 1 << k;</​code>​ Din moment ce k se stabileste in prealabil, $\log_2{m} = k$. 
 + 
 + 
 +===Link-uri utile=== 
 + 
 +[[https://​en.wikipedia.org/​wiki/​Count-distinct_problem]] 
 + 
 +[[https://​www.omnicoreagency.com/​youtube-statistics]] 
 + 
 +[[https://​en.wikipedia.org/​wiki/​HyperLogLog]] 
 + 
 +[[https://​en.wikipedia.org/​wiki/​Linear_probing]] 
 + 
 +[[https://​stackoverflow.com/​questions/​12327004/​how-does-the-hyperloglog-algorithm-work]]
sd-ca/teme/tema2-2020.1585244531.txt.gz · Last modified: 2020/03/26 19:42 by gabriel_danut.matei
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0