Hard Problems
În cadrul acestui laborator vom analiza suita de probleme NPC (nondeterministic polynomial-time complete) despre care se va discuta la cursurile și laboratoarele următoare. Lăsând pentru o secundă formalitățile deoparte, NP reprezintă, în linii mari, clasa de probleme cu „soluții ușor verificabile”. Toți algoritmii noștri vor urma același model: vor genera o listă a tuturor posibilelor soluții, apoi vor verifica dacă o anumită soluție îndeplinește criteriile cerute de problemă. Dacă oricare dintre candidați îndeplinește aceste criterii, algoritmul furnizează un răspuns pozitiv; dacă niciun candidat nu reușește, algoritmul furnizează un răspuns negativ. Așadar, putem împărți algoritmul în două secțiuni:
- Generarea nedeterministă de soluții
- Certificatul polinomial (reprezintă etapa de verificare a soluției generate)
În cadrul laboratorului, ne vom focusa atenția pe cea de-a doua parte.
Probleme cu Grafuri
Î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ă.
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.
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'$.
Î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ă.
- Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect.
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).
- 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.
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$.
- 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.
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ă.
- 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.
- 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
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ă.
- Dați exemplu de o situație în care soluția greedy nu generează răspunsul corect.
Formule Satisfiabile
O formulă booleană se referă la o expresie logică formată din variabile booleene (care pot avea valorile adevărat sau fals) și operații logice precum conjuncție (AND), disjuncție (OR), și negație (NOT).
6. SAT
Primind ca intrare o formulă booleană, obiectivul problemei SAT este să se determine dacă există o atribuire a valorilor adevărat sau fals pentru variabilele booleane astfel încât întreaga formulă să fie evaluată la adevărat.
- Câți candidați sunt pentru soluție?
- Care este complexitatea generării tuturor soluțiilor?
- Oferiți pseudocod pentru verificarea polinomială a unui candidat (certificatul polinomial).
- Care este complexitatea certificatului polinomial?
7. CNF SAT
Asemănător, verifică dacă formula booleană primită ca input este satisfiabilă. Diferența constă în faptul că formula booleană este dată în forma conjunctivă normală, adică este scrisă sub forma unei conjuncții de clauze, unde o clauză este o disjuncție de literali. Un literal este fie o variabilă booleană, fie negația unei variabile booleene.
- Mai este valabilă soluția de la SAT?
- Pare să aibă soluție polinomială?
8. 3SAT
Adăugăm încă o restricție și anume că numărul de literali dintr-o clauză este egal cu 3.
- Garantează această contrângere o soluție mai eficientă?
Probleme NPC cu mulțimi de numere
Pentru urmatoarele probleme, propuneți o variantă de pseudocod ce verifică validitatea unui candidat.
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$?
10. Partitioning
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.
11. Set Cover
Date de intrare: Un univers $ U$ și o colecție $ S$ de submulțimi ale lui $ U$.
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.
12. 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,
$ v_i$ - valoarea obiectului $ i$,
$ w_i$ - greutatea obiectului $ i$,
$ W$ - capacitatea maximă a rucsacului,
atunci problema Knapsack poate fi formulată astfel:
Maximizăm: $ ∑_{i=1}^n (v_i x_i)$
Sub restricția: $ ∑_{i=1}^n (w_i x_i)≤W$
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.