12.09.2013 Views

Dynamisch Programmeren

Dynamisch Programmeren

Dynamisch Programmeren

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Dynamisch</strong> <strong>Programmeren</strong><br />

extreem ver doorgedreven recursie: om een groot probleem op te<br />

lossen, splitsen we het in kleinere problemen die onafhankelijk van<br />

elkaar opgelost kunnen worden<br />

wanneer we niet precies weten welke kleinere problemen op te lossen,<br />

berekenen we ze allemaal en bewaren de antwoorden voor later gebruik<br />

‘programmeren’ is hier in de betekenis van ‘het proces van beperkingen<br />

formuleren zodanig dat de methode toepasbaar is’<br />

1


soorten problemen:<br />

• het is niet altijd mogelijk om oplossingen voor kleinere problemen<br />

te combineren en tot een oplossing voor een groter probleem te<br />

komen<br />

• het aantal op te lossen kleine problemen kan onaanvaardbaar groot<br />

zijn<br />

2


Knapzak probleem<br />

zoek een combinatie van objecten die in een knapzak passen zodanig<br />

dat de waarde maximaal is<br />

toepassingen: vervoersmaatschappij (laden van vrachtwagen, schip,<br />

vliegtuig, ...)<br />

3


for (j = 1; j


Fig.1 Voorbeeld van een knapzak probleem<br />

5


cost[i] is de hoogste waarde die met knapzak capaciteit i verkregen<br />

kan worden; best[i] is het laatst toegevoegde item om dat maximum<br />

te bekomen<br />

de inhoud van de optimale knapzak kan berekend worden met de best<br />

array<br />

6


Fig.2 Oplossing van het knapzak probleem<br />

7


Eig.1 De tijd nodig voor het oplossen van het knapzak probleem met<br />

dynamisch programmeren is evenredig met NM (N: soorten objecten;<br />

M: grootte van de knapzak).<br />

het probleem is dus eenvoudig op te lossen als M niet groot is<br />

als M of de groottes, waarden van de objecten reële getallen zijn ipv<br />

gehele getallen werkt het niet (fundamenteel probleem)<br />

voordeel: vroeger opgeloste deelproblemen moeten niet opnieuw bekeken<br />

worden;<br />

dynamisch programmeren vindt een optimale oplossing<br />

8


Matrix Chain Product<br />

klassieke toepassing: minimaliseren van de hoeveelheid rekenwerk nodig<br />

om een reeks matrices van verschillende grootte te vermenigvuldigen<br />

de volgorde waarin de matrices vermenigvuldigd worden bepaalt het<br />

aantal bewerkingen<br />

aantal mogelijkheden om N matrices te vermenigvuldigen: Catalaans<br />

getal is ongeveer 4 N−1 /N √ πN<br />

9


⎛<br />

⎜<br />

⎝<br />

a11 a12<br />

a21 a22<br />

a31 a32<br />

a41 a42<br />

⎞<br />

⎟<br />

⎠<br />

b11 b12 b13<br />

b21 b22 b23<br />

⎛<br />

⎝ c11<br />

c21<br />

c31<br />

⎞<br />

⎠ d11 d12<br />

e11 e12<br />

e21 e22<br />

f11 f12 f13<br />

f21 f22 f23<br />

10


de oplossing met dynamisch programmeren is ‘bottom-up’:<br />

er is maar 1 manier om M1 te vermenigvuldigen met M2, en 1 manier<br />

om M2 met M3 te vermenigvuldigen; die kosten worden bewaard<br />

we berekenen ook de manier om opeenvolgende triples te vermenigvuldigen,<br />

gebruik makend van wat al berekend is<br />

11


for (i = 1; i


voor 1 ≤ j ≤ N − 1 vinden we de minimale kost om MiM i+1...M i+j te<br />

berekenen<br />

optimale volgorde, afgeleid uit cost en best:<br />

13


Fig.3 Oplossing van het matrix chain probleem<br />

14


order(int i, int j)<br />

{<br />

if (i == j)<br />

cout >> name(i);<br />

else<br />

{<br />

cout >> ’(’;<br />

order(i, best[i][j]-1);<br />

cout >> ’*’;<br />

order(best[i][j], j);<br />

cout >> ’)’;<br />

}<br />

}<br />

15


Eig.2 <strong>Dynamisch</strong> programmeren lost het ‘matrix chain product’ probleem<br />

op in tijd evenredig met N 3 en met geheugen evenredig met<br />

N 2 .<br />

16


Optimale Binaire Zoekbomen<br />

naar sommige sleutels wordt veel vaker gezocht dan naar andere; het<br />

is best om de vaakst gezochte bovenaan in de zoekboom te plaatsen<br />

aan elke knoop van de binaire boom kennen we een integer toe die<br />

evenredig is met de frequentie van zoeken<br />

17


Fig.4 Optimale binaire zoekboom<br />

18


kost van de boom berekenen door de frequentie van elke knoop te<br />

vermenigvuldigen met de afstand tot de wortel en alles op te tellen<br />

(gewogen interne padlengte)<br />

het verschil met Huffman codering is dat het hier wel belangrijk is om<br />

de volgorde te respecteren; in binaire bomen zijn alle knopen links<br />

van de wortel kleiner enz.<br />

beste manier is voor elke j, toenemend van 1 tot N − 1 om een<br />

deelboom op te bouwen met Ki, K i+1, ...K i+j voor 1 ≤ i ≤ N − j<br />

19


for ( i =1; i


Fig.5 Binaire zoekboom met frequenties<br />

21


Eig.3 De dynamic programming methode om een optimale binaire<br />

boom te vinden gebeurt in tijd evenredig met N 3 en gebruikt ruimte<br />

evenredig met N 2 .<br />

22


Tijd en ruimte<br />

toepassingen van dynamisch programmeren kunnen compleet verschillende<br />

tijd en ruimte nodig hebben afhankelijk van de hoeveelheid informatie<br />

over kleine deelproblemen<br />

voor de knapzak is de benodigde ruimte evenredig met de grootte van<br />

de knapzak; voor andere problemen is N 2 ruimte nodig<br />

23

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!