11. Dynamické programování III

11 - Dynamické programování III

Připomenutí teorie

Přednáška 11 v oddíle Přednášky.

Optimální vyhledávací strom

Toto je úloha kde máme sestrojit BVS, pro který známe pravděpodobnosti dotazů na jednotlivé klíče. Chceme minimalizovat očekávaný počet operací, kdy nalezení klíče kk v hloubce hkh_k vyžaduje hk+1h_k+1 operací. Pokud je pravděpodobnost dotazu na klíč kk rovna pkp_k, celková cena umístění klíče kk do hloubky hkh_k bude pk(hk+1)p_k(h_k + 1). Minimalizujeme součet přes všech nn klíčů.

Podobně jako při závorkování, optimální strom o nn uzlech lze vidět jako kořen a 2 optimální podstromy v levé a pravé větvi. Toto je naše “optimal substructure”. Když budeme hledat optimální strom o nn uzlech tak, že budeme zkoušet každý z nn uzlů jako kořen, budeme využívat stejné podstromy vícekrát - “overlapping subproblems”. Cenu stromu vypočteme vždy jako součet pravděpodobností výskytu všech uzlů + ceny obou podstromů.

Složitost bude také Θ(n3)\Theta(n^3), výpočet je podobný výpočtu závorkování.

Nejdelší společná podposloupnost

V této úloze máme 2 řetězce A,BA,B délek mm a nn, a hledáme nejdelší podposloupnost (opět ne nutně navazující) která se vyskytuje zároveň v obou řetězcích.

Když známe nejdelší společnou podposloupnost pro kratší řetězce, můžeme toho využít pro optimální řešení pro řetězce se znakem navíc. Celé se to provádí tak, že vyplňujeme 2D pole m×nm \times n, kde na doplňujeme čísla podle předpisu:

