Programowanie dynamiczne

Transkrypt

Programowanie dynamiczne
Notatki z AiSD. Nr 6.
Programowanie dynamiczne
Opracowaª: Krzysztof Lory±
IIUWr. II rok informatyki.
1
4 kwietnia 2014
Wst¦p
Zastosowanie metody Dziel i Zwyci¦»aj do problemów zdeniowanych rekurencyjnie jest w zasadzie
ograniczone do przypadków, gdy podproblemy, na które dzielimy problem, s¡ niezale»ne. W przeciwnym razie metoda ta prowadzi do wielokrotnego obliczania rozwi¡za« tych samych podproblemów.
Jednym ze sposobów zaradzenia temu zjawisku jest tzw. spami¦tywanie, polegaj¡ce na pami¦taniu
rozwi¡za« podproblemów napotkanych w trakcie oblicze«.
W przypadku, gdy przestrze« wszyst-
kich mo»liwych podproblemów jest niedu»a, efektywniejsze od spami¦tywania mo»e by¢ zastosowanie
metody programowania dynamicznego. Polega ona na obliczaniu rozwi¡za« dla wszystkich podproblemów, pocz¡wszy od podproblemów najprostszych.
Przykªad 1.
Problem:
Dane:
Wynik:
Liczby naturalne
n, k .
n
k .
n
n
n−1
n−1
k korzysta z zale»no±ci k = k−1 + k . Zastosowanie metody Dziel i Zwyci¦»aj byªoby jednak w tym przypadku nierozwa»ne, poniewa» w trakcie
n−1
n−1
liczenia
wywoªywaliby±my rekurencyjnie procedur¦ dla tych samych danych (tj. dla
k−1 jak i
k
n − 2 i k − 1), co w konsekwencji prowadzi do tego, »e niektóre podproblemy byªyby rozwi¡zywane
Naturalna metoda redukcji problemu obliczenia
wykªadnicz¡ liczb¦ razy. Poni»sza procedura unika tego wykorzystuj¡c tablic¦
tab[1..n, 1..k]
do spa-
mi¦tywania.
for i=1 to n do
for j = 0 to k do tabi,j ←00 ?00
..................
function nPOk(n, k)
if k = n or k =00000then tabk,n ← 1; return 1;
if tabn−1,k−1 = ? then tabn−1,k−1 ←nPOk(n − 1, k − 1)
if tabn−1,k =00 ?00 then tabn−1,k ←nPOk(n − 1, k)
tabn,k = tabn−1,k−1 + tabn−1,k
tabn,k
return
Rekurencyjne obliczanie
n
k
z u»yciem spami¦tywania
Za zastosowaniem w tym przypadku programowania dynamicznego przemawia fakt, i» liczba ró»-
n
k jest niewielka, a mianowicie
2
O(n ). Podobnie jak w metodzie spami¦tywania, algorytm dynamiczny oblicza pocz¡tkowy fragment
nych podproblemów, jakie mog¡ pojawi¢ si¦ w trakcie obliczania
trójk¡ta Pascala i umieszcza go w tablicy
tab.
W przeciwie«stwie jednak do poprzedniej metody,
która jest metod¡ top-down i jest implementowana rekurencyjnie, algorytm dynamiczny jest metod¡ bottom-up i jest implementowany iteracyjnie. To pozwala w szczególno±ci na wyeliminowanie
kosztów zwi¡zanych z obsªug¡ rekursji.
1
for i = 1 to n do tabi,0 ← 1
..................
function nPOk(n, k)
for j = 1 to k do
tabj,j ← 1
i=j+1
tabn,k
for
return
Obliczanie
n
k
to n do tabi,j ← tabi−1,j−1 + tabi−1,j
metod¡ programowania dynamicznego
Fakt, »e metoda programowania dynamicznego oblicza w sposób systematyczny rozwi¡zania wszystkich podproblemów, pozwala cz¦sto na poczynienie dodatkowych oszcz¦dno±ci w stosunku do metody
spami¦tywania.
W tym przykªadzie mo»emy znacznie zredukowa¢ koszty pami¦ciowe.
Jak ªatwo
zauwa»y¢, obliczenie kolejnej przek¡tnej trójk¡ta Pascala wymaga znajomo±ci jedynie warto±ci z poprzedniej przek¡tnej. Tak wi¦c zamiast tablicy
n×k
wystarcza tablica
n × 2,
a nawet tablica
n × 1.
2
Podobnie jak w przypadku metody dziel i zwyci¦»aj, kluczem do zastosowania programowania
dynamicznego jest znalezienie takiego sposobu dzielenia problemu na podproblemy, by optymalne rozwi¡zanie problemu mo»na byªo w prosty sposób otrzyma¢ z optymalnych rozwi¡za« podproblemów.
Wskazaniem na zastosowanie wówczas programowania dynamicznego a nie metody dziel i zwyci¦»aj
jest sytuacja, gdy sumaryczny rozmiar podproblemów jest du»y. Oczywi±cie, jak ju» wspominali±my,
aby algorytm dynamiczny byª efektywny, przestrze« wszystkich mo»liwych podproblemów nie mo»e
by¢ zbyt liczna.
Przykªad 2.
Problem:
{ai,j }
liczb nieujemnych (i
Dane:
Tablica
Wynik:
Ci¡g indeksów
Pm
j=1
i1 , . . . , im
taki, »e
= 1, . . . , n; j = 1, . . . , m)
∀j=1,...,m−1 |ij − ij+1 | ≤ 1,
minimalizuj¡cy sum¦
aij ,j
Interpretacja: Ci¡g
kolumny tablicy
a.
i1 , . . . , i m
wyznacza tras¦ wiod¡c¡ od pierwszej do ostatniej
Startujemy z dowolnego pola pierwszej kolumny i ko«czymy na
dowolnym polu ostatniej kolumny.
W ka»dym ruchu przesuwamy si¦ o jedno pole:
albo w prawo na wprost albo w prawo na ukos (jak pokazano na rysunku 1). Chcemy
znale¹¢
tras¦ o minimalnej dªugo±ci rozumianej jako suma liczb z pól znajduj¡cych
si¦ na trasie.
Rysunek 1: Mo»liwe kierunki ruchu w tablicy
a.
Jak ªatwo sprawdzi¢ liczba wszystkich prawidªowych tras jest wykªadnicza, wi¦c rozwi¡zanie siªowe
nie wchodzi w rachub¦.
2
Rozwa»my najpierw nieco prostsze zadanie, polegaj¡ce na znalezieniu dªugo±ci optymalnej trasy.
Potem poka»emy w jaki sposób zorganizowa¢ obliczenia, by wyznaczenie samej trasy byªo proste.
di,k oznacza minimaln¡ dªugo±¢ trasy wiod¡cej od dowolnego pola pierwszej kolumny do pola
P (i, k) - problem wyznaczenia di,k . Rozwi¡zanie P (i, k) (dla k > 1) mo»na ªatwo otrzyma¢ z
rozwi¡za« trzech prostszych podproblemów, a mianowicie P (i − 1, k − 1) , P (i, k − 1) i P (i + 1, k − 1)
(w przypadku P (1, k) i P (n, k) - dwóch podproblemów). Problem speªnia wi¦c wymagane kryterium
Niech
ai,k ,
a
optymalno±ci.
Je±li za rozmiar
P (i, k)
k −1.
problemów rozmiaru
przyjmiemy warto±¢
k,
to problem rozmiaru
k
redukujemy do trzech pod-
To zbyt skromna redukcja, by stosowa¢ metod¦ dziel i zwyci¦»aj. Z drugiej
strony przestrze« wszystkich podproblemów jest stosunkowo niewielka - skªada si¦ z
(zawiera wszystkie
P (i, j)
dla
i = 1, . . . , n, j = 1, . . . , m),
nm
elementów
mo»emy wi¦c zastosowa¢ programowanie
dynamiczne.
for j = 1 to m do d0,j ← dn+1,j ← ∞
for i = 1 to n do di,1 ← ai,1
for j = 2 to m do
for i = 1 to n do di,j ← ai,j + min{di−1,j−1 , di,j−1 , di+1,j−1 }
return min{di,m | i = 1, . . . , n}
Pozostaje wyja±ni¢, w jaki sposób mo»na odtworzy¢ optymaln¡ tras¦. Niech
i,
dla której osi¡gane jest
trasy.
min{di,m | i = 1, . . . , n},
a wi¦c
ai0 ,m
i0
b¦dzie warto±ci¡
jest ostatnim polem optymalnej
Aby wyznaczy¢ przedostatnie pole wystarczy sprawdzi¢, która z trzech warto±ci
j ∈ {i0 − 1, i0 , i0 + 1})
dj,m−1
(dla
jest minimalna. Post¦puj¡c dalej rekurencyjnie wyznaczymy caª¡ tras¦.
procedure trasa(i, j)
{ if j = 1 then return i
if di−1,j−1 < di,j−1 then k ← i − 1 else k ← i
if dk,j−1 < di+1,j−1 then k ← i + 1
return concat(trasa(k, j − 1), i)
}
..................
write(trasa(i0 , m))
2
Programowanie dynamiczne jest cz¦st¡ metod¡ rozwi¡zywania problemów optymalizacyjnych. Przykªad 2 stanowi ilustracj¦ klasycznego sposobu rozwi¡zania takiego problemu: najpierw znajdujemy
warto±¢ optymalnego rozwi¡zania a dopiero potem, na podstawie wylicze« tej warto±ci, konstruujemy
optymalne rozwi¡zanie.
2
2.1
Dalsze przykªady
Najdªu»szy wspólny podci¡g.
2.1.1 Denicja problemu
Denicja 1 Ci¡g Z = hz1 , z2 , . . . , zk i jest podci¡giem ci¡gu X = hx1 , x2 , . . . , xn i, je±li istnieje ±ci±le
rosn¡cy ci¡g indeksów
hi1 , i2 , . . . , ik i (1 ≤ ij ≤ n)
taki, »e
∀j=1,2,...k xij = zj .
3
Je±li
Z
ci¡gów
jest podci¡giem zarówno ci¡gu
X
X
jak i ci¡gu
Y,
to mówimy, »e
Z
jest wspólnym podci¡giem
Y.
i
Konwencja: Dla wygody, w dalszej cz¦±ci ci¡gi b¦dziemy traktowa¢ jako napisy nad ustalonym al-
fabetem.
Przykªad:
'BABA' jest wspólnym podci¡giem ci¡gów 'ABRACADABRA' i 'RABARBAR', ale nie jest ich najdªu»szym wspólnym podci¡giem (dªu»szym jest np. 'RAAAR').
2
Oznaczenia:
• LCS(X, Y ) = {Z | Z
•
przez
Xi
jest wspólnym podci¡giem
oznaczamy i-literowy preks ci¡gu
szczególno±ci przez
X0
X
i
o maksymalnej dªugo±ci}
Y
X = hx1 , x2 , . . . , xn i,
tj. podci¡g
hx1 , x2 , . . . , xi i;
w
oznaczamy ci¡g pusty.
Problem:
X = hx1 , x2 , . . . , xm i i Y = hy1 , y2 , . . . , yn i
Z z LCS(X, Y )
Dane:
ci¡gi
Wynik:
dowolny ci¡g
2.1.2 Redukcja problemu
Problem znalezienia ci¡gu
Z z LCS(X, Y ) mo»emy zredukowa¢ do prostszych problemów na podstawie
nast¦puj¡cej obserwacji:
•
ka»dego ci¡gu z
•
X i ostatnia litera Y
LCS(X, Y ).
je±li ostatnia litera
X
je±li
i
Y
s¡ takie same, to litera ta musi by¢ ostatnim elementem
ró»ni¡ si¦ na ostatniej pozycji (tj,
na ostatniej pozycji ma liter¦ ró»n¡ od
pozycji ma liter¦ ró»n¡ od
xm
xm 6= yn ),
LCS(X, Y ),
LCS(X, Y ),
który
który na ostatniej
yn .
W pierwszym przypadku problem znalezienia ci¡gu z
LCS(Xm−1 , Yn−1 ).
znalezienia ci¡gu z
to istnieje ci¡g w
lub istnieje ci¡g w
LCS(Xm , Yn )
redukujemy do podproblemu
Rozwi¡zaniem b¦dzie konkatenacja znalezionego ci¡gu i ostat-
X -a. W drugim przypadku problem redukujemy do dwóch podproblemów: znalezienie
LCS(Xm−1 , Yn ) i znalezienie ci¡gu z LCS(Xm , Yn−1 ). W tym przypadku rozwi¡zaniem b¦-
niej litery
ci¡gu z
dzie dªu»szy ze znalezionych ci¡gów.
2.1.3 Algorytm
Najpierw koncentrujemy si¦ na obliczeniu warto±ci rozwi¡zania optymalnego, któr¡ w tym przypadku
jest dªugo±¢ elementów z
LCS(X, Y ).
Sposobu na obliczenie tej warto±ci dostarcza nam obserwacja
poczyniona w poprzednim paragrae.
Fakt 1
Niech
di,j
oznacza dªugo±¢ elementów z
di,j
LCS(Xi , Yj ).

 0
1 + di−1,j−1
=

max(di,j−1 , di−1,j )
je±li
je±li
je±li
Wówczas:
i = 0 lub j = 0,
i, j > 0 i xi = yj ,
i, j > 0 i xi 6= yj
2
Tablic¦
d
mo»emy oblicza¢ kolejno wierszami (lub kolumnami), a wynik odczytamy z
4
dm,n .
Procedure LCS(Xm , Yn )
for i ← 1 to m do di,0 ← 0
for j ← 0 to n do d0,j ← 0
for i ← 1 to m do
for j ← 1 to n do
if xi = yj then di,j ← 1 + di−1,j−1
else di,j ← max{di−1,j , di,j−1 }
Aby wypisa¢ jaki± element z
LCS
musimy przej±¢ tablic¦
d
jeszcze raz, pocz¡wszy od elementu
dn,m ,
w podobny sposób jak to robili±my w Przykªadzie 2.
Je±li zale»y nam na szybko±ci algorytmu, mo»emy nieco przyspieszy¢ t¦ jego faz¦. W tym celu, w
trakcie obliczania tablicy
d,
gólnych elementów tablicy
mo»emy w dodatkowej tablicy zapami¦tywa¢ drog¦ doj±cia do poszcze-
d.
Elementy dodatkowej tablicy przyjmowaªyby jedn¡ z trzech ró»nych
warto±ci, w zale»no±ci od tego czy
di−1,j ,
di,j
powstaª przez dodanie
czy te» wreszcie przez przepisanie
1
do
di−1,j−1 ,
czy przez przepisanie
di,j−1 .
2.1.4 Koszt algorytmu
d odbywa si¦ w czasie staªym. Tak wi¦c caªkowity
Θ(n · m). Koszt skonstruowania najdªu»szego podci¡gu na
Obliczenie ka»dego elementu tablicy
koszt wy-
d
podstawie
peªnienia tablicy
tablicy
2.2
d
jest równy
jest liniowy.
Wyznaczanie optymalnej kolejno±ci mno»enia macierzy.
2.2.1 Denicja problemu
Mamy obliczy¢ warto±¢ wyra»enia
M postaci M1 ×M2 ×· · ·×Mn , gdzie Mi s¡ macierzami. Zakªadamy,
Mi jest równa liczbie wierszy macierzy Mi+1
»e wyra»enie jest poprawne, tj. liczba kolumn macierzy
(dla
i = 1, . . . , n − 1).
Poniewa» mno»enie macierzy jest dziaªaniem ª¡cznym, warto±¢
M
mo»emy liczy¢ na wiele sposo-
bów. Wybór sposobu mo»e w istotny sposób wpªyn¡¢ na liczb¦ operacji skalarnych jakie wykonamy
podczas oblicze«.
Przykªad Niech macierze
M1 , M2 , M3
maj¡ wymiary odpowiednio
d × 1, 1 × d i d × 1.
Rozwa»my
dwa sposoby obliczenia ich iloczynu:
• (M1 × M2 ) × M3
W wyniku pierwszego mno»enia otrzymujemy macierz
d × d, wi¦c jego koszt (niezale»nie od
d2 . W drugim mno»eniu tak»e musimy
przyj¦tej metody mno»enia macierzy) wynosi co najmniej
wykona¢
Θ(d2 )
operacji.
• M1 × (M2 × M3 )
Koszt obliczenia M2 × M3
wynosi
O(d). W
O(d).
jego wyniku otrzymujemy macierz
1 × 1,
wi¦c koszt
nast¦pnego mno»enia wynosi tak»e
1
Dalsze rozwa»ania b¦dziemy przeprowadza¢ przy nast¦puj¡cym zaªo»eniu :
Koszt pomno»enia macierzy o wymiarach a × b i b × c wynosi abc.
1 Jest
to koszt mno»enia wykonanego metod¡ tradycyjn¡; pó¹niej poznamy inne, szybsze metody.
5
2
Problem:
Dane:
d0 , d1 , . . . , dn
- liczby naturalne
di−1 × di
Interpretacja:
Zadanie:
Mi .
- wymiar macierzy
Wyznaczy¢ kolejno±¢ mno»enia macierzy
M1 × M2 × · · · × Mn ,
przy której koszt
obliczenia tego iloczynu jest minimalny.
2.2.2 Rozwi¡zanie siªowe
Rozwi¡zanie siªowe, polegaj¡ce na sprawdzeniu wszystkich mo»liwych sposobów wykonania oblicze«,
jest nieakceptowalne. Liczba tych sposobów dana jest wzorem
S(n) =
1
Pn−1
i=1
Uzasadnienie wzoru: Ka»de z
n−1
je±li
S(i)S(n − i)
je±li
mno»e« wyst¦puj¡cych w ci¡gu
n=1
n>1
M1 × . . . × Mn ,
mo»e by¢ ostatnim,
jakie wykonamy obliczaj¡c ten iloczyn. Liczba sposobów mno»enia macierzy, w których i-te mno»enie jest
ostatnim, jest równa iloczynowi
(tj. liczby sposobów, na które mo»na pomno»y¢
S(i) · S(n − i)
macierzy oraz liczby sposobów, na które mo»na pomno»y¢
Rozwi¡zaniem powy»szego równania jest
n−i
S(n) ="n−ta
i
pierwszych
ostatnich macierzy).
liczba Catalana"=
! n−2
1 2
n n−1
n
= Ω( 4n2 ).
Tak
wi¦c koszt sprawdzania wszystkich mo»liwych iloczynów jest wykªadniczy.
2.2.3 Rozwi¡zanie dynamiczne
k -te mno»enie jest ostatnim
M1 × . . . × Mk oraz Mk+1 × . . . × Mn
Zauwa»amy, »e problem speªnia kryterium optymalno±ci. Je±li bowiem
jakie wykonamy w optymalnym sposobie oblicze«, to iloczyny
te» musiaªy by¢ obliczone w optymalny sposób.
Na podstawie tej wªasno±ci mo»emy uªo»y¢ nast¦puj¡cy algorytm rekurencyjny wyznaczaj¡cy optymalny koszt oblicze«.
function matmult(i, j)
if i = j then return 0
opt ← ∞
k←i
j−1
opt ← min(opt, dj−1 dk dj + matmult(i, k) + matmult(k + 1, j))
opt
for
to
do
return
n
)).
(i, j).
Algorytm ten, jakkolwiek szybszy od metody siªowej, nadal dziaªa w czasie wykªadniczym (Θ(3
Przyczyna tkwi w wielokrotnym wykonywaniu oblicze« dla tych samych warto±ci parametrów
Unikniemy tego mankamentu stosuj¡c programowanie dynamiczne. Niech
mi,j =
minimalny koszt obliczenia
Dla wygody przyjmujemy, »e
mi,j = 0
(dla
i ≥ j ).
Mi × Mi+1 × · · · × Mj ”
Wówczas
mi,j = min (mi,k + mk+1,j + di−1 dk dj ).
i≤k<j
Skªadnik mi,k jest kosztem obliczenia Mi × Mi+1 × · · · × Mk , skªadnik mk+1,j - kosztem obliczenia
Mk+1 × Mk+2 × · · · × Mj , natomiast di−1 dk dj to koszt obliczenia iloczynu dwóch powstaªych macierzy.
6
procedure dyn − matmult(d[0..n]);
intm[1..n, 1..n], p[1..n, 1..n]
for i ← 1 to n do mii ← 0;
for s ← 1 to n − 1 do
for i ← 1 to n − s do
j ←i+s
mij ← mini≤k<j (mi,k + mk+1,j + di−1 dk dj )
pij ← "to k, przy którym osi¡gane byªo minimum dla mij "
p[1..n, 1..n]
return
Algorytm oblicza warto±ci
mi,i+s
(na podstawie powy»szego wzoru) oraz warto±ci
pi,i+s ,
które
umo»liwiaj¡ pó¹niejsze skonstruowanie rozwi¡zania.
Koszt algorytmu.
Tablic¦
mi,j
Koszt policzenia jednego elementu
znajduje si¦
n−s
liczymy przek¡tna za przek¡tn¡ pocz¡wszy od gªównej przek¡tnej.
mi,i+l na s-tej przek¡tnej wynosi Θ(s).
Poniewa» na
s-tej przek¡tnej
elementów, koszt algorytmu wynosi
T (n) =
n−1
X
Θ(s) · (n − s) = Θ(n3 ).
s=0
Odtworzenie rozwi¡zania
stawie tablicy
p.
Odtworzenia rozwi¡zania dokonujemy w standardowy sposób na pod-
Zwró¢ uwag¦, »e znalezienie rozwi¡zania na podstawie samych tylko warto±ci
wymagaªoby czasu
Θ(n2 ).
7
mij