This shows you the differences between two versions of the page.
pp:22:teme:racket-smp [2022/12/20 21:00] mihaela.balint [Etapa 4] |
pp:22:teme:racket-smp [2023/02/28 23:30] (current) mihaela.balint |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Problema mariajelor stabile ====== | + | ====== Racket: Problema mariajelor stabile ====== |
* Data publicării: 28.02.2023 | * Data publicării: 28.02.2023 | ||
Line 24: | Line 24: | ||
În această etapă vă veți familiariza cu problema mariajelor stabile (SMP) și felul în care modelăm datele sale de intrare in Racket, apoi veți implementa câteva funcții de manipulare a acestor date. | În această etapă vă veți familiariza cu problema mariajelor stabile (SMP) și felul în care modelăm datele sale de intrare in Racket, apoi veți implementa câteva funcții de manipulare a acestor date. | ||
- | În SMP se dau un număr egal de bărbați și femei și, pentru fiecare dintre aceștia, un "clasament" al persoanelor de sex opus, și se cere să se căsătorească fiecare bărbat cu câte o femeie astfel încât să nu existe un bărbat și o femeie în căsătorii diferite care s-ar prefera unul pe altul în detrimentul soților lor. Dacă ar exista o asemenea pereche, cei doi ar fi motivați să își părăsească partenerii pentru a fi împreună, așadar căsătoriile lor nu ar fi stabile (de aici numele problemei). | + | În SMP se dau un număr egal de bărbați și femei și, pentru fiecare dintre aceștia, un "clasament" al tuturor persoanelor de sex opus, și se cere să se căsătorească fiecare bărbat cu câte o femeie astfel încât să nu existe un bărbat și o femeie în căsătorii diferite care s-ar prefera unul pe altul în detrimentul soților lor. Dacă ar exista o asemenea pereche, cei doi ar fi motivați să își părăsească partenerii pentru a fi împreună, așadar căsătoriile lor nu ar fi stabile (de aici numele problemei). |
Vom modela o instanță SMP în Racket ca pe două liste (egale ca lungime) de preferințe masculine, respectiv feminine, ca în exemplul următor: | Vom modela o instanță SMP în Racket ca pe două liste (egale ca lungime) de preferințe masculine, respectiv feminine, ca în exemplul următor: | ||
Line 37: | Line 37: | ||
[cora bobo cos adi ])) | [cora bobo cos adi ])) | ||
</file> | </file> | ||
- | Astfel, lista de preferințe masculine/feminine este o listă de liste, fiecare listă interioară având pe prima poziție un bărbat/o femeie, iar pe următoarele poziții persoanele de sex opus în ordinea preferințelor acestui bărbat/acestei femei. Deși în exemplu bărbații/femeile apar în ordine alfabetică, nu presupuneți că acest lucru este necesar să se întâmple. | + | Astfel, lista de preferințe masculine/feminine este o listă de liste, fiecare listă interioară având pe prima poziție un bărbat/o femeie, iar pe următoarele poziții persoanele de sex opus în ordinea preferințelor acestui bărbat/acestei femei. De-a lungul întregii teme, o listă de preferințe masculine/feminine se va referi la o listă cu acest format. Când, în schimb, ne vom referi la lista preferințelor unei persoane p, ne vom referi la felul în care p a clasat persoanele de sex opus, așadar o listă care conține doar persoane de sex opus, nu și pe p pe prima poziție. Deși în exemplu bărbații/femeile apar în ordine alfabetică, nu presupuneți că acest lucru este necesar să se întâmple. |
Aceste liste vor fi definite în checker, însă este necesar să le înțelegeți structura pentru a putea implementa funcțiile din cerință. | Aceste liste vor fi definite în checker, însă este necesar să le înțelegeți structura pentru a putea implementa funcțiile din cerință. | ||
Line 50: | Line 50: | ||
<file> | <file> | ||
- | (get-men men-pref) | + | (get-men mpref) |
- | (get-women women-pref) | + | (get-women wpref) |
</file> | </file> | ||
* get-men primește o listă de preferințe masculine și determină lista tuturor bărbaților din problemă | * get-men primește o listă de preferințe masculine și determină lista tuturor bărbaților din problemă | ||
Line 60: | Line 60: | ||
(get-pref-list pref person) | (get-pref-list pref person) | ||
</file> | </file> | ||
- | * get-pref-list primește o listă de preferințe (masculine sau feminine) și o persoană person ale cărei preferințe apar (garantat) în listă și întoarce lista preferințelor lui person | + | * get-pref-list primește o listă de preferințe (masculine sau feminine) și o persoană person ale cărei preferințe apar (garantat) în listă și întoarce lista preferințelor lui person |
* ex: ''%%(get-pref-list women-preferences 'bia)%%'' => '''(adi cos bobo)'' | * ex: ''%%(get-pref-list women-preferences 'bia)%%'' => '''(adi cos bobo)'' | ||
Line 90: | Line 90: | ||
Scopul etapei este consolidarea cunoștințelor legate de: | Scopul etapei este consolidarea cunoștințelor legate de: | ||
- | * funcționale | + | * funcționale (faptul că funcțiile sunt valori de ordinul întâi oferă atât posibilitatea de a lucra cu funcționalele din limbaj, cât și pe aceea de a implementa propriile funcționale, pentru orice șablon util pe care îl observați - din acest motiv, aveți inclusiv sarcina de a implementa două funcționale și a le folosi ulterior) |
* funcții anonime | * funcții anonime | ||
* programare de tip “wishful thinking” - veți implementa funcția stable-match? folosindu-vă de funcția better-match-exists?, întrucât noțiunea de stabilitate este definită ca "nu există un partener mai potrivit pentru niciunul dintre soți"; dacă nu ați fi avut deja funcția better-match-exists?, ar fi fost o idee foarte bună să programați stable-match? ca și cum ați fi implementat deja conceptul de partener mai potrivit (wishful thinking), și apoi să aveți grijă chiar să implementați această funcție ajutătoare | * programare de tip “wishful thinking” - veți implementa funcția stable-match? folosindu-vă de funcția better-match-exists?, întrucât noțiunea de stabilitate este definită ca "nu există un partener mai potrivit pentru niciunul dintre soți"; dacă nu ați fi avut deja funcția better-match-exists?, ar fi fost o idee foarte bună să programați stable-match? ca și cum ați fi implementat deja conceptul de partener mai potrivit (wishful thinking), și apoi să aveți grijă chiar să implementați această funcție ajutătoare | ||
Line 142: | Line 142: | ||
</file> | </file> | ||
* get-unstable-couples primește o listă engagements de logodne (unde fiecare cuplu are pe prima poziție o femeie), respectiv două liste mpref/wpref de preferințe masculine/feminine și întoarce lista tuturor cuplurilor instabile din engagements | * get-unstable-couples primește o listă engagements de logodne (unde fiecare cuplu are pe prima poziție o femeie), respectiv două liste mpref/wpref de preferințe masculine/feminine și întoarce lista tuturor cuplurilor instabile din engagements | ||
- | * ex: ''%%(get-unstable-couples '((ana . cos) (bia . adi) (cora . bobo)) men-preferences women-preferences)%%'' => ''%%'((ana . cos) (bia . adi))%%'' (întrucât ana și adi se preferă reciproc în dauna partenerilor lor actuali) | + | * ex: ''%%(get-unstable-couples '((ana . cos) (bia . adi) (cora . bobo)) men-preferences women-preferences)%%'' => ''%%'((ana . cos) (bia . adi))%%'' (întrucât ana și adi se preferă reciproc în dauna partenerilor lor actuali) (ordinea cuplurilor în rezultat nu contează, checker-ul sortează singur returul funcției get-unstable-couples) |
<file> | <file> | ||
Line 187: | Line 187: | ||
Algoritmul de actualizare este bazat pe o metodă introdusă de Roth și Vande, și funcționează în felul următor: | Algoritmul de actualizare este bazat pe o metodă introdusă de Roth și Vande, și funcționează în felul următor: | ||
- | * pornește de la soluția anterioară (căsătoriile stabile la momentul anterior) | + | * pornește de la soluția anterioară - căsătoriile stabile la momentul anterior |
* dintre acestea, elimină cuplurile care au devenit instabile în urma schimbărilor de preferințe | * dintre acestea, elimină cuplurile care au devenit instabile în urma schimbărilor de preferințe | ||
* consideră că toate cuplurile rămase (care sunt stabile între ele) se găsesc împreună într-o cameră, în timp ce toate celelalte persoane din problemă așteaptă la coadă la intrarea în cameră | * consideră că toate cuplurile rămase (care sunt stabile între ele) se găsesc împreună într-o cameră, în timp ce toate celelalte persoane din problemă așteaptă la coadă la intrarea în cameră | ||
Line 222: | Line 222: | ||
* întrucât toate persoanele au intrat în cameră, acesta este și rezultatul final | * întrucât toate persoanele au intrat în cameră, acesta este și rezultatul final | ||
- | Pentru exemplificarea următoarelor două funcții, vom folosi următoarele liste de preferințe reflectând situația la două momente de timp t0 și t1 (singura diferență apare la preferințele lui adi): | + | Pentru exemplificarea următoarelor două funcții, vom folosi următoarele liste de preferințe reflectând situația la două momente de timp t<sub>0</sub> și t<sub>1</sub> (singura diferență apare la preferințele lui adi): |
<file> | <file> | ||
(define men-preferences-0 (define men-preferences-1 | (define men-preferences-0 (define men-preferences-1 | ||
Line 236: | Line 236: | ||
<file> | <file> | ||
(update-stable-match engagements mpref wpref) | (update-stable-match engagements mpref wpref) | ||
- | </file> | + | </file> |
* update-stable-match primește o listă completă de logodne engagements (soluția SMP de la momentul anterior de timp), respectiv două liste mpref/wpref de preferințe masculine/feminine (de la momentul actual) și întoarce o nouă listă completă de logodne stabile (conform cu preferințele actuale) | * update-stable-match primește o listă completă de logodne engagements (soluția SMP de la momentul anterior de timp), respectiv două liste mpref/wpref de preferințe masculine/feminine (de la momentul actual) și întoarce o nouă listă completă de logodne stabile (conform cu preferințele actuale) | ||
* ex: ''%%(update-stable-match '((ana . adi) (bia . cos) (cora . bobo)) men-preferences-1 women-preferences-1)%%'' => ''%%'((ana . cos) (bia . adi) (cora . bobo))%%'' | * ex: ''%%(update-stable-match '((ana . adi) (bia . cos) (cora . bobo)) men-preferences-1 women-preferences-1)%%'' => ''%%'((ana . cos) (bia . adi) (cora . bobo))%%'' | ||
Line 250: | Line 250: | ||
</file> | </file> | ||
* build-stable-matches-stream primește un flux de instanțe SMP (reprezentând preferințele acelorași persoane la momente succesive de timp) și întoarce fluxul de soluții SMP corespunzătoare acestor instanțe | * build-stable-matches-stream primește un flux de instanțe SMP (reprezentând preferințele acelorași persoane la momente succesive de timp) și întoarce fluxul de soluții SMP corespunzătoare acestor instanțe | ||
- | * pentru exemplificare, considerăm că am definit fluxul pref-stream-a care are pe prima poziție perechea (cons men-preferences-0 women-preferences-0) și pe a doua (și ultima) poziție perechea (cons men-preferences-1 women-preferences-1) | + | * pentru exemplificare, considerăm că am definit fluxul pref-stream-a care are pe prima poziție perechea ''%%(cons men-preferences-0 women-preferences-0)%%'' și pe a doua (și ultima) poziție perechea ''%%(cons men-preferences-1 women-preferences-1)%%'' |
* ex: ''%%(build-stable-matches-stream pref-stream-a)%%'' => un flux care are pe prima poziție căsătoriile ''%%'((ana . adi) (bia . cos) (cora . bobo))%%'' și pe a doua poziție căsătoriile ''%%'((ana . cos) (bia . adi) (cora . bobo))%%'' | * ex: ''%%(build-stable-matches-stream pref-stream-a)%%'' => un flux care are pe prima poziție căsătoriile ''%%'((ana . adi) (bia . cos) (cora . bobo))%%'' și pe a doua poziție căsătoriile ''%%'((ana . cos) (bia . adi) (cora . bobo))%%'' | ||
- | * primul element Sol0 din fluxul rezultat se obține aplicând algoritmul Gale-Shapley asupra preferințelor de la momentul t0 | + | * primul element Sol<sub>0</sub> din fluxul rezultat se obține aplicând algoritmul Gale-Shapley asupra preferințelor de la momentul t<sub>0</sub> |
- | * al doilea element din fluxul rezultat se obține aplicând update-stable-match asupra lui Sol0 și a preferințelor de la momentul t1 | + | * al doilea element din fluxul rezultat se obține aplicând update-stable-match asupra lui Sol<sub>0</sub> și a preferințelor de la momentul t<sub>1</sub> |
+ | |||
+ | ===== Precizări ===== | ||
+ | |||
+ | * Exercițiile din fiecare etapă se rezolvă în fișierul care poartă numele etapei (**etapa1.rkt**, **etapa2.rkt**, etc.). Pentru testare, veți rula codul din fișierul **checker.rkt**. | ||
+ | * Fiecare etapă (o arhivă .zip cu fișierul care poartă numele etapei plus eventualele fișiere care sunt solicitate de acesta cu "require") se va încărca pe vmchecker. Testele de vmchecker sunt aceleași cu cele din checker.rkt. Pentru etapele 3 și 4 testele folosesc funcția stable-match? implementată în etapa 2. Pentru a preveni teste care trec sau nu trec din cauză că funcția stable-match? este implementată greșit, pe vmchecker vom folosi un stable-match? implementat de noi (deci în această situație puteți obține punctaje diferite local față de vmchecker). | ||
+ | * Dacă doriți să rezolvați exerciții din etapa curentă care depind de exerciții din etapele anterioare pe care nu le-ați rezolvat, puteți semnala acest lucru asistentului, care vă va pune la dispoziție o rezolvare pentru acele exerciții astfel încât să puteți continua tema. Odată ce alegeți această variantă, nu mai puteți primi punctaj pe exercițiile pentru care ați primit rezolvarea, chiar daca deadline-ul lor nu a expirat. Puteți solicita rezolvări doar pentru exercițiile din etapele anterioare, nu și pentru cele din etapa curentă. Dacă implementați un exercițiu din etapa curentă pe baza unui alt exercițiu din etapa curentă pe care nu l-ați rezolvat, se va lua în calcul punctajul dat de checker, chiar dacă implementarea ar funcționa în caz că exercițiul nerezolvat ar funcționa. | ||
+ | * Tema este în primul rând o temă de programare funcțională - pentru care folosim Racket. Racket este un limbaj multiparadigmă, care conține și elemente "ne-funcționale" (de exemplu proceduri cu efecte laterale), pe care **nu** este permis să le folosiți în rezolvare. | ||
+ | * Pentru fiecare etapă, checker-ul vă oferă un punctaj între 0 și 120 de puncte. Pentru a obține cele 1.33p din nota finală cu care este creditată tema de Racket, este suficient să acumulați 400 de puncte de-a lungul celor 4 etape. Un punctaj între 400 și 480 se transformă într-un bonus proporțional. | ||
+ | * Veți prezenta tema asistentului, care poate modifica punctajul dat de checker dacă observă nereguli precum răspunsuri hardcodate, proceduri cu efecte laterale, implementări neconforme cu restricțiile din enunț. | ||
+ | |||
+ | ===== Resurse ===== | ||
+ | |||
+ | ===== Changelog ===== | ||
+ | * 28.02 (ora 23:25) - Am publicat tema. | ||
+ | |||
+ | ===== Referinţe ===== | ||
+ | * [[https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8871443/|Matching-Updating Mechanism: A Solution for the Stable Marriage Problem with Dynamic Preferences]] | ||