ALGORYTMY I STRUKTURY DANYCH WYKŁAD 14 Techniki konstruowania algorytmów – programowanie dynamiczne Grażyna Mirkowska PJWSTK, 2004
G. Mirkowska, ASD_14 Progamowanie dynamiczne Plan wykładu Paradygmat programowania dynamicznego Przykłady Mnożenie macierzy Najdłuższy wspólny podciąg Problem plecakowy 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Mnożenie macierzy Dany jest ciąg macierzy A1, A2,...,An. Obliczyć iloczyn A1 A2 ... An tak by koszt mnożenia był najmniejszy. Uwaga: Możemy pomnożyć macierz A przez B wttw, gdy A ma tyle kolumn ile B wierszy . Koszt(AB) = A .w *A .k* B .w Przykład Obliczyć A B C. A(10 100) B(100 5) C(5 50) (A B) C = A ( B C) Koszt prawej strony = (100 *5*50) + (10*100*50) = 75000 mnożeń skalarnych Koszt lewej strony = (10 *100*5 ) + (10*5*50)= 7500 mnożeń skalarnych 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Pomysł Prosty Algorytm? A ile jest możliwych ustawień nawiasów? n-1sza liczba Catalana (4n/n 3/2) Rozważyć wszystkie możliwe ustawienia nawiasów w ciągu, a potem wykonać mnożenia zgodnie z ustawieniem nawiasów. Za każdym razem wyliczyć koszt mnożenia przy danym ustawieniu nawiasów i wybrać to ustawienie, które ma koszt najmniejszy. Za duży koszt! Pomysł A ile jest możliwych ustawień nawiasów? (A1, ..., Ak) ( Ak+1, ...,An) Niech P(n) będzie liczbą ustawień nawiasów w ciągu n elementowym. 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Paradygmat programowania dynamicznego 1. Scharakteryzować strukturę rozwiązania optymalnego. W naszym przykładzie: dla pewnego k, policzymy najpierw optymalne ustawienie nawiasów dla iloczynu (A1,..., Ak) potem optymalne ustawienie nawiasów dla iloczynu (Ak+1..,An), a potem dodamy do tego koszt mnożenia 2 macierzy. Rozwiązanie optymalne zawiera w sobie optymalne rozwiązania dla podproblemów. 2. Zdefiniować rekurencyjnie wartość rozwiązania optymalnego, jako funkcję rozwiązań optymalnych dla podproblemów. 3. Skonstruować rozwiązanie problemu na bazie wyliczonych wielkości. 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Liczymy minimalne koszty Niech m[i,j] będzie minimalną liczbą mnożeń skalarnych potrzebnych do policzenia iloczynu ( Ai..,Aj), oraz macierz Ai ma wymiar (p i-1 pi). Przecież można zapamiętywać policzone wcześniej wartości m[i,j]! Niech s[i,j] = k, gdzie k realizuje minimum dla m[i,j]. Rekurencyjny algorytm obliczania m[i,j] nie jest możliwy do zastosowania, bo jego koszt jest wykładniczy, ale... 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Algorytm MCM Koszt O(n3) Ustawienie początkowej wartości elementów tablicy m. for i :=1 to n do m[i,i] :=0; od; for x := 2 to n do for i := 1 to n-x+1 do j := i+x-1 m[i,j] := +; for k := i to j-1do q := m[i,k]+m[k+1,j] + pi-1*pk *pj; if q < m[i,j] then m[i,j] := q; s[i,j] :=k fi od od od return m,s; Dwie pętle odpowiedzialne za wypełnienie wszystkich elementów m[i,j]. Zauważyć, że wszystkie liczby m[i,k] i m[k+1,j] są już wyliczone. Wyszukiwanie minimum Koszt O(n3) 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Przykład (n=6) A1(3035) A2(35 15) A3(15 5) A4(5 10) A5(10 20) A6(20 25) m[2,5]= min { m[2,2] + m[3,5] + p1*p2*p5, m[2,3] + m[4,5] + p1*p3*p5, m[2,4] + m[5,5] + p1*p4*p5 } 15125 10500 5375 3500 5000 11875 7125 2500 1000 9375 4375 750 7875 2625 15750 1 2 3 4 5 6 3 5 4 1 2 6 Tablica s A1 A2 A3 A4 A5 A6 Tablica m 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
W jakiej kolejności mnożyć? Zasada 3 paradygmatu programowania dynamicznego: Skonstruować rozwiązanie problemu na bazie wyliczonych wielkości. W naszym przykładzie : Mnóż (A,s,1,6) daje : (A1(A2 A3))((A4A5) A6) mnóż(A,s,i,j) { If j>i then X := mnóż(A,s,i,s[i,j]); Y:= mnóż(A,s,s[i,j]+1, j); return wynik mnożenia macierzy (XY) else return Ai } Algorytm 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Najdłuższy wspólny podciąg Dane są dwa ciągi znaków X i Y X = (x1,…xm) Y = (y1,…,yn) Znaleźć taki ciąg Z=(z1,…zk), że Z jest najdłuższym podciągiem zarówno ciągu X jak i Y, ozn. Z = nwp(X,Y) Problem Ale to zbyt dużo kosztuje O(2m) Wygenerować wszystkie podciągi ciągu X. Dla każdego z tych ciągów sprawdzić czy występuje w Y, zapamiętując jednocześnie najdłuższy z takich ciągów. Przykład Algorytm naiwny X = aawbbsccpddólnvby Y = xxwsyyypózzlinsy nwp(X,Y) = wspólny 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Analiza zadania Oznaczenie: Xi = (x1,…xi) Niech X= (x1,…xm) Y= (y1,…,yn) oraz nwp(X,Y) = Z , gdzie Z= (z1,…zk). Jeżeli xm= yn, wtedy zk=xm=yn oraz Z k-1= nwp(Xm-1, Yn-1). Jeżeli xm yn, wtedy Z = nwp(Xm-1,Y) i zk xm lub Z = nwp(X,Yn-1) i zk yn. Twierdzenie Przykład Abrakadabrabarakuda Abrakadabr barakud Abrakad barakud Abrakabaraku itd k d a 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Algorytm2 string nwp(X,Y :string) : string; begin string Z; if x(m) = y(n) then Z := nwp(X m-1, Y n-1) x(m) else Z1 := nwp(X m-1, Y); Z2 := nwp(X, Y n-1); Z := dłuższy z ciągów Z1 i Z2; fi ; return Z; end; konkatenacja Równanie rekurencyjne można napisać tak T(n+m) = T(n+m-1) + T(m-1+n) = 2 T(n+m-1), T(2) =1 Koszt tego algorytmu będzie w najgorszym razie wykładniczy. 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
Jak wyliczyć długość nwp(X,Y)? długość najdłuższego wspólnego podciągu ciągów X,Y. d(X,Y) = d( X m-1 ,Y n-1 ) +1, gdy xm=yn d(X,Y) = max (d(X m-1 ,Y),d(X ,Y n-1 ), gdy xmyn Przykład 1 2 3 4 5 6 B D C A B A 1 A 0 0 0 1 1 2 2 B 1 1 1 1 2 2 3 C 1 1 2 2 2 2 Koszt Koszt obliczenia d(X,Y) wynosi card(X) * card(Y) porównań. 1 1 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Algorytm Begin for i :=1 to m do d(i,0):=0 od; for j :=0 to n do d(0,j) := 0 od; for i :=1 to m do for j :=1 to n do if x(i)=y(j) then d(i,j) := d(i-1,j-1) +1; b(i,j) := „\” else if d(i-1,j) d(i,j-1) then d(i,j) := d(i-1,j); b(i,j) := „” else d(i,j) := d(i,j-1); b(i,j) := „ ” fi fi od od end Po przekątnej zadanie, które trzeba rozwiązać, żeby otrzymać optymalny wynik. „w górę” zadanie, które trzeba rozwiązać, żeby otrzymać optymalny wynik „w lewo” zadanie, które trzeba rozwiązać, żeby otrzymać optymalny wynik 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Wypisanie nwp Procedure Drukuj(b,i,j); begin if i=0 or j=0 then return fi; if b(i,j) = „\” then call drukuj(b,i-1,j-1); write(x(i)) else if b(i,j) = „ ” then call drukuj(b,i-1,j) else call drukuj (b,i,j-1) fi fi end Przykład b(i,j) 1 2 3 4 5 6 B D C A B A 0 0 0 0 0 0 1 A 0 0 0 0 1 1 2 2 B 0 1 1 1 1 2 2 3 C 0 1 1 2 2 2 2 4 B 0 1 1 2 2 3 3 5 D 0 1 2 2 2 3 3 6 A 0 2 2 3 3 4 4 7 B 0 1 2 2 3 4 4 1 1 2 2 3 3 4 4 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Problem plecakowy Dane jest n obiektów oraz liczba całkowita M (pojemność plecaka). Niech s(i) oznacza rozmiar obiektu itego, a w(i) wartość tego obiektu. Zarówno M jak rozmiary i wartości są liczbami naturalnymi. Znaleźć takie liczby naturalne x1, x2,...xn, by Sxi s(i) M, a suma Sxi w(i) miała największą wartość. Złodziej może zabrać 5 obiektów A o wartości 20 lub 4 obiekty B o wartości 16 lub 2C i 1A o wartości 24. Powiedzmy, że w banku są obiekty A,B,C,D,E, których rozmiary i wartości są jak na rysunku. lub B. Jest wiele komercyjnych zastosowań w których występuje problem plecakowy: pakowanie kontenerów, samochodów. Przykład 17 A,3,4 B,4,5 C,7,10 D,8,11 E,9,13 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Algorytm Niezmiennik: dla x <i, koszt[x] = maksymalna wartość plecaka o pojemności x, jeśli mamy do dyspozycji tylko obiekty o numerach <j Rozwiązanie polega na wyliczeniu najlepszych kombinacji elementów dla wszystkich pojemności plecaka od 1 do M. for j := 1 to n do for i := 1 to M do if i – s[j] 0 then if koszt[i]< (koszt[i-s[j]] + w[j])then koszt [i] := koszt[i-s[j]] + w[j]; b[i] :=j fi fi od od Koszt: n* M operacji Koszt tego algorytmu n*M. Dla małych M jest on akceptowalny ale dla dyżych nie. Zauważmy, że ten algorytm nie działa poprawnie jeśli M lub rozmiary lub wartości nie jest liczbami naturalnymi. Co więcej nie jest znany żaden dobry algorytm dla tego problemu. b[i] ostatni element, który został dodany do plecaka by osiągnąć wartość maksymalną. koszt[i] = największa wartość jaka może być osiągnięta jeśli pojemność plecaka wynosi i 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne
G. Mirkowska, ASD_14 Progamowanie dynamiczne Przykład tablica kosztów tablica b-ostatni element 2 3 4 5 6 7 8 9 1 10 11 12 13 14 15 16 17 4 8 12 16 20 A 4 5 8 9 10 12 13 14 16 17 18 20 21 22 A B 4 5 8 10 12 14 15 16 18 20 22 24 A B C 4 5 8 10 11 12 14 15 16 18 20 21 22 24 A B C D b[M] jest w plecaku i mogę to odczytać. pozostała zawartość jest taka sama jak dla optymalnego rozwiązania dla plecaka o rozmiarze M-s[b[M]]. Zatem następny obiekt to b[M-s[b[M]]]. Oznaczmy M-s[b[M]]= k wtedy następny element biorę jako b[k]. Teraz muszę sprawdzić optymalne rozwiązanie dla plecaka o rozmiarze k- s[b[k]] (odejmuję rozmiar ostatnio wlozonego obiektu) itd. 4 5 8 10 11 13 14 15 17 18 20 21 23 24 A B C D E Zawartość plecaka: b[17]= C, b[17-7]= C, b[10-7]=A Największa wartość = 24 2018-12-25 G. Mirkowska, ASD_14 Progamowanie dynamiczne