Differences

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

Link to this comparison view

pp:23:teme:haskell-structuri-functionale [2023/04/22 16:10]
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 70: Line 70:
   * atașându-i unui arbore existent o **copie** a sa (din perspectivă structurală,​ nu neapărat a conținutului) ca **cel mai din stânga copil**, se obține tot un arbore binomial.   * atașându-i unui arbore existent o **copie** a sa (din perspectivă structurală,​ nu neapărat a conținutului) ca **cel mai din stânga copil**, se obține tot un arbore binomial.
  
-{{ :​pp:​23:​teme:​haskell:​binomial-trees.png |{{:​binomial-trees.png|Arbori binomiali}}}}+{{ :​pp:​23:​teme:​haskell:​binomial-trees.png |{{:​binomial-trees.png|Arbori binomiali}}
  
 Fig. 1. Arbori binomiali. Adaptare după [[https://​www.oreilly.com/​library/​view/​c-data-structures/​9781788833738/​ae9c1988-22e7-4a85-8285-da0b8f4cada5.xhtml|oreilly.com]]. Fig. 1. Arbori binomiali. Adaptare după [[https://​www.oreilly.com/​library/​view/​c-data-structures/​9781788833738/​ae9c1988-22e7-4a85-8285-da0b8f4cada5.xhtml|oreilly.com]].
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.
  
-{{ :​pp:​23:​teme:​haskell:​binomial-heap.png |{{:​binomial-heap.png|Heap binomial}}}}+{{ :​pp:​23:​teme:​haskell:​binomial-heap.png |{{:​binomial-heap.png|Heap binomial}}
  
 Fig. 2. //Heap// binomial. Adaptare după [[https://​www.bartleby.com/​subject/​engineering/​computer-science/​concepts/​binomial-heap|bartleby.com]]. Fig. 2. //Heap// binomial. Adaptare după [[https://​www.bartleby.com/​subject/​engineering/​computer-science/​concepts/​binomial-heap|bartleby.com]].
Line 108: Line 108:
 În ambele cazuri, rezultă un **transport** în forma unui arbore de rang 1, care îl **înlocuiește** pe cel vid din //heap//-ul original; de asemenea, dispare arborele de rang 0. Dacă în //heap//-ul original ar fi existat deja un arbore de rang 1, procesul de atașare și propagare a transportului ar fi **continuat recursiv**, către poziția de rang 2 ș.a.m.d. În ambele cazuri, rezultă un **transport** în forma unui arbore de rang 1, care îl **înlocuiește** pe cel vid din //heap//-ul original; de asemenea, dispare arborele de rang 0. Dacă în //heap//-ul original ar fi existat deja un arbore de rang 1, procesul de atașare și propagare a transportului ar fi **continuat recursiv**, către poziția de rang 2 ș.a.m.d.
  
-{{ :​pp:​23:​teme:​haskell:​binomial-heap-insert.png |{{:​binomial-heap-insert.png|Inserare}}}}+{{ :​pp:​23:​teme:​haskell:​binomial-heap-insert.png |{{:​binomial-heap-insert.png|Inserare}}
  
 Fig. 3. Inserarea în //heap//-ul binomial din fig. 2. Fig. 3. Inserarea în //heap//-ul binomial din fig. 2.
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.
  
  
pp/23/teme/haskell-structuri-functionale.1682169019.txt.gz · Last modified: 2023/04/22 16:10 by bot.pp
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