Differences

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

Link to this comparison view

pp:26:teme:haskell-graphs [2026/03/22 12:22]
mihnea.muraru [Etapa 1]
pp:26:teme:haskell-graphs [2026/04/27 15:55] (current)
mihnea.muraru
Line 1: Line 1:
-====== Haskell: ​Graph Zoo ======+====== Haskell: ​Grafuri funcționale ​======
  
-  * Data publicării: ​TODO +  * Data publicării: ​27.04.2026 
-  * Data ultimei modificări: ​TODO+  * Data ultimei modificări: ​27.04.2026
   * Deadline hard: ziua laboratorului 12   * Deadline hard: ziua laboratorului 12
-  * Forum temă+  * [[https://​curs.upb.ro/​2025/​mod/​forum/​view.php?​id=169983|Forum temă]]
   * [[https://​vmchecker.cs.pub.ro/​ui/#​PP|vmchecker]]   * [[https://​vmchecker.cs.pub.ro/​ui/#​PP|vmchecker]]
  
Line 23: Line 23:
   * una pe care o veți rezolva după laboratorul 11, cu deadline în ziua laboratorului 12, la ora 08:00.   * una pe care o veți rezolva după laboratorul 11, cu deadline în ziua laboratorului 12, la ora 08:00.
  
-Așa cum se poate observa, **ziua deadline-ului variază în funcție de semigrupa în care sunteți repartizați**. **Restanțierii care refac tema și nu refac laboratorul beneficiază de ultimul deadline** (deci vor avea deadline-uri în zilele de TODO).+Așa cum se poate observa, **ziua deadline-ului variază în funcție de semigrupa în care sunteți repartizați**. **Restanțierii care refac tema și nu refac laboratorul beneficiază de ultimul deadline** (deci vor avea deadline-uri în zilele de 08.05, 15.05, 22.05 și 29.05).
  
 **Rezolvările tuturor etapelor pot fi trimise până la ora 08:00 în ziua laboratorului 12** (**deadline hard pentru toate etapele**). Orice exercițiu trimis după un **deadline soft**, dar înainte de cel hard, se punctează cu **jumătate** din punctaj. Orice exercițiu trimis după deadline-ul hard nu se mai punctează deloc. Nota finală pe etapă se calculează conform formulei: **n = (n1 + n2) / 2** (n1 = nota obținută înainte de deadline; n2 = nota obținută după deadline). Când toate submisiile sunt înainte de deadline-ul soft, nota pe ultima submisie este și nota finală (întrucât n1 = n2). **Rezolvările tuturor etapelor pot fi trimise până la ora 08:00 în ziua laboratorului 12** (**deadline hard pentru toate etapele**). Orice exercițiu trimis după un **deadline soft**, dar înainte de cel hard, se punctează cu **jumătate** din punctaj. Orice exercițiu trimis după deadline-ul hard nu se mai punctează deloc. Nota finală pe etapă se calculează conform formulei: **n = (n1 + n2) / 2** (n1 = nota obținută înainte de deadline; n2 = nota obținută după deadline). Când toate submisiile sunt înainte de deadline-ul soft, nota pe ultima submisie este și nota finală (întrucât n1 = n2).
Line 49: Line 49:
  
   * ''​%%StandardGraph%%'':​ conține **reprezentarea** grafului orientat și funcții de **acces și manipulare**:​   * ''​%%StandardGraph%%'':​ conține **reprezentarea** grafului orientat și funcții de **acces și manipulare**:​
-    * tipul ''​%%StandardGraph a%%'',​ deja definit ca **pereche** între o mulțime de noduri și una de arce +    * Tipul ''​%%StandardGraph a%%'',​ deja definit ca **pereche** între o mulțime de noduri și una de arce. 
-    * funcția ''​%%fromComponents%%''​ **construiește** un graf pe baza nodurilor și arcelor +    * Funcția ''​%%fromComponents%%''​ **construiește** un graf pe baza nodurilor și arcelor. 
-    * funcțiile ''​%%nodes%%''​ și ''​%%edges%%''​ întorc **cele două mulțimi** de mai sus +    * Funcțiile ''​%%nodes%%''​ și ''​%%edges%%''​ întorc **cele două mulțimi** de mai sus. 
-    * funcțiile ''​%%outNeighbors%%''​ și ''​%%inNeghbors%%''​ întorc mulțimile de **vecini** înspre care ies, respectiv dinspre care intră arce către nodul curent +    * Funcțiile ''​%%outNeighbors%%''​ și ''​%%inNeghbors%%''​ întorc mulțimile de **vecini** înspre care ies, respectiv dinspre care intră arce către nodul curent. 
-    * funcția ''​%%removeNode%%''​ **înlătură** un nod și toate arcele sale din graf +    * Funcția ''​%%removeNode%%''​ **înlătură** un nod și toate arcele sale din graf. 
-    * funcția ''​%%splitNode%%''​ **sparge** un nod în mai multe noduri, ținând cond de arcele nodului inițial +    * Funcția ''​%%splitNode%%''​ **sparge** un nod în mai multe noduri, ținând cond de arcele nodului inițial. 
-    * funcția ''​%%mergeNodes%%''​ **îmbină** mai multe noduri într-unul singur, ținând cont de arcele nodurilor inițiale +    * Funcția ''​%%mergeNodes%%''​ **îmbină** mai multe noduri într-unul singur, ținând cont de arcele nodurilor inițiale. 
-  * ''​%%Algorithms%%'':​ conține algoritmii standard de **căutare**,​ BFS și DFS: +  * ''​%%Algorithms%%'':​ conține algoritmii standard de **căutare**,​ BFS și DFS, **restricționați** pentru simplitate la grafuri pentru care nu există mai multe căi între două noduri și nici cicluri. 
-    * funcțiile ''​%%bfs%%''​ și ''​%%dfs%%''​ întorc lista de noduri parcurse în ordinea aferentă **căutării în lățime**, respectiv **în adâncime**,​ pornind de la un anumit nod, ținând cont și de posibilele cicluriAceste funcții vor fi **derivate** dintr-o funcție mai generală, menționată în continuare +    * Funcțiile ''​%%bfs%%''​ și ''​%%dfs%%''​ întorc lista de noduri parcurse în ordinea aferentă **căutării în lățime**, respectiv **în adâncime**,​ pornind de la un anumit nod. 
-    * funcția ''​%%search%%''​ **generalizează** cele două strategii de căutare de mai sus, plecând de la observația că singura diferență dintre ele este modul în care se **combină** la un moment dat nodurile deja existente în structura de date utilizată (stivă/​coadă,​ ambele reprezentate ca liste standard) cu vecinii proaspăt expandați ai nodului curent. ​Funcția **nu este testată direct**. +    * Funcția ''​%%countIntermediate%%''​ verifică **existența unei căi** între două noduri din graf, și calculează **numărul nodurilor intermediare** pe care le expandează cele două strategii de mai sus pentru acest scop.
-    * funcția ''​%%countIntermediate%%''​ verifică **existența unei căi** între două noduri din graf, și calculează **numărul nodurilor intermediare** pe care le expandează cele două strategii de mai sus pentru acest scop.+
  
 Pentru reprezentarea **mulțimilor**,​ utilizăm modulul ''​[[https://​hackage.haskell.org/​package/​containers-0.6.7/​docs/​Data-Set.html|Data.Set]]''​ (versiunea 0.6.7, corespunzătoare vmchecker), care definește tipul ''​Set a''​ (mulțime ordonată cu elemente de tipul ''​a''​). Având în vedere că multe dintre funcțiile pe mulțimi au **același nume** cu cele pe liste (''​map'',​ ''​filter'',​ ''​foldr''​ etc.), conflictele se evită plasând la începutul scheletului liniile: Pentru reprezentarea **mulțimilor**,​ utilizăm modulul ''​[[https://​hackage.haskell.org/​package/​containers-0.6.7/​docs/​Data-Set.html|Data.Set]]''​ (versiunea 0.6.7, corespunzătoare vmchecker), care definește tipul ''​Set a''​ (mulțime ordonată cu elemente de tipul ''​a''​). Având în vedere că multe dintre funcțiile pe mulțimi au **același nume** cu cele pe liste (''​map'',​ ''​filter'',​ ''​foldr''​ etc.), conflictele se evită plasând la începutul scheletului liniile:
Line 75: Line 74:
 Găsiți detalii despre **funcționalitate** și **implementare**,​ precum și **exemple**,​ direct în codul sursă. Aveți de completat definițiile care încep cu **''​%%*** TODO ***%%''​**. Găsiți detalii despre **funcționalitate** și **implementare**,​ precum și **exemple**,​ direct în codul sursă. Aveți de completat definițiile care încep cu **''​%%*** TODO ***%%''​**.
  
-Se impun următoarele **constrângeri** de implementare:​+Se impun următoarele **constrângeri** de implementare ​asupra funcțiilor din modulul ''​StandardGraph''​:
  
-  * Toate funcțiile din această etapă, cu excepția ''​%%search%%'', ​trebuie implementate **FĂRĂ recursivitate explicită**. +  * Toate trebuie implementate **FĂRĂ recursivitate explicită**. 
-  * Funcțiile ​trebuie să opereze **direct pe mulțimile** de arce și noduri, utilizând funcțiile specifice acestei reprezentări,​ **FĂRĂ conversii** redundante la liste și înapoi la mulțimi.+  * Ele trebuie să opereze **direct pe mulțimile** de noduri ​și arce, utilizând funcțiile specifice acestei reprezentări,​ **FĂRĂ conversii** redundante la liste și înapoi la mulțimi.
  
 Este suficient ca arhiva pentru **vmchecker** să conțină modulele ''​%%StandardGraph%%''​ și ''​%%Algorithms%%''​. Este suficient ca arhiva pentru **vmchecker** să conțină modulele ''​%%StandardGraph%%''​ și ''​%%Algorithms%%''​.
 +
 +**ATENȚIE!** După ce experimentați în modulul ''​Algorithms''​ cu funcțiile de **debug** din schelet, ''​appendDebug''​ și ''​concatMapDebug'',​ așa cum se precizează în comentarii, **reveniți** la versiunile obișnuite ale acestora, ''​(++)''​ și ''​concatMap'',​ pentru a evita generarea mesajelor stufoase pe vmchecker.
  
 ==== Depunctări ==== ==== Depunctări ====
  
-O funcție care nu respectă cele două constrângeri de mai sus va fi **depunctată total**.+  * Funcțiile din modulul ''​StandardGraph'' ​care nu respectă cele două constrângeri de mai sus vor fi **depunctate total**. 
 +  * Funcțiile din modulul ''​Algorithms''​ care nu respectă constrângerile din schelet vor fi **depunctate ​total**.
 ===== Etapa 2 ===== ===== Etapa 2 =====
  
 În această etapă: În această etapă:
  
-  * veți lucra cu o altă reprezentare a grafurilor orientate, pe care o vom denumi //​**constructivă**//​sau //​**algebrică**//​ (explicațiile urmează)+  * veți lucra cu o altă reprezentare a grafurilor orientate, pe care o vom denumi //​**constructivă**//​ sau //​**algebrică**//​ (explicațiile urmează)
   * veți **redefini** funcțiile de acces și manipulare din etapa 1 (din modulul ''​%%StandardGraph%%''​),​ pentru a opera pe noua reprezentare   * veți **redefini** funcțiile de acces și manipulare din etapa 1 (din modulul ''​%%StandardGraph%%''​),​ pentru a opera pe noua reprezentare
   * pentru bonus, veți începe să implementați o funcționalitate de **compactare** a reprezentării unui graf, continuată în etapa 3.   * pentru bonus, veți începe să implementați o funcționalitate de **compactare** a reprezentării unui graf, continuată în etapa 3.
Line 110: Line 112:
 Ideile de mai sus se pot traduce direct într-un **tip de date utilizator**,​ unde ''​%%a%%''​ este tipul **etichetelor** nodurilor: Ideile de mai sus se pot traduce direct într-un **tip de date utilizator**,​ unde ''​%%a%%''​ este tipul **etichetelor** nodurilor:
  
-<​code>​+<​code ​haskell>
 data AlgebraicGraph a data AlgebraicGraph a
     = Empty     = Empty
Line 120: Line 122:
 Mai jos, sunt **exemplificate** mai multe grafuri care utilizează această reprezentare,​ pentru o înțelegere mai bună: Mai jos, sunt **exemplificate** mai multe grafuri care utilizează această reprezentare,​ pentru o înțelegere mai bună:
  
-  * ''​%%Overlay (Node 2) (Node 3)%%''​ este un graf foarte simplu, care conține doar nodurile 2 și 3, fără ​niciun arc.+  * ''​%%Overlay (Node 2) (Node 3)%%''​ este un graf foarte simplu, care conține doar nodurile 2 și 3, fără ​arce.
   * ''​%%Connect (Node 2) (Node 3)%%''​ conține nodurile 2 și 3, precum și arcul (2, 3).   * ''​%%Connect (Node 2) (Node 3)%%''​ conține nodurile 2 și 3, precum și arcul (2, 3).
   * ''​%%Connect (Node 1) (Overlay (Node 2) (Node 3))%%''​ conține nodurile 1, 2 și 3, și arcele (1, 2) și (1, 3), pentru că nodul 1 trebuie conectat cu fiecare dintre nodurile 2 și 3.   * ''​%%Connect (Node 1) (Overlay (Node 2) (Node 3))%%''​ conține nodurile 1, 2 și 3, și arcele (1, 2) și (1, 3), pentru că nodul 1 trebuie conectat cu fiecare dintre nodurile 2 și 3.
Line 146: Line 148:
   * Mulțimea [1, 3] **nu** ar putea constitui un modul, pentru că există arcul (1, 2), dar nu și arcul (3, 2).   * Mulțimea [1, 3] **nu** ar putea constitui un modul, pentru că există arcul (1, 2), dar nu și arcul (3, 2).
  
-{{ :pp:22:​teme:​haskell:​graph.png }}+{{ :pp:26:​teme:​haskell:​graph.png }}
  
 Orice graf are două descompuneri modulare **banale**: Orice graf are două descompuneri modulare **banale**:
Line 163: Line 165:
 Veți implementa aspecte legate de descompunerea modulară parțial ca bonus, în cadrul etapelor 2 și 3. Deși există [[https://​www.sciencedirect.com/​science/​article/​pii/​S0166218X04002458|algoritmi eficienți (liniari)]] pentru determinarea descompunerii modulare, aceștia sunt destul de complicați,​ astfel că vom utiliza o abordare mai simplă bazată pe forță brută. Cu alte cuvinte, vom genera **toate partițiile** mulțimii de noduri, și apoi le vom filtra pentru a obține modulele. Veți implementa aspecte legate de descompunerea modulară parțial ca bonus, în cadrul etapelor 2 și 3. Deși există [[https://​www.sciencedirect.com/​science/​article/​pii/​S0166218X04002458|algoritmi eficienți (liniari)]] pentru determinarea descompunerii modulare, aceștia sunt destul de complicați,​ astfel că vom utiliza o abordare mai simplă bazată pe forță brută. Cu alte cuvinte, vom genera **toate partițiile** mulțimii de noduri, și apoi le vom filtra pentru a obține modulele.
  
-În etapa 2, **scheletul** conține următoarele module:+Ca încălzire:​ 
 +  * Gândiți-vă cum se poate **redefini** tipul ''​%%StandardGraph%%''​ din etapa 1 ca **tip de date utilizator** (''​%%data%%''​)în locul sinonimului de tip pereche. 
 +  ​Funcțiile ''​%%nodes%%''​ și ''​%%edges%%''​ pot fi definite direct drept **câmpuri** în cadrul tipului. 
 +  * Funcția ''​%%fromComponents%%''​ trebuie și ea redefinită
 +  * Schițați în comentarii redefinirea celor patru entități de mai sus. Această parte nu este testată automat, dar o veți **prezenta**. 
 +  * Nu este necesar să reimplementați celelalte funcții din acest modul.
  
-  * ''​%%StandardGraph%%'':​ implementat în etapa 1. Reprezentarea originală este de **pereche** de mulțimi de noduri, respectiv arce. Ca încălzire: +În etapa 2, **scheletul** conține următoarele module:
-    * Gândiți-vă cum se poate **redefini** tipul ''​%%StandardGraph%%''​ ca **tip de date utilizator** (''​%%data%%''​),​ în locul sinonimului de tip pereche. +
-    * Funcțiile ''​%%nodes%%''​ și ''​%%edges%%''​ pot fi definite direct drept **câmpuri** în cadrul tipului. +
-    * Funcția ''​%%fromComponents%%''​ trebuie și ea redefinită. +
-    * Schițați în comentarii redefinirea celor patru entități de mai sus. Această parte nu este testată automat, dar o veți **prezenta**. +
-    * Nu este necesar să reimplementați celelalte funcții din acest modul.+
   * ''​%%AlgebraicGraph%%'':​ conține **reprezentarea algebrică** a grafurilor, descrisă mai sus   * ''​%%AlgebraicGraph%%'':​ conține **reprezentarea algebrică** a grafurilor, descrisă mai sus
     * Tipul ''​%%AlgebraicGraph%%''​ este cel prezentat mai sus.     * Tipul ''​%%AlgebraicGraph%%''​ este cel prezentat mai sus.
     * Mai departe, veți implementa **aceleași funcții** ca în modulul ''​%%StandardGraph%%'',​ cu excepția ''​%%fromComponents%%'',​ dar de data aceasta vor opera pe reprezentarea algebrică.     * Mai departe, veți implementa **aceleași funcții** ca în modulul ''​%%StandardGraph%%'',​ cu excepția ''​%%fromComponents%%'',​ dar de data aceasta vor opera pe reprezentarea algebrică.
-    * Toate funcțiile vor fi implementate **CU recursivitate explicită**. 
     * Veți observa că implementările funcțiilor ''​%%removeNode%%'',​ ''​%%splitNode%%''​ și ''​%%mergeNodes%%''​ respectă un **tipar similar**, pe care vom căuta să îl generalizăm în etapa 3.     * Veți observa că implementările funcțiilor ''​%%removeNode%%'',​ ''​%%splitNode%%''​ și ''​%%mergeNodes%%''​ respectă un **tipar similar**, pe care vom căuta să îl generalizăm în etapa 3.
-    * **ATENȚIE!** Funcțiile de mai sus trebuie să opereze **direct pe reprezentarea algebrică** din această etapă. **NU este permisă** convertirea în reprezentarea din etapa 1 și utilizarea funcțiilor de acolo. 
   * ''​%%Modular%%'':​ conține momentan doar câteva funcții pentru determinarea **descompunerii modulare** a grafului, dar va fi îmbogățit în etapa 3:   * ''​%%Modular%%'':​ conține momentan doar câteva funcții pentru determinarea **descompunerii modulare** a grafului, dar va fi îmbogățit în etapa 3:
     * Funcția ''​%%mapSingle%%''​ este asemănătoare cu ''​%%map%%'',​ în sensul că aplică o funcție asupra fiecărui element al unei liste, dar aplicarea se face asupra unui **singur element** din listă la un moment dat, celelalte rămânând nemodificate.     * Funcția ''​%%mapSingle%%''​ este asemănătoare cu ''​%%map%%'',​ în sensul că aplică o funcție asupra fiecărui element al unei liste, dar aplicarea se face asupra unui **singur element** din listă la un moment dat, celelalte rămânând nemodificate.
     * Funcția ''​%%partitions%%''​ generează toate partițiile unei liste.     * Funcția ''​%%partitions%%''​ generează toate partițiile unei liste.
 +
 +Se impun următoarele **constrângeri** de implementare asupra funcțiilor din modulul ''​AlgebraicGraph'':​
 +
 +  * Toate trebuie implementate **CU recursivitate explicită**.
 +  * Toate trebuie să opereze **direct pe reprezentarea algebrică** din această etapă. **NU este permisă** convertirea în reprezentarea din etapa 1 și utilizarea funcțiilor de acolo.
 +
 +Este suficient ca arhiva pentru **vmchecker** să conțină modulele ''​%%AlgebraicGraph%%''​ și ''​%%Modular%%''​.
 +
 +==== Depunctări ====
 +
 +Funcțiile care nu respectă constrângerile de mai sus sau pe cele din schelet vor fi **depunctate total**.
  
 ===== Etapa 3 ===== ===== Etapa 3 =====
Line 221: Line 232:
     * Funcția ''​%%maximalModularPartition%%''​ determină cea mai acoperitoare partiție, pornind de la lista tuturor partițiilor mulțimii de noduri (vedeți explicațiile din comentarii).     * Funcția ''​%%maximalModularPartition%%''​ determină cea mai acoperitoare partiție, pornind de la lista tuturor partițiilor mulțimii de noduri (vedeți explicațiile din comentarii).
     * Funcția ''​%%modularlyDecompose%%''​ este **deja implementată**,​ și vă permite să puneți cap la cap funcțiile de mai sus.     * Funcția ''​%%modularlyDecompose%%''​ este **deja implementată**,​ și vă permite să puneți cap la cap funcțiile de mai sus.
 +
 +Este suficient ca arhiva pentru **vmchecker** să conțină modulele ''​%%AlgebraicGraph%%''​ și ''​%%Modular%%''​.
 +
 +==== Depunctări ====
 +
 +Funcțiile care nu respectă constrângerile din schelet vor fi **depunctate total**.
 +
  
 ===== Precizări ===== ===== Precizări =====
  
-  * Încercați să folosiți pe cât posibil funcții **predefinite** din modulele [[https://​hackage.haskell.org/​package/​base-4.16.1.0/​docs/​Data-List.html|Data.List]] și [[https://​hackage.haskell.org/​package/​containers-0.6.5.1/​docs/​Data-Set.html|Data.Set]]. Este foarte posibil ca o funcție de prelucrare de care aveți nevoie să fie deja definită aici. 
-  * Ca sugestie, exploatați cu încredere //**pattern matching**//,​ **''​%%case%%''​** și **gărzi**, în locul //​if//​-urilor imbricate. 
   * Pentru **rularea testelor**, încărcați în interpretor modulul ''​%%TestGraph%%''​ și evaluați ''​%%checkAll%%''​.   * Pentru **rularea testelor**, încărcați în interpretor modulul ''​%%TestGraph%%''​ și evaluați ''​%%checkAll%%''​.
 +  * Încercați să folosiți pe cât posibil funcții **predefinite** din modulele ''​[[https://​hackage-content.haskell.org/​package/​base-4.22.0.0/​docs/​Data-List.html|Data.List]]''​ și ''​[[https://​hackage.haskell.org/​package/​containers-0.6.7/​docs/​Data-Set.html|Data.Set]]''​. Este foarte posibil ca o funcție de prelucrare de care aveți nevoie să fie deja definită aici.
 +  * Ca sugestie, exploatați cu încredere //**pattern matching**//,​ **''​%%case%%''​** și **gărzi**, în locul //​if//​-urilor imbricate.
  
 ===== Resurse ===== ===== Resurse =====
  
-  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​22/​teme/​haskell/​etapa1.zip|Schelet etapa 1]] +  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​26/​teme/​haskell/​etapa1.zip|Schelet etapa 1]] 
-  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​22/​teme/​haskell/​etapa2.zip|Schelet etapa 2]] +  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​26/​teme/​haskell/​etapa2.zip|Schelet etapa 2]] 
-  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​22/​teme/​haskell/​etapa3.zip|Schelet etapa 3]]+  * [[https://​ocw.cs.pub.ro/​courses/​_media/​pp/​26/​teme/​haskell/​etapa3.zip|Schelet etapa 3]]
  
 ===== Referințe ===== ===== Referințe =====
pp/26/teme/haskell-graphs.1774174959.txt.gz · Last modified: 2026/03/22 12:22 (external edit)
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