Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
aa:lab:6 [2023/11/16 01:30] vlad.juja |
aa:lab:6 [2024/11/28 18:12] (current) lfa |
||
---|---|---|---|
Line 13: | Line 13: | ||
Înainte de a trece la examinarea unor probleme pe grafuri, este util să recapitulăm ce sunt grafurile. \\ | Înainte de a trece la examinarea unor probleme pe grafuri, este util să recapitulăm ce sunt grafurile. \\ | ||
- | Grafurile sunt considerate a fi perechi G = (V, E), unde V reprezintă un set de noduri, iar E un set de muchii. Fiecare nod este identificat printr-un număr de la 1 la |V|. O muchie este o pereche de noduri. De obicei, ne referim la grafurile neorientate, unde o muchie este o pereche neordonată. \\ | + | Grafurile sunt considerate a fi perechi $ G = (V, E)$, unde $ V$ reprezintă un set de noduri, iar E un set de muchii. Fiecare nod este identificat printr-un număr de la 1 la $ |V|$. O muchie este o pereche de noduri. De obicei, ne referim la grafurile neorientate, unde o muchie este o pereche neordonată. \\ |
- | Vom utiliza matricele de adiacență pentru a reprezenta grafurile. O matrice de adiacență este o tabelă de dimensiune |V| pe |V|, unde nodurile indexează atât liniile, cât și coloanele; intrarea i, j a matricei este o valoare booleană care arată dacă (i, j) ∈ E. Pentru grafurile neorientate, matricea este simetrică în raport cu diagonala principală. \\ | + | Vom utiliza matricele de adiacență pentru a reprezenta grafurile. O matrice de adiacență este o tabelă de dimensiune $ |V|$ pe $ |V|$, unde nodurile indexează atât liniile, cât și coloanele; intrarea $ i$ , $ j$ a matricei este o valoare booleană care arată dacă $ (i, j) ∈ E$. Pentru grafurile neorientate, matricea este simetrică în raport cu diagonala principală. \\ |
Matricea de adiacență în sine conține toate informațiile necesare pentru a descrie graful, astfel încât poate servi ca intrare pentru algoritmii noștri.\\ | Matricea de adiacență în sine conține toate informațiile necesare pentru a descrie graful, astfel încât poate servi ca intrare pentru algoritmii noștri.\\ | ||
Line 23: | Line 23: | ||
=== 1. K Vertex Cover === | === 1. K Vertex Cover === | ||
- | Dându-se un graf neorientat G = (V, E) și un număr întreg pozitiv K, se cere găsirea unui subset V' ⊆ V, cu |V'| = K, astfel încât fiecare muchie din E să aibă cel puțin unul dintre capete în V'. \\ | + | Dându-se un graf neorientat $ G = (V, E)$ și un număr întreg pozitiv $ K$, se cere găsirea unui subset $ V' ⊆ V$, cu $ |V'| = K$, astfel încât fiecare muchie din $ E$ să aibă cel puțin unul dintre capete în $ V'$. \\ |
- | În termeni simpli, problema K Vertex Cover implică găsirea unui subset de K noduri astfel încât fiecare muchie a grafului să aibă cel puțin unul dintre capete în acel set. | + | În termeni simpli, problema K Vertex Cover implică găsirea unui subset de $ K$ noduri astfel încât fiecare muchie a grafului să aibă cel puțin unul dintre capete în acel set. |
* Propuneți o soluție greedy pentru această problemă. | * Propuneți o soluție greedy pentru această problemă. | ||
* Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | * Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | ||
Line 33: | Line 33: | ||
=== 2. K Clique === | === 2. K Clique === | ||
- | Dându-se un graf neorientat G = (V, E) și un număr întreg pozitiv K, se cere găsirea unui set V' ⊆ V, cu |V'| = K, astfel încât toate nodurile din V' sunt conectate între ele prin muchii din E. În termeni simpli, problema K Clique implică găsirea unui set de K noduri astfel încât oricare două noduri din acest set sunt conectate printr-o muchie (orice nod e conectat cu orice nod). | + | Dându-se un graf neorientat $ G = (V, E)$ și un număr întreg pozitiv $ K$, se cere găsirea unui set $ V' ⊆ V$, cu $ |V'| = K$, astfel încât toate nodurile din $ V'$ sunt conectate între ele prin muchii din $ E$. În termeni simpli, problema K Clique implică găsirea unui set de $ K$ noduri astfel încât oricare două noduri din acest set sunt conectate printr-o muchie (orice nod e conectat cu orice nod). |
* Propuneți o soluție greedy pentru această problemă. | * Propuneți o soluție greedy pentru această problemă. | ||
* Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | * Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | ||
Line 41: | Line 41: | ||
=== 3. K Coloring === | === 3. K Coloring === | ||
- | Dându-se un graf neorientat G = (V, E) și un număr întreg pozitiv K, se cere să se determine dacă este posibil să se atribuie culori nodurilor astfel încât nicio pereche de două noduri adiacente să nu aibă aceeași culoare, iar numărul total de culori utilizate să fie cel mult K. | + | Dându-se un graf neorientat $ G = (V, E)$ și un număr întreg pozitiv $ K$, se cere să se determine dacă este posibil să se atribuie culori nodurilor astfel încât nicio pereche de două noduri adiacente să nu aibă aceeași culoare, iar numărul total de culori utilizate să fie cel mult $ K$. |
* Propuneți o soluție greedy pentru această problemă. | * Propuneți o soluție greedy pentru această problemă. | ||
* Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | * Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | ||
Line 48: | Line 48: | ||
=== 4. Hamilton Path === | === 4. Hamilton Path === | ||
- | Dându-se un graf orientat G = (V, E), se cere să se determine dacă există un drum Hamiltonian în graful respectiv. Un drum Hamiltonian este un drum care vizitează fiecare nod exact o dată. | + | Dându-se un graf orientat $ G = (V, E)$, se cere să se determine dacă există un drum Hamiltonian în graful respectiv. Un drum Hamiltonian este un drum care vizitează fiecare nod exact o dată. |
* Propuneți o soluție greedy pentru această problemă. | * Propuneți o soluție greedy pentru această problemă. | ||
* Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | * Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | ||
- | * O variantă ușor modificată a acestui algoritm este TSP (The Travelling Salesman Problem): Dându-se un graf ponderat G = (V, E) și un buget B, există un drum Hamiltonian cu cost total mai mic decât B? Ce trebuie modificat în soluția anterioară pentru a obține soluția pentru TSP? | + | * O variantă ușor modificată a acestui algoritm este TSP (The Travelling Salesman Problem): Dându-se un graf ponderat $ G = (V, E)$ și un buget $ B$, există un drum Hamiltonian cu cost total mai mic decât $ B$? Ce trebuie modificat în soluția anterioară pentru a obține soluția pentru TSP? |
\\ | \\ | ||
=== 5. K Cut === | === 5. K Cut === | ||
- | Dându-se un graf G = (V, E) și un număr K, există o împărțire a nodurilor în două mulțimi astfel încât să existe k muchii cu câte un capăt în fiecare mulțime? | + | Dându-se un graf $ G = (V, E)$ și un număr $ K$, există o împărțire a nodurilor în două mulțimi astfel încât să existe $ K$ muchii cu câte un capăt în fiecare mulțime? |
* Propuneți o soluție greedy pentru această problemă. | * Propuneți o soluție greedy pentru această problemă. | ||
* Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | * Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect. | ||
Line 89: | Line 89: | ||
- | ===== Programare Dinamică și Pseudopolinomiale ===== | + | ===== Probleme NPC cu mulțimi de numere ===== |
- | Programarea dinamică este o tehnică de proiectare a algoritmilor care constă în rezolvarea unei probleme prin împărțirea acesteia în subprobleme mai mici și rezolvarea fiecăreia dintre acestea doar o dată, stocând rezultatele pentru a evita recalcularea lor ulterioară. Această abordare este eficientă în rezolvarea problemelor ce pot fi descompuse în subprobleme overlapped sau care prezintă o structură de optimalitate. \\ | + | Pentru urmatoarele probleme, propuneți o variantă de pseudocod ce verifică validitatea unui candidat. \\ |
+ | \\ | ||
- | Prin memorarea soluțiilor intermediare într-o tabelă sau altă structură de date, programarea dinamică ajută la reducerea complexității temporale și evită recalcularea anumitor subprobleme, contribuind la îmbunătățirea performanței algoritmilor. \\ | + | === 9. Subset Sum === |
+ | Dându-se un set de numere întregi $ S$ și un număr întreg $ K$, problema Subset Sum solicită determinarea dacă există un subșir $ A$ al lui $ S$ astfel încât suma elementelor din $ A$ să fie egală cu $ K$. Cu alte cuvinte, este posibil să se găsească o submulțime a numerelor din $ S$ astfel încât suma acestora să fie exact $ K$?\\ | ||
+ | \\ | ||
- | === 9. Knapsack === | ||
- | Avem un rucsac cu o capacitate maximă dată (exprimată într-o anumită unitate, de exemplu, greutate), și un set de obiecte, fiecare având o valoare și o greutate specifică. Scopul este să determinăm cum să umplem rucsacul astfel încât să maximizăm valoarea totală a obiectelor, având în vedere restricția de capacitate a rucsacului. | ||
- | Matematic, dacă notăm: \\ | ||
- | n - numărul total de obiecte disponibile, \\ | + | === 10. Partitioning === |
- | $ v_i$ - valoarea obiectului $ i$, \\ | + | |
- | $ w_i$ - greutatea obiectului $ i$, \\ | + | |
- | W - capacitatea maximă a rucsacului, \\ | + | |
- | atunci problema Knapsack poate fi formulată astfel: \\ | + | Dându-se un set $ S$ de numere întregi, se cere determinarea dacă setul poate fi împărțit în două submulțimi $ S_1$ și $ S_2$ astfel încât suma elementelor din $ S_1$ să fie egală cu suma elementelor din $ S_2$. Cu alte cuvinte, se caută o împărțire a setului în două submulțimi cu sume egale.\\ |
+ | \\ | ||
- | Maximizăm: $ ∑_{i=1}^n (v_i x_i)$ \\ | ||
- | Sub restricția: $ ∑_{i=1}^n (w_i x_i)≤W$ \\ | + | === 11. Set Cover === |
- | unde $ x_i$ este o variabilă binară ce indică dacă obiectul $ i$ este sau nu inclus în rucsac. Adică, $ x_i = 1$ dacă obiectul i este inclus și $ x_i = 0$ în caz contrar. | + | Date de intrare: Un univers $ U$ și o colecție $ S$ de submulțimi ale lui $ U$. \\ |
- | * Implementați algoritmul în scheletul de cod oferit și verificați-vă soluția | + | Problemă: Există o subcolecție $ S'$ a lui $ S$ astfel încât fiecare element din $ U$ este acoperit de cel puțin un subset din $ S'$? \\ |
+ | Verificare: Verificarea constă în a asigura că fiecare element din $ U$ este acoperit de cel puțin un subset din $ S'$. \\ | ||
+ | \\ | ||
+ | ===== BONUS: Programare Dinamică și Pseudopolinomiale ===== | ||
+ | Programarea dinamică este o tehnică de proiectare a algoritmilor care constă în rezolvarea unei probleme prin împărțirea acesteia în subprobleme mai mici și rezolvarea fiecăreia dintre acestea doar o dată, stocând rezultatele pentru a evita recalcularea lor ulterioară. Această abordare este eficientă în rezolvarea problemelor ce pot fi descompuse în subprobleme overlapped sau care prezintă o structură de optimalitate. \\ | ||
+ | Prin memorarea soluțiilor intermediare într-o tabelă sau altă structură de date, programarea dinamică ajută la reducerea complexității temporale și evită recalcularea anumitor subprobleme, contribuind la îmbunătățirea performanței algoritmilor. \\ | ||
+ | \\ | ||
- | /* | ||
- | 1. Folosiți Teorema Master pentru a rezolva următoarele recurențe: | ||
- | * $ T_1(n) = 4T_1(n/4) + 1$ | + | === 12. Knapsack === |
- | <hidden Exemplu de cod cu aceasta recurenta> | + | |
- | <code c> | + | |
- | // O metoda destul de ineficienta de calcul al sumei elementelor unui vector | + | |
- | int sum(int arr[], int lo, int hi) { | + | |
- | if(lo == hi) | + | |
- | return arr[lo]; | + | |
- | int x = (hi - lo) / 4; | + | |
- | return sum(arr, lo, lo + x) + | + | |
- | sum(arr, lo + x + 1, lo + 2 * x) + | + | |
- | sum(arr, lo + 2 * x + 1, lo + 3 * x) + | + | |
- | sum(arr, lo + 3 * x + 1, hi); | + | |
- | } | + | |
- | </code> | + | |
- | </hidden> | + | |
- | * $ T_3(n) = 4T_3(n/2) + n^2$ | + | |
- | * $ T_2(n) = 8T_2(n/2) + 2n^2$ | + | |
- | 2. Fie următorul algoritm de căutare a unei valori ''v'' într-un array sortat ''arr'': | + | Avem un rucsac cu o capacitate maximă dată (exprimată într-o anumită unitate, de exemplu, greutate), și un set de obiecte, fiecare având o valoare și o greutate specifică. Scopul este să determinăm cum să umplem rucsacul astfel încât să maximizăm valoarea totală a obiectelor, având în vedere restricția de capacitate a rucsacului. |
+ | Matematic, dacă notăm: \\ | ||
- | <code c> | + | $ n$ - numărul total de obiecte disponibile, \\ |
- | int search(int arr[], int lo, int hi, int v) | + | $ v_i$ - valoarea obiectului $ i$, \\ |
- | { | + | $ w_i$ - greutatea obiectului $ i$, \\ |
- | int mid = (lo + hi) / 2; | + | $ W$ - capacitatea maximă a rucsacului, \\ |
- | if (arr[mid] == v) | + | |
- | return mid; | + | |
- | if (lo == hi) | + | |
- | return -1; | + | |
- | if (arr[mid] > v) | + | |
- | return search(arr, lo, mid, v); | + | |
- | else | + | |
- | return search(arr, mid, hi, v); | + | |
- | } | + | |
- | </code> | + | atunci problema Knapsack poate fi formulată astfel: \\ |
- | * Determinați relația de recurență a algoritmului de căutare prezentat. | + | Maximizăm: $ ∑_{i=1}^n (v_i x_i)$ \\ |
- | * Demonstrați recurența utilizând Teorema Master. | + | |
- | * Demonstrați recurența utilizând Metoda Arborilor. | + | |
- | * Demonstrați recurența utilizând Metoda Substituției. | + | |
- | 3. Folosiți cele 3 metode (metoda arborilor, metoda substituției, teorema master) pentru a rezolva recurențele: | + | Sub restricția: $ ∑_{i=1}^n (w_i x_i)≤W$ \\ |
- | * $ T_a(n) = 2T_a(n-1) + 1$ | + | unde $ x_i$ este o variabilă binară ce indică dacă obiectul $ i$ este sau nu inclus în rucsac. Adică, $ x_i = 1$ dacă obiectul i este inclus și $ x_i = 0$ în caz contrar. |
- | * $ T_b(n) = T_b(n-1) + 1$ | + | |
- | * $ T_c(n) = 2T_c(n/2) + \log(n)$ | + | |
- | * $ T_d(n) = T_d(n/9) + T_d(8n/9) + n$ | + | |
- | * $ T_e(n) = T_e(2n/3) + 1$ | + | |
- | * $ T_f(n) = T_f(\sqrt{n}) + 1$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
- | * $ T_g(n) = 2T_g(\sqrt{n}) + n$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
- | * $ T_h(n) = \sqrt{n}T_h(\sqrt{n}) + n$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
- | 4. Rezolvați următoarea recurență folosind metoda substituției: $math[T(n) = 2 T(\frac{n}{2}) + 1]. | ||
- | 5. Rezolvați următoarea recurență folosind metoda arborilor: $math[T(n) = T(] $math[n \over 4] $math[) + T(] $math[3n \over 4] $math[) + n]. | + | <note> |
- | */ | + | Soluțiile acestui laborator se găsesc [[https://ocw.cs.pub.ro/ppcarte/doku.php?id=aa:lab:sol:6|aici]] |
+ | </note> |