Professional Documents
Culture Documents
PROGRAMIRANJE
Dinamičko programiranje
Na prethodnim časovima razmatrali smo vrlo elegantne algoritamske strate-
gije, kao što su podeli-i-savladaj, pretraživanje grafova ili pohlepni algoritmi.
Ove strategije obezbeđuju oruđa za rešavanje čitave lepeze važnih računarskih
problema, ali ipak, mogu se primeniti na vrlo specifične tipove problema.
Dinamičko programiranje i linearno programiranje, o kojima ćemo govo-
riti na narednim časovima, predstavljaju algoritamske tehnike sa vrlo širokim
poljem primene, koje se mogu koristiti onda kada pomenuti specijalizovani
metodi ne daju rezultate.
Međutim, ta opštost dinamičkog i linearnog programiranja je često praćena
smanjenjem efikasnosti (u odnosu na prethodne metode).
Dinamičko programiranje
Inače, kao što ćemo videti, sam termin dinamičko programiranje nema mnogo
zajedničkog sa onim što obično zovemo programiranjem (pisanje koda).
Dinamičko programiranje, kao i sam termin, uveo je 1950tih godina Ričard
Belman (Richard Bellman), u vreme kada se programiranjem u današnjem
smislu bavilo samo nekoliko ljudi i kada još nije postojao poseban termin za to.
Termin „programiranje“ koji se javlja u gornjem nazivu se zapravo može shvati-
ti kao „planiranje“, jer je „dinamičko programiranje“ zamišljeno kao optimalno
planiranje višestepenih procesa (multistage processes).
Sličnu etimologiju ima i termin „linearno programiranje“, o kome će kasnije
biti reči.
Najkraći putevi u DAG-u (još jednom)
Kada smo ranije razmatrali problem najkraćih puteva, istakli smo da je taj
problem posebno lak kada se radi sa usmerenim acikličnim grafovima – DAG-
ovima.
Reći ćemo još par reči o Dag-ovima, jer oni leže u samom srcu dinamičkog
programiranja.
Posebno važno svojstvo DAG-ova je to da mogu biti linearizovani – mogu
biti aranžirani na pravoj tako da sve grane idu isključivo sleva na desno (Fig.
6.1).
Najkraći putevi u DAG-u (još jednom)
Ako računamo vrednosti dist sleva na desno kao na Slici 6.1, onda možemo
uvek biti sigurni da u trenutku kada smo došli do čvora 𝑣 mi već imamo sve
potrebne informacije da bi izračunali 𝑑𝑖𝑠𝑡(𝑣).
Dakle, sve distance možemo izračunati u jednom prolazu
Najkraći putevi u DAG-u (još jednom)
Primetimo da ovaj algoritam rešava kolekciju podproblema {𝑑𝑖𝑠𝑡(𝑢) | 𝑢 ∈ 𝑉}.
Mi krećemo od najmanjeg od njih, 𝑑𝑖𝑠𝑡(𝑠), za koji znamo da će rešenje biti 0.
Onda postepeno prelazimo na „veće“ podprobleme – rastojanja do čvorova
koji su sve dalje i dalje od polaznog, u skladu sa linearizovanim DAG-om.
Zapravo, mi podproblem shvatamo onoliko većim koliko drugih podproblema
treba da rešimo pre no što pređemo na rešavanje tog podproblema.
To je veoma opšta tehnika. Za svaki čvor, izračunavamo neku funkciju koristeći
vrednosti prethodnika tog čvora.
U ovom slučaju ta funkcija je minimum suma, ali može biti i bilo šta drugo –
ako umesto minimuma uzmemo maksimum dobijamo najduže puteve, umesto
da sabiramo težine grana mi ih možemo množiti, i slično.
Definicija dinamičkog programiranja
Dinamičko programiranje je veoma moćna algoritamska strategija kojom se
problemi rešavaju na sledeći način:
▫ identifikuje se kolekcija podproblema glavnog problema
▫ ta kolekcija se linearizuje – podproblemi se rešavaju linearno, počev od
najmanjeg pa do najvećeg podproblema, našeg polaznog problema
▫ identifikuje se formula kojom se svaki podproblem izražava u funkciji
prethodnih, jednostavnijih podproblema
Primetimo sledeće:
1. Graf 𝐺 = (𝑉, 𝐸) je DAG, jer za svaku granu (𝑖, 𝑗) važi da je 𝑖 < 𝑗.
2. Postoji bijektivna korespondencija između rastućih podnizova i puteva u
tom DAG-u
Prema tome, problem nalaženja najdužeg rastućeg podniza je prosto problem
nalaženja najdužeg puta u DAG-u.
Najduži rastući podniz
Evo sada i algoritma:
𝐿(𝑗) je dužina najdužeg puta koji se završava u čvoru 𝑗 plus 1, odnosno dužina
najdužeg rastućeg podniza koji se završava sa 𝑎𝑗 (dodajemo 1 jer brojimo čvo-
rove a ne grane na putu).
Na isti način kao kod najkraćih puteva vidimo da svaki put u čvor 𝑗 mora da
prođe kroz neki od njegovih prethodnika, pa je 𝐿(𝑗) jednako 1 plus maksimum
𝐿(∙) vrednosti prethodnika čvora 𝑗.
Ukoliko nema grana u 𝑗, onda imamo maksimum nad praznim skupom, tj. 0.
Krajnji odgovor je je najveći 𝐿(𝑗), jer je dozvoljena bilo koja završna pozicija.
Opšta šema dinamičkog programiranja
Ovde možemo lepo da uočimo opštu šemu dinamičkog programiranja:
Da bi rešili polazni problem mi smo definisali kolekciju podproblema
𝐿 𝑗 1 ≤ 𝑗 ≤ 𝑛}
sa sledećim ključnim svojstvima:
1. Postoji uređenje podproblema – u ovom slučaju podproblemi su uređeni
po brojevima 𝑗.
2. Postoji relacija koja pokazuje kako rešiti podproblem ako znamo rešenja
manjih podproblema – u ovom slučaju to je relacija
𝐿 𝑗 = 1 + max 𝐿 𝑖 (𝑖, 𝑗) ∈ 𝐸}.
U opštem slučaju, postoji mnogo mogućih poravnanja dveju reči i bilo bi užasno
neefikasno pretraživati sva moguća poravnanja da bi našli najbolje.
𝐸 𝑖, 𝑗 = min{1 + 𝐸 𝑖 − 1, 𝑗 , 1 + 𝐸 𝑖, 𝑗 − 1 , diff 𝑖, 𝑗 + 𝐸 𝑖 − 1, 𝑗 − 1 }
pri čemu je
0 ako je 𝑥 𝑖 = 𝑦[𝑗]
diff 𝑖, 𝑗 = ቊ .
1 ako je 𝑥 𝑖 ≠ 𝑦[𝑗]
𝑖 − 1, 𝑗 → 𝑖, 𝑗 , 𝑖, 𝑗 − 1 → 𝑖, 𝑗 i 𝑖 − 1, 𝑗 − 1 → 𝑖, 𝑗 .
Pri tome, granama ćemo dodati i težine, tako da sve grane budu težine 1, osim
grana oblika 𝑖 − 1, 𝑗 − 1 → 𝑖, 𝑗 za koje je 𝑥 𝑖 = 𝑦[𝑗], tj. diff 𝑖, 𝑗 = 0.
U tom slučaju, konačno rešenje našeg problema je rastojanje između čvorova
𝑠 = (0,0) i 𝑡 = (𝑚, 𝑛) u tom DAG-u.
Najkraći putevi između 𝑠 i 𝑡 odgovaraju optimalnim poravnanjima.
Edit distanca
Evo kako izgleda DAG za reči EXPONENTIAL i POLYNOMIAL :
𝐾 𝑤 = max {𝐾 𝑤 − 𝑤𝑖 + 𝑣𝑖 } ,
𝑖:𝑤𝑖 ≤𝑤
𝐾 𝑤, 𝑗 = max 𝐾 𝑤 − 𝑤𝑗 , 𝑗 − 1 + 𝑣𝑗 , 𝐾 𝑤, 𝑗 − 1 .
Kako se nijedan problem nikad neće ponoviti, vreme realizacije je 𝑂(𝑛𝑊), isto
kao kod dinamičkog programiranja. U tom smislu memoizacija ne daje bolje
rezultate od dinamičkog programiranja.
Međutim, ima i slučajeva kada se memoizacija isplati. Naime, dinamičko pro-
gramiranje automatski rešava svaki podproblem koji bi mogao biti potreban,
dok memoizacija rešava samo one koji se zaista koriste.
Na primer, ako su 𝑊 i svi 𝑤𝑖 umnošci broja 100, onda je podproblem 𝐾(𝑤)
beskorisan ako 100 ne deli 𝑤, i memoizirani algoritam nikada neće doći u
situaciju da ga rešava.
Lanačno matrično množenje
Pretpostavimo da treba da pomnožimo četiri matrice 𝐴, 𝐵, 𝐶 i 𝐷.
Zbog asocijativnosti množenja matrica svi proizvodi u kojima se te matrice
javljaju u datom redosledu, čitano sleva na desno, su jednaki
Taj proizvod se obično označava bez zagrada, u obliku 𝐴 × 𝐵 × 𝐶 × 𝐷.
Na primer, ako su dimenzije matrica 50 × 20, 20 × 1, 1 × 10 i 10 × 100, tim
redom, onda je proizvod matrica tipa 50 × 100.
Lanačno matrično množenje
Međutim, bez obzira na to što se uvek dobija isti rezultat, redosled množenja
(raspored zagrada) može da utiče na brzinu izvršenja tog množenja
Množenje matrica tipa 𝑚 × 𝑛 i 𝑛 × 𝑝 zahteva 𝑚𝑛𝑝 množenja, i na sledeći način
možemo uporediti različite načine izračunavanja proizvoda
𝐶 𝑖, 𝑗 = min 𝐶 𝑖, 𝑘 + 𝐶 𝑘 + 1, 𝑗 + 𝑚𝑖−1 ∙ 𝑚𝑘 ∙ 𝑚𝑗
𝑖≤𝑘≤𝑗
Za čvor 𝑣 i 𝑖 ≤ 𝑘 neka je
Ideja je sledeća: najpre ćemo zabraniti sve međučvorove, i u tom slučaju naj-
kraći put između 𝑢 i 𝑣 je prosto grana (𝑢, 𝑣), ako postoji.
𝐶 𝑆, 𝑗 = min 𝐶 𝑆 ∖ 𝑗 , 𝑖 + 𝑑𝑖𝑗
𝑖∈𝑆 ∖ 𝑗
Problem trgovačkog putnika
Podproblemi su uređeni po |𝑆| – broju elemenata skupa 𝑆
Prema tome, potrebne su nam samo dva |𝑉| × |𝑉| niza da smestimo dist vred-
nosti – jedan za neparne vrednosti 𝑘, a drugi za parne vrednosti.