l[i,j]={0pokud i=0j=0l[i1,j1]+1pokud i>0j>0A[i]=B[j]max(l[i1,j],l[i,j1])pokud i>0j>0A[i]B[j]l[i, j] = \begin{cases} 0 & \mathrm{pokud} \ i = 0 \lor j = 0 \\ l[i-1, j-1] + 1 & \mathrm{pokud} \ i > 0 \land j > 0 \land A[i] = B[j] \\ \max(l[i-1, j], l[i, j-1])& \mathrm{pokud} \ i > 0 \land j > 0 \land A[i] \ne B[j] \\ \end{cases}

Toto je pak problém s tabelací, podobný těm, co jsme řešili na minulých cvičeních.

Podobný proces je používaný pro výpočet Hammingovy, či Levenshteinovy vzdálenosti dvou řetězců.

Složitost bude Θ(mn)\Theta(m \cdot n), protože vyplňujeme tabulku o dimenzích m×nm \times n.

Úloha batohu (Knapsack)

Problém batohy (knapsack problem) je klasický NP-těžký problém. Máme batoh s kapacitou CC a nn předmětů, kde každý předmět ii má váhu/velikost cic_i a cenu/hodnotu (value) viv_i. Chceme maximalizovat hodnotu předmětů tak, aby předměty které zvolíme nepřeplnily batoh, tedy součet jejich vah byl menší než kapacita CC.

Uvažují se 2 varianty, 0/1 knapsack znamená, že každý předmět máme jen jeden a rozhodujeme zda ho vzít, či nevzít (0/1). Neomezená varianta pak znamená, že každý předmět můžeme vzít kolikrát chceme. Obě varianty řešíme tak, že uvažujeme optimální řešení pro batoh s menší kapacitou a do nich zkoušíme přidat další předměty.

Pro neomezený knapsack si toto lze představit převodem na hledání nejdelší cesty v DAGu s CC uzly a hranami s cenou předmětů mezi každými uzly které reprezentují odpovídající změnu ve zbývající kapacitě. Na obrázku vpravo je sestrojen DAG pro C=10,n=4,v=(9,14,16,30),c=(2,3,4,6)C = 10, n = 4, v = (9, 14, 16, 30), c = (2, 3, 4, 6).

10_knapsack_illustr.png

Pro 0/1 knapsack pak vyplňujeme tabulku kde řádky znamenají přidání konkrétního předmětu a sloupce jsou změny v kapacitě. Do tabulky pak zapisujeme maximální hodnotu kterou můžeme dostat s batohem dané kapacity a s danými předměty.

h(i,j)={0pokud i=0j=0max(h(i1,j),h(i1,jci)+vi)jinakh(i, j) = \begin{cases} 0 & \mathrm{pokud} \ i = 0 \lor j = 0 \\ \max(h(i-1, j), h(i-1, j-c_i) + v_i) & \mathrm{jinak} \end{cases}

Knapsack je tedy převoditelný na problém nejdelší cesty v DAGu či tabelaci, což jsme již řešili na minulých cvičeních.

Řešení neomezeného i 0/1 knapsacku má složitost Θ(Cn)\Theta(C \cdot n), protože vyplňujeme tabulku o dimenzích C×nC \times n, či procházíme DAG s Θ(Cn)\Theta(C \cdot n) hranami.

Řešené úlohy

Optimální vyhledávací strom

Řešená úloha 1: Určete, jak bude vypadat optimální BVS, když jej vybudujeme pro 7 klíčů s frekvencemi:

  • A: 0.10

  • B: 0.10

  • C: 0.25

  • D: 0.35

  • E: 0.10

  • F: 0.05

  • G: 0.05

Řešení

Vyplňujeme od diagonály směrem doprava nahoru. Pro každou buňku projdeme páry existujících hodnot od buňky v řádku zleva a ve sloupci shora, a najdeme minimální hodnotu vypočtenou dle předpisu výpočtu výše.

-

A

B

C

D

E

F

G

A

0

0.10

0.30

0.75

1.45

1.75

1.90

2.10

B

-

0

0.10

0.45

1.15

1.35

1.50

1.70

C

-

-

0

0.25

0.85

1.05

1.20

1.40

D

-

-

-

0

0.35

0.55

0.70

0.90

E

-

-

-

-

0

0.10

0.20

0.35

F

-

-

-

-

-

0

0.05

0.15

G

-

-

-

-

-

-

0

0.05

-

-

-

-

-

-

-

-

0

Diagonála obsahuje nuly, které reprezentují prázdné stromy.

Strom lze rekonstruovat, pokud si zapamatujeme např. který index v řádku jsme využili pro výpočet minimální hodnoty v buňce. To nám zároveň přesně určí i pozici ve sloupci. Když pak konstruujeme (pod)strom, kořen bude vždy klíč na pozici i+1i+1 kde ii je index zapsaný v buňce.

i

1

2

3

4

5

6

7

8

-

A

B

C

D

E

F

G

A

0\color{#6f00ff}0

1

1\color{#9f00ff}1

3\color{#Cf00ff}3

3

3

4

4\color{#ff00ff}4

B

-

0\color{#2f00ff}0

2\color{#6f00ff}2

3

4

4

4

4

C

-

-

0\color{#2f00ff}0

3

4

4

4

4

D

-

-

-

0\color{#9f00ff}0

4

4

4

4

E

-

-

-

-

0\color{#6f00ff}0

5\color{#9f00ff}5

5

6\color{#Cf00ff}6

F

-

-

-

-

-

0\color{#6f00ff}0

6

7

G

-

-

-

-

-

-

0\color{#6f00ff}0

7\color{#9f00ff}7

-

-

-

-

-

-

-

-

0\color{#6f00ff}0

10_03_tree.svg

Nejdelší společná podposloupnost

Řešená úloha 2: Najděte nejdelší společnou podposloupnost dvojice řetězců:

  • 11101001000

  • 00010010111

Řešení

Doplněním tabulky dle předpisu výše:

-

1

1

1

0

1

0

0

1

0

0

0

-

0

0

0

0\color{blue}0

0

0

0

0

1

0

0

0

0

0

0

0

0

1\color{blue}1

1\color{blue}1

1

1

1

1

1

1

0

0

0

0

0

1

1

2\color{blue}2

2

2

2

2

2

0

0

0

0

0

1

1

2

3\color{blue}3

3

3

3

3

1

0

1

1

1

1

2

2

3

4\color{blue}4

4

4

4

0

0

1

1

1

2

2

3

3

4

5\color{blue}5

5

5

0

0

1

1

1

2

2

3

4

4

5

6\color{blue}6

6

1

0

1

2

2

2

3

3

4

5

5

6\color{blue}6

6

0

0

1

2

2

3

3

4

4

5

6

6

7\color{blue}7

1

0

1

2

3

3

4

4

4

5

6

6

7\color{blue}7

1

0

1

2

3

3

4

4

4

5

6

6

7\color{blue}7

1

0

1

2

3

3

4

4

4

5

6

6

7\color{blue}7

Jde o podposloupnost 0001000, což lze vyčíst zpětně z diagonálních přechodů v tabulce výše. (Viz modrá “trasa”)


Úloha batohu (Knapsack)

Řešená úloha 3: Řešte neomezenou variantu úlohy batohu pro kapacitu 10 a tři předměty, jejichž váhy jsou postupně 1, 3, 6 a ceny jsou ve stejném pořadí předmětů 11, 33, 65.

Jaká bude maximální cena předmětů v batohu?

Převodem na DAG

Nalezením nejdelší (dle ohodnocení hran) cesty v tomto DAGu.

10_5_knapsack_dag.png
Tabulkou

Pro každou buňku se zkusím pro každý předmět podívat na hodnotu na indexu nižším o váhu předmětu. K té hodnotě přičtu cenu předmětu a z těchto čísel vyberu maximum a vložím do buňky.

Zaplněná kapacita

0

1

2

3

4

5

6

7

8

9

10

Nejlepší cena

0

11

22

33

44

55

66

77

88

99

110

Index právě přidaného předmětu

0

1

1

2

1

1

2

1

1

2

1

Indexujeme předměty od 1.

Jaké bude řešení pro 0/1 knapsack pro stejné předměty a kapacitu 7?

Řešení

Za každou řádku přidávám jeden předmět. Přičítám k předchozí řádce, s posunem dle váhy předmětu.

Zaplněná kapacita

0

1

2

3

4

5

6

7

Žádný předmět

0

0

0

0

0

0

0

0

Předmět 1

0

11

11

11

11

11

11

11

Předměty 1-2

0

11

11

33

44

44

44

44

Předměty 1-3

0

11

11

33

44

44

65

76

Obsah batohu lze rekonstruovat z tabulky takto:

  1. začneme vpravo dole,

  2. posuneme se doleva dokud bychom nesnížili cenu batohu (hodnotu v buňce) - toto je “volná” kapacita

  3. pokud je v buňce o 1 výš stejné číslo:

    • předmět z řádky nepřidáme a posuneme se o řádek výš do stejného sloupce

    • pokud ne, předmět přidáme a posuneme se o řádek výš, s posunem dle váhy přidaného předmětu

  4. opakujeme proces od bodu 2


Další úlohy

Optimální vyhledávací strom

Úloha 4: Pravděpodobnost dotazu na jednotlivé klíče v obou daných BVS je tato:

A: 0.10 B: 0.20 C: 0.25 D: 0.05 E: 0.10 F: 0.25 G: 0.05

Vypočtěte, který strom je výhodnější pro operaci FIND.


Úloha 5: Určete, jak bude vypadat optimální BVS, když jej vybudujeme pro 7 klíčů s frekvencemi:

E: 0.04 F: 0.05 G: 0.22 H: 0.04 I: 0.06 J: 0.05 K: 0.15


Nejdelší společná podposloupnost

Úloha 6: Najděte nejdelší společnou podposloupnost dvojice řetězců

  • 1100110011001100

  • 1010101010101010


Úloha 7: Najděte nejdelší společnou podposloupnost dvojice řetězců

  • 110100100010000100001000001

  • 001011011101111011110111110 = doplněk


Úloha batohu (Knapsack)

Úloha 8: Řešte 0/1 variantu úlohy batohu pro kapacitu 130 a pět předmětů, jejichž váhy jsou postupně 20, 30, 40, 50, 60 a ceny jsou ve stejném pořadí předmětů 11, 33, 45, 58, 65.

Jaká bude maximální cena předmětů v batohu?

Uvažte, jak se vyhnout tabulce se cca 130 sloupci a upravte postup řešení tak, aby stačilo řádově méně sloupců.


Ostatní úlohy

Úloha 9: Každá zásilka ve skladu má určenou váhu a je nutno všechy zásilky naložit na dvě přistavené dodávky tak, aby se váhy nákladů na obou dodávkách lišily co nejméně.

Zdůvodněte, zda lze či nelze metodu DP pro řešení úlohy batohu využít i v této situaci.


Úloha 10: Kryštof staví malé sportovní lodě. Vyrábí jich několik typů a vždy se věnuje stavbě jen jedné lodě, dokud není hotová. Pro každý typ lodě zná počet dní potřebný ke stavbě lodě a zná svůj zisk z jejího prodeje. Ví, kolik dní bude letos v sezóně věnovat své práci.

Navrhněte metodu dynamického programování, která bude maximalizovat Kryštofův výdělek za letošní sezónu.


Je na stránce chyba?

Nahlašte nám ji

Máte otázky nebo připomínky?

Edit Dejte nám vědět