300 likes | 534 Views
Curs 6. Algoritmi de enumerare ş i paradigma “backtracking” “backtracking” – prezentare general ă algoritmi de enumerare “backtracking” – algoritmi Studii de caz problema celor n regine colorarea grafurilor submul ţ imea de sum ă dată. Backtracking: cadru l general.
E N D
Curs 6 • Algoritmi de enumerare şi paradigma “backtracking” • “backtracking” – prezentare generală • algoritmi de enumerare • “backtracking” – algoritmi • Studii de caz • problema celor n regine • colorarea grafurilor • submulţimea de sumădată
Backtracking: cadrul general • metoda de rezolvare: căutare în spaţiul soluţiilor candidat (finit) • căutare exhaustivă: este cercetat întregul spaţiu • backtracking = căutare sistematică • spaţiul soluţiilor este organizat ca un arbore • un vârf este viabil dacă sunt şanse să se găsească o soluţie explorând subarborele cu rădăcina în acel vârf • sunt exploraţi numai subarborii cu rădăcini viabile • "backtracking" explorează lista vârfurilor viabile din arbore utilizând DFS
Backtracking: elemente de bază • spaţii de căutare: • produsul cartezian • submulţimi • permutări • drumuri în graf • etc. • se defineşte o funcţie criteriu prin care se stabileşte dacă un vârf este viabil sau nu • arborele este explorat prin algoritmul DFS • fie x = (x0, ..., xk) secvenţa care descrie drumul de la rădăcină la vârful curent • dacă vârful curent este pe frontieră se verifică dacă x este soluţie • în caz contrar se alege următorul succesor viabil (dacă există)
Backtracking pentru probleme de minim • problema: calculul lui minx f(x) • presupunere: f(x1,...,xk-1, xk) = f(x1,...,xk-1) + g(xk) cu g(xk) > 0 • se porneşte cu un minim iniţial • dacă vârful curent este pe frontieră se verifică dacăf(x) este mai mic decât minimul calculat pânăîn acel moment; dacă da, atunci f(x) devine noul minim • dacă vârful curent NU este pe frontierăşi f() calculat pentru soluţia parţială este mai mare decât minimul calculat pânăîn acel moment, atunci vârful nu este viabil şi este abandonat
3 1 2 2 1 2 2 1 1 (3,2) (3,1) (2,2) (2,1) (1,2) (1,1) Spaţiul soluţiilor = produs cartezian • S = {1,2,3} {1,2} • dimensiunea spaţiului: A0 A1 ... An-1 are |A0| |A1| ... |An-1| elemente
Enumerarea elementelor din {0,...,m-1}n • fiecare vârf în arbore este identificat cu drumul de la rădăcină până la el: (x0, x1, ..., xk) • pentru vârful de pe frontieră, k = n-1 şi drumul (x0, x1, ..., xn-1) este un element al produsului • simulăm generarea arborelui prin parcurgere DFS • stiva este reprezentată de variabila simplă k; aceasta indică poziţia vârfului stivei
Enumerarea elementelor din {0,...,m-1}n procedure EnumProdCart(m,n) begin k 0; x[0] -1 while (k >= 0) do if (x[k] < m-1) then x[k]++ if (k=n-1) then scrie(x) else k++ x[k] -1 else k-- end
2 0 1 2 0 2 2 0 0 1 1 1 (2,1) (2,0) (1,0) (1,1) (1,2) (2,2) (1,2) (0,1) (0,0) Exemplu • S = {0,1,2} 2
Produs cartezian – algoritm recursiv • (x0, x1, ..., xk, ...xn-1) • xk ia valori 0, 1, 2, ..., m-1 procedure enumProdCartRec(x, k) for j 0 to m-1 do x[k] j if (k = n-1) then scrieElement(x, n) else enumProdCartRec(x, k+1) end enumProdCartRec(x, 0)
Spaţiul soluţiilor = submulţimi • S {0, 1, ..., n-1} • S poate fi reprezentată prin vectorul său caracteristic x: x[i] {0,1}, x[i] = 1 i S • vectorul caracteristic {0,1}n • enumerare submulţimi = enumerare vectori caracteristici • dimensiune spaţiu: 2n
0 1 0 1 0 1 0 0 0 0 1 1 1 1 Submulţimi: exemplu n = 3 {2} {1} {1,2}
2 0 1 2 2 1 1 0 0 2 1 2 0 0 1 0 1 2 0 2 1 1 0 2 1 2 0 2 0 1 2 1 0 Spaţiul soluţiilor = permutări • enumerare permutări prin "bactracking" • x[k] viabil 0 x[k] n-1 si x[k] x[i] pentru i = 0, ..., k-1 n = 3:
Spaţiul soluţiilor = permutări • Varianta recursivă: Fie Sn mulţimea permutărilor elementelor mulţimii{0, 1, …, n-1} • Orice permutare din Sn se obţine dintr-o permutare din Sn-1 prin adăugarea lui n-1 într-o anume poziţie • Definiţia recursivă: • S0 = {(0)} • Sn = { (io, …,in-2, n-1), (io, …, n-1, in-2), …,(n-1, io,…,in-2) | (io, …,in-2) Sn-1} • Generalizare: Sn(, k) mulţimea permutărilor din Sn ce pot fi obţinute din Sk: Sn(, k) = Sn((io, …,ik-1, k), k+1) ... Sn((k, io, …,ik-1), k+1), unde = (io, …,ik-1) • Sn(, n) = {} • Sn = Sn((0), 1)
O reprezentare (0) (0,1) (1,0) (0,1,2) (0,2,1) (2,0,1) (1,0,2) (1,2,0) (2,1,0)
Spaţiul soluţiilor = permutări (recursiv) procedure enumPermRec(p, k) if (k = n) then scriePerm(p,n) else p[k] k for i k-1 downto 0 do enumPermRec(p,k+1) swap(p[i+1],p[i]) enumPermRec(p,k+1) end p[0] = 0 enumPermRec(p, 0)
Spaţiul soluţiilor = permutări (nerecursiv) procedure enumPerm(n) k 0 S[0] 0 while (k >= 0) do if (S[k] >= 0) //pozitia pe care se afla k in //permutarea generarii curente then f(k, S[k], p) S[k] S[k]-1 if (k = n-1) then scriePerm(p,n) else k k+1 S[k] k else aux p[0] for i 0 to k-1 do p[i] p[i+1] p[k] aux k k-1 end
Spaţiul soluţiilor = permutări function f(k, i, p) if (i = k) then p[k] k else aux p[i+1] p[i+1] p[i] p[i] aux end
0 0 1 4 4 1 2 2 3 3 3 2 4 3 2 1 2 1 4 Spaţiul soluţiilor = drumuri în graf cu sursa dată • se parcurge DFS • ori de câte ori se epuizează lista de aşteptare a lui i ≠ i0 se face p[i] = a[i] (se reia de la capăt) • se înlocuieşte testul i S cu i stiva
(0,0) (0,0) (0,1) (0,2) (1,0) (0,1) (1,1) (1,1) (1,0) (0,2) (1,2) (1,1) (0,1) (1,2) (1,2) (1,0) (1,2) (0,2) (1,2) Drumuri în graf cu sursa şi destinaţia precizate • lista de adiacenţă = parcurgerea în sensul acelor de ceasornic începând cu vecinul din dreapta • se parcurge DFS începând cu (0, 0) • ori de câte ori se întâlneşte (1,2) stiva descrie un drum de la (0,0) la (1,2)
(0,0) (5,3) Spaţiul soluţiilor = labirint lista de adiacenţă = parcurgerea în sensul arcelor de ceasornic începând cu vecinul din dreapta
Backtracking – algoritm nerecursiv procedure backtracking(n) k 0 while (k >= 0) do if ((exista y in T(x[0..k]) neincercat) and (viabil(y))) then x[k+1] y if (x = solutie) then scrie(x) else k k+1 else k k-1 end T(x[0..k]) multimea tuturor valorilor posibile pentru x[k+1]
Backtracking – algoritm recursiv procedure backtrackingRec(x, k) forall y in T(x[0..k]) neincercat and viabil(y) do x[k+1] y if (x = solutie) then scrie(x) else backtrackingRec(x, k+1) end
Backtracking – spaţiul produs cartezian procedure backtrack(n, m) k 0 x[0] -1 while (k >= 0) do if (x[k] < m-1) then repeat x[k] x[k]+1 until(viabil(x, k) or (x[k]=m-1)) if (viabil(x, k)) then if ((k = n-1) and ST(x)) then scrieElement(x,n) else k k+1 x[k] -1 else k k-1 end
Backtracking – spaţiul produs cartezian procedure backtrackRec(x, k) for j 0 to m-1 do x[k] j if ((k = n-1) and (ST(x)) then scrieElement(x, n) else if (viabil(x, k)) then backtrackRec(x, k+1) end
0 1 2 3 0 1 2 3 Backtracking: problema celor n regine • Problema • intrare: o tablă de şah n n, n regine • ieşire: toate aşezările posibile ale celor n regine pe tabla fără ca ele să se atace
Problema celor n regine • reprezentarea soluţiei • o reprezentare care nu-i OK Q[i,j] = true pe pozitia [i,j] se găseste o regină nr. sol. candidat = 2nn • o reprezentare mai bună s[i] = j Q[i,j] = true nr. sol. candidat = nn n = 8 2nn = 264, nn = 224 • criteriul de viabilitate • (i) 0 i k – 1 s[i] s[k] |s[i] – s[k]| |i-k|
3 0 2 1 0 3 0 3 2 1 0 3 2 1 1 2 Problema celor n regine: arborele tăiat 0 1 2 3 0 x x 1 x x 2 x x x x 3
Backtracking: colorarea grafurilor • problema • instanţa • un graf G = (V, E), V = {0, ..., n-1}, • m culori 1, 2, ..., m • colorare c : V {1, 2, ..., m}, {i, j} E c[i] c[j] • ieşire: • toate colorările posibile • modelul matematic • reprezentarea soluţiilor • c {1, 2, ...,m}n • criteriul de viabilitate • (j) 0 j < k and {j, k} E c[j] c[k]
Backtracking: submulţimi de sumă dată • problema • instanţa • o mulţime A cu n elemente • fiecare a A are o mărime s[a] Z+ • un număr M Z+ • ieşire • submulţimile A’ A cu (s[a] a A’) = M
Backtracking: submulţimi de sumă dată • modelul matematic • reprezentarea soluţiei • pp. A = {0, 1, ..., n-1}, s[i] = wi • A' reprezentată prin vectorul caracteristic x • criteriul de viabilitate: i=1,k xiwi M şi i=1,k xiwi + i=k+1,n wi M