Table of Contents

Racket: Problema mariajelor stabile

Descriere generală și organizare

Tema constă în rezolvarea problemei mariajelor stabile și este împărțită în 4 etape:

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 23.03, 30.03, 06.04, 13.04).

Rezolvările tuturor etapelor pot fi trimise până în ziua laboratorului 6, dar orice exercițiu trimis după deadline (și până în ziua laboratorului 6) se punctează cu jumătate din punctaj. Orice exercițiu trimis după ziua laboratorului 6 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, nota pe ultima submisie este și nota finală (întrucât n1 = n2).

În fiecare etapă, veți folosi ce ați învățat în săptămâna anterioară pentru a dezvolta aplicația.

Pentru fiecare etapă veți primi un schelet de cod (dar rezolvarea se bazează în mare măsură pe rezolvările anterioare). Enunțul din această pagină este menit să descrie problema mariajelor stabile (pe care o vom denumi SMP, conform prescurtării în limba engleză) și să vină cu exemple de rulare a funcțiilor din schelet. Dacă preferați, odată ce ați înțeles problema, puteți rezolva tema utilizând doar indicațiile din schelet.

Etapa 1

Î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 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:

(define men-preferences
  '([adi  ana  bia cora]
    [bobo cora ana bia ]
    [cos  cora bia ana ]))
(define women-preferences
  '([ana  bobo adi cos ]
    [bia  adi  cos bobo]
    [cora bobo cos adi ]))

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ță.

În etapa 1, veți exersa lucrul cu:

Funcțiile pe care va trebui să le implementați sunt:

(get-men mpref)
(get-women wpref)
(get-pref-list pref person)
(preferable? pref-list x y)
(get-partner engagements person)
(better-match-exists? p1 p2 p1-list pref2 engagements)

Etapa 2

În această etapă veți reimplementa majoritatea funcțiilor din etapa anterioară folosind ce ați învățat în utima săptămână. Apoi veți implementa verificarea stabilității unei liste de căsătorii.

Scopul etapei este consolidarea cunoștințelor legate de:

Funcțiile noi pe care va trebui să le implementați sunt:

(find-first p L)
(change-first p L val)
(update-engagements engagements p1 p2)
(stable-match? engagements mpref wpref)

Etapa 3

În această etapă veți rezolva problema mariajelor stabile folosind algoritmul Gale-Shapley și veți implementa câteva funcții necesare etapei următoare. Observați că la începutul fișierului etapa3.rkt apare linia (require "etapa2.rkt"), ceea ce înseamnă că va fi necesar să aduceți rezolvarea etapei 2 în același folder în care rezolvați etapa 3, pentru a beneficia de funcțiile implementate anterior.

Veți continua să folosiți recursivitate și funcționale (facilități fundamentale în programarea funcțională), dar scopul principal al etapei este lucrul cu expresii de legare statică a variabilelor:

Funcțiile pe care va trebui să le implementați sunt:

(get-unstable-couples engagements mpref wpref)
(engage free-men engagements mpref wpref)
(gale-shapley mpref wpref)
(get-couple-members pair-list)

Etapa 4

În această etapă veți rezolva SMP pentru cazul în care preferințele evoluează în timp, așa cum se întâmplă adesea în realitate. Orice schimbare poate afecta stabilitatea căsătoriilor obținute anterior, dar - având în vedere că preferințele nu se schimbă radical de la un moment la altul - pare mai puțin costisitor ca în loc să rulăm algoritmul Gale-Shapley de la zero de fiecare dată când se schimbă ceva, să pornim de la soluția anterioară și să o actualizăm pe aceasta în cazul în care identificăm în ea cupluri instabile.

Observați că la începutul fișierului etapa4.rkt se solicită să aduceți în folderul curent rezolvările etapelor 2 și 3, pentru a beneficia de funcțiile implementate anterior.

Veți exersa în continuare stilul funcțional de a programa studiat în săptămânile anterioare, plus conceptul de flux introdus la ultimul laborator. Întrucât o instanță SMP este reprezentată prin două liste de preferințe masculine, respectiv feminine, vom reprezenta SMP cu preferințe dinamice ca pe un flux de instanțe SMP, fiecare element din flux reprezentând preferințele la un anumit moment în timp. Soluția SMP cu preferințe dinamice trebuie calculată tot sub formă de flux, unde fiecare element este o listă de căsătorii stabile conform preferințelor la momentul respectiv. Veți obține primul element din fluxul rezultat aplicând algoritmul Gale-Shapley asupra primului element din fluxul de intrare, iar pe următoarele prin aplicarea succesivă a algoritmului de actualizare prezentat mai jos.

Algoritmul de actualizare este bazat pe o metodă introdusă de Roth și Vande, și funcționează în felul următor:

Toate funcțiile din această etapă întorc una sau mai multe liste de cupluri. Așa cum v-ați obișnuit în etapa anterioară, ordinea cuplurilor în listă nu contează (dar pe prima poziție a fiecărui cuplu se va găsi un bărbat/o femeie, în funcție de cum cere fiecare funcție în parte). Aveți de implementat următoarele funcții:

(match person engagements pref1 pref2 queue)
(path-to-stability engagements mpref wpref queue)

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):

(define men-preferences-0       (define men-preferences-1
  '([adi  ana  bia cora]          '([adi  cora  bia ana]
    [bobo cora ana bia ]            [bobo cora ana bia]
    [cos  cora bia ana ]))          [cos  cora bia ana]))
(define women-preferences-0     (define women-preferences-1
  '([ana  bobo adi cos ]          '([ana  bobo adi cos ]
    [bia  adi  cos bobo]            [bia  adi  cos bobo]
    [cora bobo cos adi ]))          [cora bobo cos adi ]))
(update-stable-match engagements mpref wpref)
(build-stable-matches-stream pref-stream)

Precizări

Resurse

Changelog

Referinţe