Algdat - øvingsforelesning Dynamisk programmering Nils Barlaug
Dagens plan 1. 2. 3. 4. Praktisk og dagens plan LF øving 8 a. Teori b. Praksis Dynamisk programmering a. Introduksjon b. Rod Cutting c. Matrise-multiplikasjon d. LIS e. LCS Tips til øving 10 Det blir Kahoot!, så følg med og ha klar en enhet du kan delta med! For presentasjoner med mer tekst og forklaringer se tidligere års utmerkede presentasjoner
Teori 8 - Floyd Warshall
Praksis 8 - Mumien
Dynamisk Programmering - motivasjon Fibonacci-tall 0 1 1 2 3 5 8 13 21 34...
Fibonacci def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) La oss prøve å kjøre den på noen n er! Det er jo kjempetregt! po s k E ell i t n ne! d i t e kjør fib(5)
Forbedre Fibonacci Vi må utnytte de overlappende delproblemene 3 i <! d et r ø j k r æ e n i L La oss prøvekjøre vidunderet! fib(5)
Enda bedre? 0 1 1 2 3 5 8 13 Også lineær kjøretid <3 La oss prøvekjøre denne
Dynamisk programmering Naiv (dum) løsning: Lett, men eksponentiell tid Memoisering Lineær tid Bottom up Lineær tid Problemer som består av delproblemer Delproblemene overlapper (brukes flere ganger) Som regel er vi interessert i optimaliseringsproblemer La oss se på et
Rod Cutting 9 + 10 + 1 = 20 Optimal substruktur 1 $1 2 $5 3 $8 4 $9 5 $10 6 $17 7 $17 8 $20 9 $24 10 $30
Rod Cutting rn: maks avkastning for stang av lengde n pn: prisen for en stang av lengde n rn = max(pn, r1+rn-1, r2+rn-2,, rn-2+r2, rn-1+r1) 1 $1 2 $5 3 $8 4 $9 5 $10 6 $17 7 $17 8 $20 9 $24 10 $30
Rod Cutting 1 $1 2 $5 3 $8 4 $9 5 $10 6 $17 7 $17 Eksponentiell kjøretid :-( 8 $20 Men vi kan memoisere :-) 9 $24 Hva blir kjøretiden da? 10 $30 rn: maks avkastning for stang av lengde n pn: prisen for en stang av lengde n CUT-ROD(p,n) if n == 0 return 0 q = - for i = 1 to n q = max(q, p[i] + CUT-ROD(p, n-i)) return q
Rod Cutting rn: maks avkastning for stang av lengde n pn: prisen for en stang av lengde n Hva hvis vi skal bygge løsningen nedenfra og opp? La oss prøve å gjøre det 1 $1 2 $5 3 $8 4 $9 5 $10 6 $17 7 $17 8 $20 i 0 1 2 3 4 5 6 7 8 9 10 9 $24 r[i] 0 1 5 8 10 13 17 18 22 25 30 10 $30
Rod Cutting 1 $1 2 $5 3 $8 4 $9 5 $10 6 $17 Hva blir kjøretiden? 7 $17 Θ(n2) Akkurat som memoisering 8 $20 9 $24 10 $30 rn: maks avkastning for stang av lengde n pn: prisen for en stang av lengde n BOTTOM-UP-CUT-ROD(p, n) let r[0..n] be a new array r[0] = 0 for j = 1 to n q = - for i = 1 to j q = max(q, p[i] + r[j - i]) r[j] = q return r[n]
Hva skjedde nå? Delproblem-grafen Problemet vårt hadde optimal substruktur Problemet hadde overlappende delproblemer Vi sørget for å løse et delproblem kun én gang, og effektivt byttet lagringsplass mot bedre kjøretid Vi behandlet problemene i omvendt topologisk rekkefølge
Abstraksjon Vi må ha: Optimal substruktur Overlappende delproblemer
DP-algoritmer dere kjenner fra før DAG Shortest Path Floyd-Warshall Bellman-Ford
Obs! For å ha optimal delstruktur må delproblemene være uavhengige! Lengste enkle sti q r t For å ha optimal delstruktur må q r og r t være lengste stier også Det er de ikke! Delproblemene er ikke uavhengige
Så hvordan går vi fram? 1. 2. 3. 4. Beskriv/karakteriser strukturen til en optimal løsning (definer problem-parametere og finn delproblem-dag en) Definer rekursivt verdien til en optimal løsning Regn ut verdien til en optimal løsning (og husk valgene du gjør) Bygg opp en optimal løsning basert på beregnet informasjon
Kahoot!
Matrise-multiplikasjon A1A2...An-1An Å multiplisere en a*b-matrise med en b*c-matrise krever a*b*c antall multiplikasjoner. Ai er en pi-1*pi-matrise. Hvordan kan vi sette parenteser på uttrykket slik at vi ender opp med færrest mulig multiplikasjoner totalt? Det blir for mye å sjekke alle muligheter!
Matrise-multiplikasjon - strukturen Hvilke delproblemer skal vi velge? La Ai..j være AiAi+1...Aj. Delproblemet er hvordan vi skal sette parenteser på Ai..j. Når du har en sekvens Ai..j må du velge en k for å splitte opp parenteser slik at du får: (Ai..k)(Ak+1..j) Da har vi delt opp delproblemet i to subdelproblemer av samme type! For å få den optimale oppdelingen av Ai..j må vi dele opp subproblemene optimalt også. Hvorfor det? Cut and paste. Houston, vi har et problem med optimal substruktur! Har vi overlappende delproblemer også? Ja :-)
Matrise-multiplikasjon - rekursiv definisjon La m[i, j] være multiplikasjonskostnaden for Ai..j.
Matrise-multiplikasjon - finne en optimal verdi
Matrise-multiplikasjon matrise A1 A2 A3 A4 dimensjon 30 x 35 35 x 15 15 x 5 5 x 10 A5 10 x 20 En optimal løsning: (A1(A2A3))((A4A5)A6) Kjøretid? O(n3) A6 20 x 25
Lengste stigende subsekvens Eksempel: Si 1 2 9 3 8 5 7 i 1 2 3 4 5 6 7 Prøve alle muligheter blir eksponentielt Struktur: La Li være lengste stigende subsekvens av S0..i som slutter på Si Substrukturen er optimal
Kjøretid? Θ(n2) Lengste stigende subsekvens Eksempel: Si 1 2 9 3 8 5 7 i 1 2 3 4 5 6 7 La l[i] være lengden på lengste subsekvens av S0..i som slutter på Si. Rekursiv definisjon: La oss prøve å finne verdi på en optimal løsning og bygge opp en optimal løsning på tavla
Lengste felles subsekvens (LCS)
Lengste felles subsekvens (LCS) 1. xm = y n Zk-1 er en LCS av Xm-1 og Yn-1 zk xm Zk er en LCS av Xm-1 og Yn zk yn Zk er en LCS av Xm og Yn-1 zk = xm = yn 2. xm y n To sekvenser X = x1x2...xm Y = y1y2...yn La Z = z1z2...zk være en LCS Xi = x1x2...xi, Yi = y1y2...yi, Zi = z1z2...zi
Lengste felles subsekvens (LCS) Hvordan kan vi bygge opp løsningen? La oss prøve X = ABCBDAB Y = BDCABA To sekvenser X = x1x2...xm Y = y1y2...yn La Z = z1z2...zk være en LCS Xi = x1x2...xi, Yi = y1y2...yi, Zi = z1z2...zi
Lengste felles subsekvens (LCS) To sekvenser X = x1x2...xm Y = y1y2...yn Kjøretid? Θ(nm) La Z = z1z2...zk være en LCS Xi = x1x2...xi, Yi = y1y2...yi, Zi = z1z2...zi
Kahoot!
Eksempel: Praksisøving 10 - MsAlgoFan på ferie from sys import stdin, maxint def korteste_rute(rekkefolge, nabomatrise, byer): # SKRIV DIN KODE HER testcases = int(stdin.readline()) for test in range(testcases): byer = int(stdin.readline()) rekkefolge = [int(by) for by in stdin.readline().split()] nabomatrise = [] for by in range(byer): # SKRIV DIN KODE HER print korteste_rute(rekkefolge, nabomatrise, byer) Input: 2 3 021 012 101 130 2 01 0-1 10 Output: 5 umulig Første testcase byer = 3 rekkefolge = [0, 2, 1] Andre testcase byer = 2 rekkefolge = [0, 1] nabomatrise må du lese inn selv!
Spørsmål?