This shows you the differences between two versions of the page.
pp:23:teme:haskell-structuri-functionale [2023/04/22 16:20] bot.pp |
pp:23:teme:haskell-structuri-functionale [2023/05/04 10:44] (current) bot.pp |
||
---|---|---|---|
Line 2: | Line 2: | ||
* Data publicării: 11.04.2023 | * Data publicării: 11.04.2023 | ||
- | * Data ultimei modificări: 22.04.2023 | + | * Data ultimei modificări: 04.05.2023 |
* Deadline hard: ziua laboratorului 10 (11 pentru seria CB) | * Deadline hard: ziua laboratorului 10 (11 pentru seria CB) | ||
* [[https://curs.upb.ro/2022/mod/forum/view.php?id=173248|Forum temă]] | * [[https://curs.upb.ro/2022/mod/forum/view.php?id=173248|Forum temă]] | ||
Line 82: | Line 82: | ||
* primul arbore are rangul 0 și dimensiunea 1 | * primul arbore are rangul 0 și dimensiunea 1 | ||
- | * atașând la un arbore de rang ''%%r-1%%'' și dimensiune ''%%2^(r-1)%%'' o copie de-a sa, obținem un arbore de rang ''%%r%%'' și dimensiune ''%%2^r%%''. Nodurile bicolore surprind creșterea rangului unui nod de la ''%%r-1%%'' la ''%%r%%'' în urma atașării copiei. | + | * atașând la un arbore de rang ''%%r-1%%'' și dimensiune ''%%2^(r-1)%%'' o copie de-a sa, obținem un arbore de rang ''%%r%%'' și dimensiune ''%%2^r%%''; nodurile bicolore surprind creșterea rangului unui nod de la ''%%r-1%%'' la ''%%r%%'' în urma atașării copiei. |
În fig. 1, se observă mai mulți arbori binomiali, cu ranguri între 0 și 4, și că **înălțimea** unui arbore este egală cu **rangul** său. De asemenea, transpare o proprietate care derivă din modalitatea de construcție: copiii unui nod de rang ''%%r%%'' au rangurile ''%%r-1%%'', ''%%r-2%%'', ..., ''%%1%%'', ''%%0%%'', exact în această ordine **descrescătoare**. De exemplu, copiii rădăcinii de rang 4 au rangurile 3, 2, 1, 0. **Numele** de arbore binomial vine de la faptul că, pe nivelul ''%%i%%'' din arborele de rang ''%%r%%'', numărul de noduri este dat de **coeficientul binomial** „combinări de ''%%r%%'' luate câte ''%%i%%''”. | În fig. 1, se observă mai mulți arbori binomiali, cu ranguri între 0 și 4, și că **înălțimea** unui arbore este egală cu **rangul** său. De asemenea, transpare o proprietate care derivă din modalitatea de construcție: copiii unui nod de rang ''%%r%%'' au rangurile ''%%r-1%%'', ''%%r-2%%'', ..., ''%%1%%'', ''%%0%%'', exact în această ordine **descrescătoare**. De exemplu, copiii rădăcinii de rang 4 au rangurile 3, 2, 1, 0. **Numele** de arbore binomial vine de la faptul că, pe nivelul ''%%i%%'' din arborele de rang ''%%r%%'', numărul de noduri este dat de **coeficientul binomial** „combinări de ''%%r%%'' luate câte ''%%i%%''”. | ||
- | Continuăm cu prezentarea **//heap//-urilor binomiale**. Acestea nu sunt decât **liste de arbori binomiali**, cu constrângerea suplimentară că arborii trebuie să respecte și **proprietatea de //heap//**, i.e. rădăcina are **prioritate mai mică** decât copiii și analog pentru subarbori. Având în vedere faptul că toți arborii binomiali au dimensiuni puteri ale lui 2, principala întrebare este cum **distribuim** elementele //heap//-ului în cadrul acestor arbori, presupunând că numărul total de elemente nu este putere a lui 2. Aici intervine **reprezentarea binară a numerelor** din etapa 1. Dacă dimensiunea //heap//-ului este ''%%n%%'', având reprezentarea binară ''%%[b_0, b_1, ..., b_m]%%'', unde ''%%m = [lg n]%%'' (parte întreagă), atunci, pentru fiecare bit ''%%0%%'', vom avea un arbore **vid**, și pentru fiecare bit ''%%b_r%%'' egal cu ''%%1%%'' vom avea un arbore de **rang ''%%r%%''**, și implicit dimensiune ''%%2^r%%''. | + | Continuăm cu prezentarea **//heap//-urilor binomiale**. Acestea nu sunt decât **liste de arbori binomiali**, cu constrângerea suplimentară că arborii trebuie să respecte și **proprietatea de //heap//**, i.e. rădăcina are **prioritate mai mică** decât copiii și analog pentru subarbori. Având în vedere faptul că toți arborii binomiali au dimensiuni puteri ale lui 2, principala întrebare este cum **distribuim** elementele //heap//-ului în cadrul acestor arbori, presupunând că numărul total de elemente nu este putere a lui 2. Aici intervine **reprezentarea binară a numerelor** din etapa 1. Dacă **dimensiunea** //heap//-ului este ''%%n%%'', având reprezentarea binară ''%%[b_0, b_1, ..., b_m]%%'', unde ''%%m = [lg n]%%'' (parte întreagă), atunci, pentru fiecare bit ''%%0%%'', vom avea un arbore **vid**, și pentru fiecare bit ''%%b_r%%'' egal cu ''%%1%%'' vom avea un arbore de **rang ''%%r%%''**, și implicit dimensiune ''%%2^r%%''. |
**Exemplificăm** ideea de mai sus cu un //heap// cu 13 elemente, **reprezentarea binară a dimensiunii** fiind ''%%[1, 0, 1, 1]%%''. Aceasta înseamnă că avem un arbore de rang 0 (dimensiune 1), niciun arbore de rang 1, un arbore de rang 2 (dimensiune 4) și un arbore de rang 3 (dimensiune 8), ca în fig. 2. Observați de asemenea respectarea **proprietății de //heap//** de către fiecare dintre cei trei arbori. | **Exemplificăm** ideea de mai sus cu un //heap// cu 13 elemente, **reprezentarea binară a dimensiunii** fiind ''%%[1, 0, 1, 1]%%''. Aceasta înseamnă că avem un arbore de rang 0 (dimensiune 1), niciun arbore de rang 1, un arbore de rang 2 (dimensiune 4) și un arbore de rang 3 (dimensiune 8), ca în fig. 2. Observați de asemenea respectarea **proprietății de //heap//** de către fiecare dintre cei trei arbori. | ||
Line 114: | Line 114: | ||
Cum reprezentarea binară a dimensiunii //heap//-ului conține un număr logaritmic de biți, deci un număr logaritmic de arbori (vizi sau nevizi), iar atașarea unui arbore la altul se face în timp constant, **inserarea** are complexitate **logaritmică**. | Cum reprezentarea binară a dimensiunii //heap//-ului conține un număr logaritmic de biți, deci un număr logaritmic de arbori (vizi sau nevizi), iar atașarea unui arbore la altul se face în timp constant, **inserarea** are complexitate **logaritmică**. | ||
- | Având în vedere că toți arborii respectă **proprietatea de //heap//**, i.e. rădăcina este elementul cu prioritate minimă din fiecare arbore, operația de **determinare** a elementului cu **prioritate minimă** din întregul //heap// presupune identificarea **rădăcinii** cu prioritate minimă. În exemplul din fig. 2, prioritatea minimă este 5, aferentă rădăcinii arborelui de rang 2. Urmând un raționament similar celui din paragraful anterior, rezultă că și această operație are complexitate **logaritmică**. | + | Având în vedere că toți arborii respectă **proprietatea de //heap//**, i.e. rădăcina este elementul cu prioritate minimă din fiecare arbore, operația de **determinare** a elementului cu **prioritate minimă** din întregul //heap// presupune identificarea **rădăcinii** cu prioritate minimă. În exemplul din fig. 2, prioritatea minimă este 5, aferentă rădăcinii arborelui de rang 2. Dacă există **mai multe** rădăcini cu prioritate minimă, se alege cea care apare **prima** în lista de arbori. Urmând un raționament similar celui din paragraful anterior, rezultă că și această operație are complexitate **logaritmică**. |
Ultima operație implementată în această etapă este cea de **combinare** (engl. //merge//) a două //heap//-uri. Aceasta o oglindește pe cea de **adunare** a două numere binare din etapa 1. La fel cum, în cazul **numerelor binare**, se adună mai întâi biții de pe poziția 0, apoi 1 etc., în cazul **//heap//-urilor binomiale**, se începe cu adunarea arborilor de pe poziția de rang 0, apoi rang 1 ș.a.m.d., ținând cont bineînțeles de eventualul **transport**. Din motive similare celor de mai sus, și această operație are complexitate **logaritmică**. | Ultima operație implementată în această etapă este cea de **combinare** (engl. //merge//) a două //heap//-uri. Aceasta o oglindește pe cea de **adunare** a două numere binare din etapa 1. La fel cum, în cazul **numerelor binare**, se adună mai întâi biții de pe poziția 0, apoi 1 etc., în cazul **//heap//-urilor binomiale**, se începe cu adunarea arborilor de pe poziția de rang 0, apoi rang 1 ș.a.m.d., ținând cont bineînțeles de eventualul **transport**. Din motive similare celor de mai sus, și această operație are complexitate **logaritmică**. | ||
Line 133: | Line 133: | ||
Este suficient ca arhiva pentru **vmchecker** să conțină modulul ''%%BinomialHeap%%''. | Este suficient ca arhiva pentru **vmchecker** să conțină modulul ''%%BinomialHeap%%''. | ||
+ | |||
+ | ===== Etapa 3 ===== | ||
+ | |||
+ | În această etapă, veți continua să implementați anumite operații asupra //heap//-urilor binomiale, în continuarea celor din etapa 2. | ||
+ | |||
+ | Construcțiile și mecanismele noi de limbaj pe care le veți exploata în rezolvare, pe lângă cele din etapa 2, sunt: | ||
+ | |||
+ | * **polimorfismul ad-hoc** | ||
+ | * **clasele**. | ||
+ | |||
+ | Ultima operație fundamentală este de **eliminare** a cheii de **prioritate minimă** din //heap//. Am lăsat-o la final, deoarece utilizează operația de **combinare** (''%%mergeTrees%%'') implementată în etapa 2. Eliminarea presupune **înlăturarea primului arbore** cu rădăcină de prioritate minimă din lista de arbori ai //heap//-ului (prin înlocuirea lui cu ''%%EmptyTree%%'') și apoi **combinarea** (''%%mergeTrees%%'') noii liste de arbori cu lista de subarbori (orfani) ai rădăcinii tocmai înlăturate. Având în vedere că lista de arbori ai //heap//-ului este ordonată **crescător** în raport cu rangul, iar lista de subarbori orfani este ordonată **descrescător** (conform structurii arborilor binomiali), este necesară **inversarea** ultimeia înainte de combinarea celor două liste! Având la bază operația de combinare, rezultă că și cea de eliminare are complexitate **logaritmică**. | ||
+ | |||
+ | Scheletul etapei 3 se găsește tot în modulul ''%%BinomialHeap%%'', în continuarea operațiilor din etapa 2, începând cu linia 243: | ||
+ | |||
+ | * funcția ''%%isolate%%'' este ajutătoare, pregătind terenul pentru următoarea operație | ||
+ | * funcția ''%%removeMin%%'' înlătură prima cheie de prioritate minimă din //heap// | ||
+ | * instanțele clasei ''%%Show%%'' pentru tipurile ''%%BinomialTree p k%%'' și ''%%BinomialHeap p k%%'' oferă reprezentări mai lizibile, sub formă de șir de caractere ale celor două categorii de structuri; observați că a fost necesară eliminarea ''%%deriving Show%%'' din definiția tipurilor, pentru evitarea conflictului de instanțe | ||
+ | * instanțele clasei ''%%Functor%%'' pentru constructorii de tip ''%%BinomialTree p%%'' și ''%%BinomialHeap p%%'' generalizează funcționala ''%%map%%'' pe aceste categorii de structuri | ||
+ | * pentru **bonus**, instanța clasei ''%%Foldable%%'' pentru constructorul de tip ''%%BinomialTree p%%'' generealizează funcționala ''%%foldr%%'' pe aceste structuri. | ||
+ | |||
+ | Găsiți detaliile despre **funcționalitate** și despre **constrângerile de implementare**, precum și **exemple**, direct în schelet. Aveți de completat definițiile care încep cu ''%%*** TODO ***%%''. | ||
+ | |||
+ | Pentru **rularea testelor**, încărcați în interpretor modulul ''%%TestBinomialHeap%%'' și evaluați ''%%main%%''. | ||
+ | |||
+ | Este suficient ca arhiva pentru **vmchecker** să conțină modulul ''%%BinomialHeap%%''. Veți avea nevoie de implementarea funcției ''%%mergeTrees%%'' din etapa 2. | ||
===== Precizări ===== | ===== Precizări ===== | ||
Line 143: | Line 168: | ||
* [[https://ocw.cs.pub.ro/courses/_media/pp/23/teme/haskell/etapa1.zip|Schelet etapa 1]] | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/teme/haskell/etapa1.zip|Schelet etapa 1]] | ||
* [[https://ocw.cs.pub.ro/courses/_media/pp/23/teme/haskell/etapa2.zip|Schelet etapa 2]] | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/teme/haskell/etapa2.zip|Schelet etapa 2]] | ||
+ | * [[https://ocw.cs.pub.ro/courses/_media/pp/23/teme/haskell/etapa3.zip|Schelet etapa 3]] | ||
===== Changelog ===== | ===== Changelog ===== | ||
* 22.04 (ora 16:10) Publicare etapa 2, doar enunț și schelet; urmează și checker-ul. | * 22.04 (ora 16:10) Publicare etapa 2, doar enunț și schelet; urmează și checker-ul. | ||
+ | * 24.04 (ora 22:45) Publicare checker etapa 2. | ||
+ | * 26.04 (ora 10:55) Actualizare checker etapa 2. Și ''%%BinomialHeap%%'' instanțiază acum ''%%Eq%%'' pentru facilitarea noilor teste. | ||
+ | * 28.04 (ora 14:50) Actualizare checker etapa 2 pt verificări mai flexibile. Dacă ați încărcat deja etapa 2 pe vmchecker, NU este necesară reîncărcarea. | ||
+ | * 30.04 (ora 10:30) Publicare etapa 3, doar enunț și schelet; urmează și checker-ul. | ||
+ | * 30.04 (ora 22:35) Actualizare checker etapa 2, în urma unor probleme semnalate de voi. Se verifică acum corespondența corectă dintre rangul arborilor și poziția acestora în lista heap-ului. | ||
+ | * 04.05 (ora 10:45) Publicare checker etapa 3. | ||