260 likes | 435 Views
Dinamikus programozás. Problémamegoldási megközelítés – (rossz fordítás) Oszd meg és uralkodj: független részproblémák Dinamikus programozás esetén nem függetlenek. (Az Oszd meg és uralkodj feleslegesen többet dolgozna)
E N D
Dinamikus programozás • Problémamegoldási megközelítés – (rossz fordítás) • Oszd meg és uralkodj: független részproblémák • Dinamikus programozás esetén nem függetlenek. (Az Oszd meg és uralkodj feleslegesen többet dolgozna) • Jellemzése:1. Vázoljuk az optimális megoldás szerkezetét2. Adjunk rekurzív definíciót az értékére3. Alulról-felfelé (bottom-up) kiszámítjuk a részproblémák optimális megoldásait4. Ezeket kombinálva kiszámítjuk az egész probléma optimális megoldását
Dinamikus programozási példa: Mátrixsorozat összeszorzása • M1 M2…Mn – a mátrixszorzás asszociatív, de nem kommutatív. Viszont nem egyformán hatékony a zárójelezéselétezik optimális zárójelezés • iMj1jMk2…lMmniMm – a szorzótényezők sor-oszlop kompatibilisek kell, hogy legyenek • iMj1jMk2 időigénye: i*j*k. Például… • (10x100 * 100x5) * 5x50 5000 + 2500 Viszont... • 10x100 * (100x5 * 5x50) 25000+50000
Mátrixszorzás • Melyik az oszlop és melyik a sor? • Közös dimenziójú oszlop- ill. sorpárok elemeit összeszorozzuk és összeadjuk. Az eredmény: sorok száma az elsőből, oszlopok száma a másodikból • Mátrixszorzat(A,B)if oszlop(A)<>sor(B) then errorelse for i=1 to sor(A) do for j=1 to oszlop(B) do C[i,j]=0 for k=1 to oszlop(A) do C[i,j]=C[i,j]+A[i,k]*B[k,j]return C
Szorzások számának becslése az összes lehetőség végigvizsgálásával? • Exponenciális algoritmus!! • Egyetlen újabb mátrixtényező hozzávétele a lehetőségek számát legalább megkétszerezi (bár nem lenne muszáj mindent újra kiszámítani) • iMj1jMk2…lMmnPn, akkor Pn+1>Pn*2 • P(1)=1;P(n)= k=0Σn-1 P(k) *P(n-k), ha n>=2 • Észrevétel: (M1M2…Mk )*(Mk+1…Mn) Ha a teljes szorzat optimális, akkor a részszorzatainak is optimálisnak kell lenni. Hányféle lehetőség van a szorzatszámbecslésre
Rekurzív (naív) megoldás • Legyen m[i,j] az Mi..j szorzatszakasz optimális kiszámításának szorzatszáma. (1<i,j<n) • m[i,i] = 0m[i,j]=mini<=k<j(m[i,k]+m[k+1,j]+ +sor(i)*oszlop(k)*oszlop(j)) • k szerinti ciklusban, az m szerinti rekurzív hívással (FentrőlLefelé-TeljestőlRészekig-TopDown - FeketeLuk megközelítés) exponenciális idő, mert a részfeladatokat esetleg többször is megoldja átfedő részfeladatok
Szorzások számának becslése • Hány részfeladat van összesen? Ahány m[i,j] részoptimum, vagyis ahány 1<=i<=j<=n (i,j) pár,összesen n*(n+1)/2=Θ(n2) • Megoldás: AlulrólFelfelé, a RészektőlEgészig, BottomUp, a részeredmények tárolásával • Algoritmuselemzés: Futásidő: 1 részfeladat kiszámítása egy n hosszú vektor (átló) optimumkeresése. Θ(n3) • Helyigény: Θ(n2) • Filozófia: TopDown vagy BottomUp? – Lebontunk, vagy építkezünk? – Csőlátás vagy halszemoptika? – Holisztika vagy redukcionizmus? Ügyes szakbarbárok, vagy haszontalan próféták?
M1(30x35)*M2(35x15)*M3(15x5)*M4(5x10)*M5(10x20)*M6(20x25) Példa i 1 i 1 6 10500 6 3500 0 3 3 3 5 5 5000 15125 5375 11875 0 3 3 3 4 7125 2500 1000 j 3 750 0 3 3 9375 4375 7875 0 2 j 2625 1 m[i,j]: az Mi..j optimális szorzásszám 15750 0 2 1 s[i,j]: i és j között hol kellett zárójelezni 1 0 Pl. az m[2,5] = min {m[2,2]+m[3,5]+35*15*20=13000--- m[2,3]+m[4,5]+35*5*20=7125--- m[2,4]+m[5,5]+35*10*20=11375} = 7125
Mátrixok száma Főátló kinullázása Átlósan haladunk, l a kezdő j index • MSzorzásSorrend(n)for i=1 to n do m[i,i]=0for l=2 to n do for i=1 to n-l+1 do j=i+l-1 m(i,j)= ∞ for k=i to j-1 do Szorz=m[i,k]+m[k+1,j]+ sor(i)*oszlop(k)*oszlop(j) if Szorz<m[i,j] then m[i,j]=Szorz s[i,j]=kreturn m, s k töréspont (i<=k<j)
Mátrixok vektora Az optimális megoldás A M…Sorrend algoritmus által elkészített „elvágási” mátrix • MátrixLáncSzorzat(M,i,j)if j>i then X=MátrixLáncSzorzat(M,i,s[i,j]) Y=MátrixLáncSzorzat(M,s[i,j]+1,j) return(Mátrixszorzat(X,Y))else return M[i] • A helyes zárójelezés: • (M1 * (M2 * M3)) * ((M4 * M5) * M6)
Hol alkalmazható egyáltalán? • Optimalizálási probléma • Optimális részstruktúrák • Egymást átfedő részfeladatok (az Oszd Meg és Uralkodj nem vizsgálja a visszatérő részfeladatokat, hanem újra megoldja őket) 1-4 1-1 2-4 1-2 3-4 1-3 4-4 2-2 3-4 2-3 4-4 1-1 2-2 3-3 4-4 1-1 2-3 1-2 3-3 3-3 4-4 2-2 3-3 2-2 3-3 1-1 2-2 Egy alternatív megoldás!! Rekurzív, felülről lefelé (naív) megoldás a részeredmények mátrixba történő feljegyzésével
Legrövidebb utak irányított gráfokban • G=(V,E) irányított gráf + w:ER súlyfüggvény. • Egy p=(v0, v1,…, vk) út súlya: w(p)= i=0Σk w(vi ,vi+1 ) • Az u-ból v-be vivő legrövidebb út definíciója: • δ(u,v)=Σmin{w(p),p:uv}, ha létezik p, egyébként ∞ • Figyelem!! δ(u,v) NEM egyértelmű!! • Legrövidebb utak feszítőfájaminimális súlyú feszítőfa • Problématípusok: • Alapprobléma: egy adott sÎV kezdőcsúcsból az összes v csúcsba vivő legrövidebb utak problémája. Következmények: • 1. Adott csúcsba mindenhonnan beérkező legrövidebb utak problémája. (megoldás az élek megfordításával) • 2. Adott csúcspár közötti legrövidebb utak problémája (nem ismert aszimptotikusan gyorsabb megoldás, mint az Alapprobléma) • 3. Összes csúcspár közötti legrövidebb utak problémája (Alapprobléma minden csúcsra – ennél gyorsabb megoldás is létezik)
Negatív súlyú élek • Negatív súlyú élek, ill. negatív összsúlyú körök problematikusak. Ha ilyet tartalmaz egy u-ból v-be vivő út, akkor δ(u,v)=- ∞. Ha v nem elérhető, akkor δ(u,v)=∞ • Algoritmuseredmények: 1. Súly, 2. Út (utak) -4 a b 4 3 6 8 5 d g s c -3 Negatív kör 7 2 3 e f -6
Algoritmusok általános jellemzése • Dijkstra algoritmusa: csak nemnegatív élekre! • Bellman-Ford algoritmus: negatív élekre is működik, megtalálja a negatív köröket is • Bellman-Ford algoritmus használata lineáris programozási feladatokra • Fokozatos közelítés: az egyes csúcsok elérési súlyainak közelítése a felső korlát fokozatos finomítása (csökkentése) útján • Alapelv: az optimális részstruktúrák elve. Egy optimális utakat tartalmazó feszítőfa részei szintén optimális utakat tartalmaznak. • Mohó algoritmusokdinamikus programozás
Dijkstra algoritmusa Elsőbbségi sor, a távolság becslés alapján. Valójában azonban mindig csak a NemBejárt-Bejárt vágatból vesszük a következő csúcsot • Dijkstra(s)for "vÎV do Táv[v]=∞ Szülő[v]=NILTáv[s]=0Bejáratlan=Vwhile Bejáratlan<>{} do u=Bejáratlan.KiveszMin for "vÎSzomszéd(u) do if Táv[v]>Táv[u]+Súly[u,v] then Táv[v]=Táv[u]+Súly[u,v] Szülő[v]=u
A Dijkstra-algoritmus működése 1 u:∞ v:∞ u:10 v:14 u:8 u:8 v:13 v:9 10 2 3 9 6 4 s:0 s:0 5 7 x:5 x:5 x:∞ y:∞ y:7 2 Megjegyzések: 1. Hasonlít a „SzéltébenBejár” és a „Prim” algoritmusra. Különbség elemzése HÁZI FELADAT… 2. Csak pozitív élsúlyokra működik 3. Mohó? Dinamikus? Bottom-up: Top-down?
Optimális feszítőfaLegrövidebb utak b c d 8 7 9 4 2 4 11 14 i e a 7 6 • A fa TELJES súlya minimális, az egyes élekhez vezető utak nem feltétlenül • Minden lépésben a nyitott vágat legkönnyebb élét vesszük hozzá a halmazhoz. Ehhez nem feltétlenül vezet a legrövidebb út. 10 8 h g f 1 2 • Az egyes élekhez vezető utak KÜLÖN-KÜLÖN minimálisak, a fa teljes súlya nem feltétlenül, • Minden lépésben a nyitott vágat legrövidebb úthosszúságú élét vesszük hozzá a halmazhoz, ez nem feltétlenül a legkönnyebb is. b c d 8 7 9 4 2 4 11 14 i e a 7 6 10 8 h g f 1 2
A Dijkstra algoritmus elemzése • 1. A „Bejáratlan” tömb lineáris vektor. KiveszMin O(V), és |V| ilyen művelet van KiveszMin össz. O(V2)A Szomszéd(u) a gráf minden élét 1szer vizsgálja meg. O(V2 +E) • 2. A „Bejáratlan” tömb bináris kupac, KiveszMin ideje O(lgV), és |V| ilyen művelet van. Kupacfelépítés: O(V) KulcsotCsökkent: O(lgV), és legfeljebb |E| ilyen művelet van. össz.O((V+E)lgV) = O(ElgV) • 3. Fibonacci kupacokkal: O(VlogV+E)
A Bellman-Ford algoritmus + elemzése • Negatív súlyú élek is lehetségesek • Negatív körökre HAMIS logikai értéket ad • Futási ideje: O(V*E) • Buborékrendezéshez hasonló működési elv • Negatív körökbe a legkönnyebb út választása miatt bepörög, és a pörgést csak a ciklus vége állítja le • Ha egy csúcs nem elérhető, akkor Táv[u]=∞
A háló lehetséges leghosszabb útja Él kiválasztása valamilyen rendezés szerint (pl. lexikografikus sorrendben) Egy közelítés hatása legrosszabb esetben |V| lépés után teljesen biztosan eljut minden élhez • BellmanFord(s)for "vÎV do Táv[v]=∞ Szülő[v]=NILTáv[s]=0for i=1 to |V|-1 do for "u,vÎE if Táv[v]>Táv[u]+Súly[u,v] then Táv[v]=Táv[u]+Súly[u,v] Szülő[v]=ufor "u,vÎE do if Táv[v]>Táv[u]+Súly[u,v] then return HAMISreturn IGAZ Negatív kör keresése A fokozatos közelítés miatt ilyen feltétel csak akkor alakulhat ki, ha fenti ciklus leállt
A Bellman-Ford algoritmus működése 5 u:6 u:∞ u:2 v:4 v:∞ -2 6 8 -4 -3 7 z:0 7 2 x:∞ x:7 y:∞ y:2 y:-2 9
Legrövidebb utak Irányított Körmentes Gráfokban (KIG) • KIG: A legrövidebb utak jól definiáltak, mert nincs negatív kör • Algoritmus: az éleket a csúcsok topologikus rendezésének sorrendjében tekinti • Nincs ciklus, nincs visszamutató él • Futási idő: Topologikus rendezés: Θ(V+E) – Minden élt egyszer vizsgálunk – Közelítés konstans idő Θ(V+E) • Sejtés: elég lenne csak a kiindulási csúcstól?
KIGLegrövidebbUtak(s)A csúcsok topologikus rendezésefor "vÎV do Táv[v]=∞ Szülő[v]=NILTáv[s]=0for "uÎV - a topologikus rendezés sorrendjében do for "vÎUtód(u) if Táv[v]>Táv[u]+Súly[u,v] then Táv[v]=Táv[u]+Súly[u,v] Szülő[v]=u Közelítés 6 1 5 2 7 -1 -2 r:∞ s:0 s:0 t:∞ t:2 t:2 u:6 u:∞ u:6 v:5 v:5 v:∞ v:6 x:4 x:3 x:3 x:∞ 3 4 2
PERT (Program Evaluation and Review Technique) diagram – kritikus út meghatározása • Munkafolyamat: tevékenységek, mérföldkövek (KIG-ek!) • Gráfélek: tevékenységek, súlyok: időtartamok • uv, vx élek: az uv tevékenységnek meg kell előznie a vx-et • Egy uv út egy tevékenységsorozat, amit csak az adott sorrendben lehet elvégezni • Kritikus út: a KIG-en keresztülvezető leghosszabb út. Ez a teljes munkafolyamat időszükségletére vonatkozó alsó határ.
Ugyanaz az algoritmus, mint a LegrövidebbUtak... …csupán a közelítés az ellenkező feltételt vizsgálja • KIGLeghosszabbUtak(s)A csúcsok topologikus rendezésefor "vÎV do Táv[v]=-∞ Szülő[v]=NILTáv[s]=0for "uÎV a topologikus rendezés sorrendjében do for "vÎUtód(u) if Táv[v]<Táv[u]+Súly[u,v] then Táv[v]=Táv[u]+Súly[u,v] Szülő[v]=u 6 1 5 2 7 1 2 r:-∞ s:0 s:0 t:-∞ t:2 t:2 u:-∞ u:6 u:9 u:9 v:10 v:10 v:6 v:-∞ x:12 x:12 x:-∞ x:4 x:10 4 3 2