Grundlagen der Programmierung 2 (1.B)

Werbung
Grundlagen der Programmierung 2
(1.B)
Prof. Dr. Manfred Schmidt-Schauÿ
Künstliche Intelligenz und Softwaretechnologie
26. April 2006
Aufrufhierarchie und Rekursive Definitionen
f, g, fi seien Haskell-definierte Funktionen.
f referenziert g direkt,
f referenziert g (indirekt),
f ist direkt rekursiv,
f ist rekursiv,
Verschränkte Rekursion:
Grundlagen der Programmierung 2 (1.B)
wenn g im Rumpf von f vorkommt.
wenn es Funktionen f1, . . . , fn gibt,
so dass gilt: f referenziert direkt f1,
f1 referenziert direkt f2, . . . ,
fn referenziert direkt g.
wenn f sich selbst direkt referenziert.
wenn f sich selbst (indirekt) referenziert.
wenn f die Funktion g referenziert
und g die Funktion f
auch für allgemeinere Fälle
- 1 -
Beispiel: Aufrufhierarchie
quadrat x
= x*x
quadratsumme x y = (quadrat x) + (quadrat y)
quadratsumme ruft direkt die Funktion quadrat auf,
quadratsumme ruft direkt die (eingebaute) Funktion ∗ auf
Die Funktion quadratsumme ist somit nicht rekursiv
Grundlagen der Programmierung 2 (1.B)
- 2 -
Beispiel: Fakultät
0! := 1
n! := n ∗ (n − 1)!
n! ist die Anzahl aller Permutationen einer n-elementigen Menge.
rekursive Definition:
fakultaet:: Integer -> Integer
fakultaet x = if x <= 0 then 1
else x*(fakultaet (x-1))
Diese Funktion ist rekursiv, da sie im Rumpf sich selbst wieder aufruft.
Grundlagen der Programmierung 2 (1.B)
- 3 -
Entwurf rekursiver Funktionen
Wichtig: zwei Fälle sind zu beachten
der Basisfall:
der Rekursionsfall:
Ergebnis: 0 wenn das Argument x ≤ 1 ist.
Ergebnis: x*(fakultaet (x-1)), wenn x > 1 ist.
Terminierung bei rekursiven Aufrufen :
• Argumente werden mit jedem rekursiven Aufruf kleiner
fakultaet x ruft fakultaet (x-1) auf für x ≥ 1.
• Der Basisfall hat das kleinste Argument
Es funktioniert:
Main> fakultaet 3
6
Main> fakultaet 40
815915283247897734345611269596115894272000000000
Grundlagen der Programmierung 2 (1.B)
- 4 -
Eine falsche Definition
fakultaet_nt:: Integer -> Integer
fakultaet_nt x = if x == 0 then 1
else x*(fakultaet_nt (x-1))
Diese Funktion terminiert nicht bei negativen Eingaben:
fakultaet_nt (-5) ruft fakultaet_nt (-6) auf usw.
Grundlagen der Programmierung 2 (1.B)
- 5 -
Definitionseinsetzung (δ-Reduktion)
Auswerten einer Anwendung von f auf n Argumente:
(f t1 . . . tn) → (Rumpff [t1/x1, . . . tn/xn])
wobei
Die Definition von f ist: f x1 . . . xn = Rumpf f
Grundlagen der Programmierung 2 (1.B)
- 6 -
Definitionseinsetzung
f t1 . . . tn → (Rumpff [t1/x1, . . . tn/xn])
entsteht durch (paralleles bzw. unabhängiges) Ersetzen
von xi durch ti.
ti kann ein Ausdruck sein; es muss kein Basiswert sein!
Grundlagen der Programmierung 2 (1.B)
- 7 -
Arithmetische Auswertungen
v op w → r
wenn:
v, w arithmetische Basiswerte,
op ein zweistelliger arithmetischer Operator,
r Resultat von v op w
op v → r
wenn:
v arithmetischer Basiswert,
op einstelliger arithmetischer Operator,
r Resultat von op v
Beachte: Wenn s op t ausgewertet werden soll,
dann zuerst die Ausdrücke s, t auswerten.
Grundlagen der Programmierung 2 (1.B)
- 8 -
Beispiel:
Programm:
main = quadrat 5
quadrat x = x*x
Auswertung als Folge von Transformationen:
main
→
quadrat 5
→
5 * 5
→
25
Grundlagen der Programmierung 2 (1.B)
- 9 -
Boolesche Auswertungen
v op w
oder
op w
wobei op einer der Operatoren &&, ||, not sein kann.
Wird als Anwendung des Operators auf Argumente ausgewertet.
Definitionen, in der Wirkung äquivalent zu den vordefinierten:
x && y = if x then y
else False
x || y = if x then True else y
not x = if x then False else True
Grundlagen der Programmierung 2 (1.B)
- 10 -
Auswertung der Fallunterscheidung
Fallunterscheidung (if-Reduktion)
(if True then e1 else e2) → e1
(if False then e1 else e2) → e2
Beachte Diese zwei Regeln können nur angewendet werden, wenn der
Bedingungsausdruck zu True oder False ausgewertet ist.
Grundlagen der Programmierung 2 (1.B)
- 11 -
Transformationen, Reduktionen
Wir nennen eine Transformation auch Reduktion
und eine Folge von Programmtransformationen auch Reduktionsfolge
(oder Auswertung).
Beachte: Reduktionen / Transformationen sind zunächst überall im
Ausdruck erlaubt.
Erst eine Auswertungs-Strategie macht die Auswertung eindeutig.
Motivation für diese Transformationssemantik:
• eindeutige Festlegung der Auswertung
• Programmtransformationen,
• Umgang mit nichtterminierenden Argumenten
• Unendliche Listen
Grundlagen der Programmierung 2 (1.B)
- 12 -
Beispiel
x && y = if x then y
x || y = if x then True
bot
= bot
else False
else y
Auswertungen unter der Annahme der obigen Definition
True && True → if True then True else False → True
True && False → if True then False else False → False
True || True → if True then True else True → True
True || False → if True then True else False → True
True && bot → if True then bot else False → bot → bot . . .
True || bot → if True then True else bot → True
Grundlagen der Programmierung 2 (1.B)
- 13 -
Transformationsmöglichkeiten
3 verschiedene Auswertungen für quadrat (4+5) :
1. quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → 9 ∗ (4 + 5) → 9 ∗ 9 → 81
2. quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → (4 + 5) ∗ 9 → 9 ∗ 9 → 81
3. quadrat(4 + 5) → (quadrat 9) → 9 ∗ 9 → 81
Beobachtungen:
•
•
Ergebnis ist gleich
Anzahl der Reduktionen verschieden
Grundlagen der Programmierung 2 (1.B)
- 14 -
Reduktionsstrategien
Zwei wichtige Reduktionsstrategien
Applikative Reihenfolge:
Argumentauswertung vor δ-Reduktion
Normale Reihenfolge:
δ-Reduktion vor Argumentauswertung
Grundlagen der Programmierung 2 (1.B)
- 15 -
Beschreibung: applikative Reihenfolge
werte t0 applikativ aus! Fälle:
•
•
•
•
t0 ist Basiswert. fertig.
t0 ≡ s t,
Wenn s kein Funktionsname und keine Anwendung,
dann applikativ s
t0 ≡ f t1 . . . tn.
Wenn ar(f ) ≤ n, dann applikativ ti, 1 ≤ i ≤ ar(f ) von links nach
rechts.
Wenn ar(f ) ≤ n und alle ti Basiswerte, dann δ-Reduktion.
Wenn n < ar(f ), dann fertig: keine Reduktion.
t0 ≡ if b then e1 else e2.
Wenn b Basiswert, dann if-Reduktion
Wenn b kein Basiswert, dann applikativ b
Grundlagen der Programmierung 2 (1.B)
- 16 -
Beschreibung: normale Reihenfolge
werte t0 in normaler Reihenfolge aus. Fälle:
• t0 ist Basiswert. fertig.
• t0 ≡ s t,
Wenn s kein Funktionsname und keine Anwendung.
Dann normale R. auf s
• t0 ≡ f t1 . . . tn und f keine eingebaute Funktion,
Wenn ar(f ) ≤ n, dann δ-Reduktion auf f t1 . . . tar(f ).
Wenn ar(f ) > n: keine Reduktion.
• t0 ≡ f t1 . . . tn und f ist eingebaute Funktion
Wenn ar(f ) ≤ n und Argumente von f keine Basiswerte,
dann normale R. auf ar(f ) Argumente von links nach rechts.
Wenn ar(f ) ≤ n, und ar(f ) Argumente von f sind Basiswerte,
dann eingebaute Funktion aufrufen.
Wenn ar(f ) > n: keine Reduktion.
• t0 ≡ if b then e1 else e2.
Wenn b Basiswert, dann if-Reduktion
Wenn b kein Basiswert, dann normale R. auf b
Grundlagen der Programmierung 2 (1.B)
- 17 -
Beispiel für verschiedene Reduktionen
3 Auswertungen für
quadrat (4+5) :
1. quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → 9 ∗ (4 + 5) → 9 ∗ 9 → 81
normale Reihenfolge der Auswertung
2. quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → (4 + 5) ∗ 9 → 9 ∗ 9 → 81
3. quadrat(4 + 5) → (quadrat 9) → 9 ∗ 9 → 81
applikative Reihenfolge der Auswertung
Grundlagen der Programmierung 2 (1.B)
- 18 -
Beispiel: Auswertung
main = fakultaet 4
fakultaet x = if x <= 1 then 1
else x*(fakultaet (x-1))
Folge von Transformationen:
(Definitionseinsetzung)
fakultaet 4
if 4 <= 1 then 1 else 4*(fakultaet (4-1))
(Auswertung arithmetische Ungleichung)
if False then 1 else 4*(fakultaet (4-1))
(if-Auswertung)
Grundlagen der Programmierung 2 (1.B)
- 19 -
Beispiel: normale Reihenfolge der Auswertung
(2)
4*(fakultaet (4-1))
(zweites Argument von * wird per Transformation ausgewertet)
4*(if (4-1) <= 1 then 1 else (4-1)*(fakultaet ((4-1)-1)))
4*(if 3 <= 1 then 1 else (4-1)*(fakultaet ((4-1)-1)))
4*(if False then 1 else (4-1)*(fakultaet ((4-1)-1)))
4*((4-1)*(fakultaet ((4-1)-1)))
4*(3*(fakultaet ((4-1)-1)))
4*(3*( if ((4-1)-1) <= 1}
Grundlagen der Programmierung 2 (1.B)
then 1 else ((4-1)*(fakultaet (((4-1)-1)-1))))
- 20 -
Beispiel: normale Reihenfolge der Auswertung
(3)
4*(3*(if (3-1) <= 1 then 1 else ((4-1)-1)*(fakultaet (((4-1)-1)-1))))
4*(3*(if 2 <= 1 then 1 else ((4-1)-1)*(fakultaet ((4-1)-1)-1))))
4*(3*(if False then 1 else ((4-1)-1)*(fakultaet (((4-1)-1)-1))))
4*(3*(((4-1)-1) *(fakultaet (((4-1)-1)-1))))
4*(3*(((3-1) *(fakultaet (((4-1)-1)-1))))
4*(3*(2*(fakultaet (((4-1)-1)-1))))
4*(3*(2*(if
(((4-1)-1)-1) <= 1 then 1
else (((4-1)-1)-1)*(fakultaet (((4-1)-1)-1)-1))))
Grundlagen der Programmierung 2 (1.B)
- 21 -
Beispiel: normale Reihenfolge der Auswertung
(4)
4*(3*(2*( if ((3-1)-1) <= 1 then 1
else (((4-1)-1)-1)*fakultaet ((((4-1)-1)-1)-1)))))
4*(3*(2*( if (2-1) <= 1 then 1
else (((4-1)-1)-1)*fakultaet ((((4-1)-1)-1)-1)))))
4*(3*(2*( if 1 <= 1 then 1
else (((4-1)-1)-1)*fakultaet ((((4-1)-1)-1)-1)))))
4*(3*(2*( if True then 1
else (((4-1)-1)-1)*fakultaet ((((4-1)-1)-1)-1))))
Grundlagen der Programmierung 2 (1.B)
- 22 -
Beispiel: normale Reihenfolge der Auswertung
(5)
4*(3*(2*1) )
4*(3*2)
4*6
24
(24 Auswertungsschritte)
Grundlagen der Programmierung 2 (1.B)
- 23 -
Beispiel: applikative Reihenfolge der Auswertung
fakultaet 4
if 4 <= 1 then 1 else 4*(fakultaet (4-1))
if False then 1 else 4*(fakultaet (4-1))
4*(fakultaet (4-1) )
(wegen applikativer Reihenfolge wird zuerst das Argument von
falkultaet ausgewertet)
4*(fakultaet 3 )
4*(if 3 <= 1 then 1
Grundlagen der Programmierung 2 (1.B)
else 3*(fakultaet (3-1)))
- 24 -
Beispiel: applikative Reihenfolge der Auswertung (2)
4*(if False then 1 else 3*(fakultaet (3-1)))
4*(3*(fakultaet (3-1) ))
4*(3*(fakultaet 2) )
4*(3*(if 2 <= 1 then 1
else 2*(fakultaet (2-1))))
4*(3*(if False then 1 else 2*(fakultaet (2-1))))
4*(3*(2*(fakultaet (2-1) )))
4*(3*(2*(fakultaet 1) )
4*(3*(2*(if 1 <= 1 then 1
Grundlagen der Programmierung 2 (1.B)
else 1*(fakultaet (1-1)))))
- 25 -
Beispiel: applikative Reihenfolge der Auswertung (3)
4*(3*(2*(if True then 1 else 1*(fakultaet (1-1)))))
4*(3*(2*1) )
4*(3*2)
4*6
24
18 Auswertungsschritte
Grundlagen der Programmierung 2 (1.B)
- 26 -
Optimale Anzahl der Reduktionen
Definition verzögerte Reihenfolge der Auswertung (lazy reduction):
•
•
•
normale Reihenfolge
gerichteter Graph statt Text
Vermeidung von unnötiger Doppelauswertung
durch gemeinsame Unterausdrücke (Sharing)
Falls ein Basiswert berechnet wird, gilt für #Reduktionsschritte:
# verzögerte R ≤ # applikative R ≤ # normale R
Es gilt: verzögerte Reduktion hat optimale Anzahl von Reduktionen
Haskell verwendet verzögerte Reduktion
Grundlagen der Programmierung 2 (1.B)
- 27 -
Beispiel
1. 4 Reduktionen: (normale R.)
quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → 9 ∗ (4 + 5) → 9 ∗ 9 → 81
2. 4 Reduktionen:
quadrat(4 + 5) → (4 + 5) ∗ (4 + 5) → (4 + 5) ∗ 9 → 9 ∗ 9 → 81
3. 3 Reduktionen (applikative R.)
quadrat(4 + 5) → (quadrat 9) → 9 ∗ 9 → 81
4. 3 Reduktionen (verzögerte R.)
quadrat(4 + 5) → (4 + 5)(1) ∗ (4 + 5)(1) → 9 ∗ 9 → 81
Grundlagen der Programmierung 2 (1.B)
- 28 -
Verzögerte Auswertung: komplexeres Beispiel
fakultaet x
= if x <= 1 then 1
else x*(fakultaet (x-1))
Die Reduktionsschritte:
fakultaet 4
if 4 <= 1 then 1
else 4*(fakultaet (4-1))
if False then 1 else 4*(fakultaet (4-1))
4*(fakultaet (4-1))
4*(if (4-1) <= 1 then 1
4*(if 3 <= 1 then 1
Grundlagen der Programmierung 2 (1.B)
else (4-1)*(fakultaet ((4-1)-1)))
else 3*(fakultaet (3-1)))
- 29 -
komplexeres Beispiel . . .
4* (if False then 1 else 3*(fakultaet (3-1)))
4*(3*(fakultaet (3-1)))
4*(3*(if (3-1) <= 1 then 1 else (3-1)*(fakultaet ((3-1)-1))))
4*(3*(if 2 <= 1 then 1 else 2*(fakultaet (2-1))))
4*(3*(if False then 1 else 2*(fakultaet (2-1))))
4*(3*(2*(fakultaet (2-1)) ))
4*(3*(2*( if (2-1) <= 1 then 1
Grundlagen der Programmierung 2 (1.B)
else (2-1)*(fakultaet ((2-1)-1)))))
- 30 -
komplexeres Beispiel . . .
4*(3*(2*( if 1 <= 1 then 1 else 1*(fakultaet (1-1)))))
4*(3*(2*(if True then 1 else 1*(fakultaet (1-1)))))
4*(3*(2*1))
4* (3*2)
4*6
24
(18 Auswertungsschritte)
Grundlagen der Programmierung 2 (1.B)
- 31 -
Ein weiterer Vorteil der verzögerten Reduktion
verzögerte Reduktionenen zur Compile-Zeit
sind korrekte Programmtransformationen
d.h. die operationale Semantik bleibt erhalten
Das ist falsch bei applikativer Reihenfolge
Grundlagen der Programmierung 2 (1.B)
- 32 -
Rekursive Auswertungsprozesse in Haskell
Auswertungsprozess, der durch eine rekursive Funktion bewirkt wird
Wir betrachten bei Auswertungsprozessen nur die applikative Reihenfolge
Beispiel: Auswertung der rekursiven Fakultätsfunktion
0! := 1
n! := n ∗ (n − 1)!
fakultaet x
= if x <= 1 then 1
else x*(fakultaet (x-1))
Grundlagen der Programmierung 2 (1.B)
- 33 -
Auswertungsprozess, linear rekursiv
bei applikativer Reihenfolge der Auswertung
(Nicht jeder Zwischenzustand ist angegeben)
(fakultaet 6)
(6 * (fakultaet (6-1)))
(6 * (5 * (fakultaet (5-1))))
(6 * (5 * (4 * (fakultaet (4-1)))))
(6 * (5 * (4 * (3 * (fakultaet (3-1))))))
(6 * (5 * (4 * (3 * (2 * (fakultaet (2-1)))))))
(6 * (5 * (4 * (3 * (2 * 1)))))
(6 * (5 * (4 * (3 * 2))))
(6 * (5 * (4 * 6)))
(6 * (5 * 24))
(6 * 120)
720
Grundlagen der Programmierung 2 (1.B)
- 34 -
Auswertungsprozess, linear rekursiv
(fakultaet 6) Auswertungsprozess ist linear rekursiv
Charakteristisch:
nur eine rekursive Funktionsanwendung
in jedem Ausdruck der Reduktionsfolge
Zwischenausdrücke sind unbeschränkt in der Größe
Grundlagen der Programmierung 2 (1.B)
- 35 -
Alternative Berechnungen der Fakultätsfunktion
Iteriere folgende Regel:
Produkt
Zähler
⇒
⇒
Produkt ∗ Zähler
Zähler + 1
Programm:
fakultaet_iter n =
fakt_iter
1 1 n
fakt_iter produkt zaehler max =
if zaehler > max
then produkt
else fakt_iter (zaehler * produkt)
fakultaet_lin n =
fakt_iter
Grundlagen der Programmierung 2 (1.B)
(zaehler + 1) max
1 1 n
- 36 -
Endrekursion
Eine Endrekursion ist eine lineare Rekursion.
Zusätzlich muss gelten:
alle rekursiven Aufrufe berechnen den Rückgabewert
ohne Nachverarbeitung
Grundlagen der Programmierung 2 (1.B)
- 37 -
Auswertungsprozess, endrekursiv
Auswertung von (fakultaet_iter 5) bei verzögerter Reihenfolge der
Auswertung
(fakultaet_iter 5)
(fakt_iter 1 1 5)
(fakt_iter (1*1) (1+1) 5)
(fakt_iter (2*(1*1)) (2+1) 5)
(fakt_iter (3*(2*(1*1))) (3+1) 5)
(fakt_iter (4*(3*(2*(1*1)))) (4+1) 5)
(fakt_iter (5*(4*(3*(2*(1*1))))) (5+1) 5)
(5*(4*(3*(2*(1*1)))))
120
Das ist eine lineare Rekursion, es ist auch eine Endrekursion
Auswertungsprozess zu fakultaet 6 nicht endrekursiv,
da fakultaet (...) eingebettet in weitere Berechnung.
Grundlagen der Programmierung 2 (1.B)
- 38 -
Iterativer Auswertungsprozess: Fakultät (2)
Iterativer Auswertungsprozess bei applikativer Auswertung:
(fakultaet_iter 6)
(fakt_iter 1 1 6)
(fakt_iter 1 2 6)
(fakt_iter 2 3 6)
(fakt_iter 6 4 6)
(fakt_iter 24 5 6)
(fakt_iter 120 6 6)
(fakt_iter 720 7 6)
720
Iterativer Prozess:
Charakteristisch: Ist eine Endrekursion
Argumente sind Basiswerte
(bzw. Größe des Gesamtausdrucks bleibt beschränkt.)
optimierte Rückgabe des Wertes
Grundlagen der Programmierung 2 (1.B)
- 39 -
Optimierung der Endrekursion
imperative Programmiersprachen
Endrekursion i.a. nicht optimiert.
d.h. Wert wird durch alle Stufen der Rekursion zurückgegeben
Endrekursion ist optimiert
am Ende wird Wert unmittelbar zurückgegeben.
Haskell
Deshalb braucht man in imperativen Programmiersprachen:
Iterationskonstrukte
for ...do,
while,
Grundlagen der Programmierung 2 (1.B)
repeat ...until.
- 40 -
Iteration in Haskell
In Haskell:
Iterative Auswertungsprozesse
sind auch bei verzögerter Auswertung
entsprechende Programmierung ist erforderlich
Naive Implementierung, verzögerte Reihenfolge der Auswertung
tendieren zu:
linear rekursiven, nicht endrekursiven bzw. nicht iterativen Prozessen.
Vergleich: Iterativ gegen linear rekursiv:
Anzahl Auswertungsschritte bleibt i.a. gleich
Größe der Zwischenausdrücke ist kleiner
Grundlagen der Programmierung 2 (1.B)
- 41 -
Baumrekursion
Beispiel Berechnung der Fibonacci-Zahlen
1, 1, 2, 3, 5, 8, 13, 21, . . .
F ib(n) :=


 0
1

 F ib(n − 1) + F ib(n − 2)
falls n = 0
falls n = 1
sonst
fib n = if n <= 0 then 0
else if n == 1 then 1
else fib (n-1) + fib(n-2)
Grundlagen der Programmierung 2 (1.B)
- 42 -
Auswertungsprozess zu fib
in applikativer Reihenfolge:
Der Auswertungs-Prozess ergibt folgende Zwischen-Ausdrücke:
fib 5
fib 4 + fib 3
(fib 3 + fib 2) + fib 3
((fib 2 + fib 1) + fib 2) +
(((fib 1 + fib 0) + fib 1) +
(((1+0) + fib 1) + fib 2) +
((1 + fib 1) + fib 2) + fib
((1+1) + fib 2) + fib 3
(2 + fib 2) + fib 3
(2 + (fib 1 + fib 0)) + fib
.......
Grundlagen der Programmierung 2 (1.B)
fib 3
fib 2)
fib 3
3
+ fib 3
3
- 43 -
Auswertungsprozess zu fib: Baum der Aufrufe
5
4
3
3
2
1
2
1
1
2
0
1
1
0
0
Das ist Baumrekursion
Charakteristisch: Ausdrücke in der Reduktionsfolge
• können unbegrenzt wachsen
• enthalten mehrere rekursive Aufrufe
• Aber: nicht geschachtelt
(d.h. die Argumente eines rekursiven Aufrufs
enthalten keine rekursiven Aufrufe)
Grundlagen der Programmierung 2 (1.B)
- 44 -
Geschachtelte Rekursion
Ist der allgemeine Fall
wird normalerweise selten benötigt,da i.a. nicht effizient berechenbar.
Beispiel: Die Ackermannfunktion
----ack 0
ack 1
ack x
ack x
Ackermanns Funktion
y
=
0
=
0 | x >= 2
=
y | x > 0 && y > 0 =
---1
2
x+2
ack (ack (x-1) y) (y-1)
Vorstellung neuer syntaktischer Möglichkeiten in Haskell:
Auswertung:
von oben nach unten wird probiert, welche Definitionsgleichung passt:
1) Argumente anpassen
2) Bedingung rechts vom | prüfen
Grundlagen der Programmierung 2 (1.B)
- 45 -
Optimierte Ackermannfunktion
----ackopt
ackopt
ackopt
ackopt
ackopt
ackopt
Ackermanns Funktion optimiert ---0 y = 1
1 0 = 2
x 0 = x+2
x 1 = 2*x
x 2 = 2^x
x y | x > 0 && y > 0 = ackopt (ackopt (x-1) y) (y-1)
*Main> logI10 (ackopt 5 3)
19728.301029995662
•
•
•
--(Anzahl DezimalStellen)
-- ( == 2^65536)
sehr schnell wachsende Funktion
man kann nachweisen: ack nicht primitiv rekursiv
hat Anwendung in der Komplexitätstheorie
Grundlagen der Programmierung 2 (1.B)
- 46 -
Tabelle der Rekursionsprozesse:
linear rekursiv
endrekursiv
iterativ
Baumrekursion
geschachtelte
Baumrekursion
maximal ein rekursiver Unterausdruck
linear rekursiv und Gesamtresultat ist Wert des
rekursiven Unterausdrucks
endrekursiv und Argumente des rekursiven Unterausdrucks sind Basiswerte
mehrere rekursive Unterausdrücke; Argument
der rekursiven Unterausdrücke ohne weitere
Rekursion
mehrere rekursive Unterausdrücke auch in den
Argumenten
Grundlagen der Programmierung 2 (1.B)
- 47 -
Optimierung: Iteration statt Rekursion
Beispiel
Berechnung von (fib
fib 3 wird
fib 2 wird
fib 1 wird
5)
2 mal berechnet
3 mal berechnet
5 mal berechnet
Genauer: Bei Berechnung von fib n für n ≥ 2
wird fib(1) jeweils (fib n)-mal berechnet
Φn
fib n ≈ √
Fazit:
5
√
wobei Φ = 1+2 5 ≈ 1.6180
fib(n) wächst exponentiell
# Reduktionen für fib(n) ist exponentiell
d.h. die Laufzeit von fib ist exponentiell
Grundlagen der Programmierung 2 (1.B)
- 48 -
Iterative Version von Fib
Beobachtung: zur Berechnung von fib(n) benötigt man
nur die Werte fib(i) für 1 ≤ i ≤ n.
Idee: Berechnung einer Wertetabelle für fib.
Verbesserte Variante:
aus fib (n − 1) und fib (n − 2) berechne fib(n)
Ohne Doppelberechnung
Rechenvorschrift: (a, b) → (a + b, a)
Grundlagen der Programmierung 2 (1.B)
- 49 -
Iterative Version von fib: Funktionen
fib_lin n
=
fib_iter a b zaehler =
Grundlagen der Programmierung 2 (1.B)
(fib_iter 1 0 n)
if zaehler <= 0
then b
else fib_iter (a + b) a (zaehler - 1)
- 50 -
Prozess für (fib lin 5)
(fib_lin 5)
(fib_iter
(fib_iter
(fib_iter
(fib_iter
(fib_iter
5
1
1
2
3
5
0
1
1
2
3
5)
4)
3)
2)
1)
Grundlagen der Programmierung 2 (1.B)
- 51 -
Analyse der fib-Optimierung
Für (fib_lin n) gilt:
• ist operational äquivalent zu fib
• benötigt linear viele Reduktionen abhängig von n
• Größe der Ausdrücke ist beschränkt
• Platzbedarf ist konstant (d.h. unabhängig) von n.
(unter Vernachlässigung der Darstellungsgröße der Zahlen)
erzeugt Iterativen Auswertungsprozess
Grundlagen der Programmierung 2 (1.B)
- 52 -
Analyse von Programmen
Wir verwenden für Haskell-Programme folgende Messungen.
Bei verzögerter Auswertung
Zeit:
Anzahl der Transformationsschritte
Platz: (Gesamt-Speicher):
Maximale Größe der Ausdrücke
Arbeitsspeicher:
Maximale Größe der Ausdrücke
(ohne die Eingabe)
arithmetische und Boolesche Operationen = 1 Transformationsschritt.
Grundlagen der Programmierung 2 (1.B)
- 53 -
Analyse von Programmen (2)
Angabe des Ressourcenbedarf eines Algorithmus
in Abhängigkeit von der Größe der Eingabe.
Notation für Algorithmus alg bei Eingabe der Größe n:
redalg(n)
maximale Anzahl der Reduktionen bei verzögerter
Auswertung für alle Eingaben der Größe n.
P latzalg(n)
Platzbearf:
maximale Größe der Ausdrücke (des
gerichteten Graphen) bei verzögerter Auswertung für alle
Eingaben der Größe n.
Die Eingaben nicht mitzählen
Grundlagen der Programmierung 2 (1.B)
- 54 -
Beispiel: fib
fib n = if n <= 0 then 0
else if n == 1 then 1
else fib (n-1) + fib(n-2)
redfib(n) ≈ 1.6n (einfach exponentiell)
andere Bezugsgröße: Größe der Darstellung der Zahl n:
size(n) = dlog10(n)e Dezimalstellen.
n
hat
size(n) )
(10
Zeitbedarf: ≈ 1.6
(doppelt exponentiell).
Grundlagen der Programmierung 2 (1.B)
- 55 -
Beispiel fakultaet n
fakultaet
n benötigt 5 ∗ (n − 1) + 3 Reduktionsschritte.
Nachweis mit vollständiger Induktion:
Grundlagen der Programmierung 2 (1.B)
- 56 -
Komplexitäten von Algorithmen
Beachte:
breite Streuung des Ressourcenbedarfs ist möglich für
die Menge aller Eingaben einer bestimmten Größe.
Komplexitäten von Platz und Zeit:
Ressourcenbedarf
im schlimmsten Fall
im besten Fall
im Mittel
Grundlagen der Programmierung 2 (1.B)
(worst-case)
(best-case)
Minimum von # Reduktionen
bzw. Minimum der Größe der Ausdrücke.
(average case)
Welche Verteilung?
- 57 -
Einige Komplexitäten
O(1)
O(log(n))
O(n)
O(n ∗ log(n))
O(n2)
O(n3)
O(nk )
O(2n)
konstant
logarithmisch
linear
fastlinear (oder auch n-log-n)
quadratisch
kubisch
polynomiell
exponentiell
Grundlagen der Programmierung 2 (1.B)
- 58 -
Beispiel fib
fib Bezugsgröße:
n: Eingabe
d: Größe der Darstellung der Zahl n
redfib(n)
platzfib(n)
=
=
O(1.62n)
O(n)
redfib lin(n)
platzfib lin(n)
=
=
O(n)
O(n)
redfib lin(d)
platzfib lin(d)
=
=
O(10d)
O(10d)
Grundlagen der Programmierung 2 (1.B)
- 59 -
Analyse des Algorithmus zum größten gemeinsamen Teiler
ggT(a, b) (Euklids Algorithmus)
Teile a durch b gibt Rest r,
wenn r = 0, dann ggT(a, b) := b
wenn r 6= 0, dann berechne ggT(b, r).
Beispiel ggT(30, 12) = ggT(12, 6) = 6
ggt a b =
if b == 0
then a
else ggt b (rem a b)
Grundlagen der Programmierung 2 (1.B)
- 60 -
Satz von Lamé
Komplexität des Euklidischen Algorithmus
SATZ (Lamé):
benötigt,
Wenn der Euklidische ggt-Algorithmus k Schritte
dann ist die kleinere Zahl der Eingabe ≥ f ib(k).
Platz- und Zeitbedarf von ggt: O(log(n))
Begründung:
Wenn n die kleinere Zahl ist und der Algorithmus k Schritte benötigt,
dann ist n ≥ f ib(k) ≈ 1.6180k
Also ist k = O(log(n))
Grundlagen der Programmierung 2 (1.B)
- 61 -
Listen und Listenfunktionen
Listen modellieren Folgen von gleichartigen, gleichgetypten Objekten.
[0,1,2,3,4,5,6,7,8,9]
Typ: [Integer]; d.h. Liste von Integer.
[]
leere Liste, (Nil)
[’a’, ’b’, ’c’]
Typ: [Char];
abgekürzt als String
Druckbild: "abc"
[[], [0], [1, 2]]
Liste von Listen;
Typ [[Integer]], d.h. eine Liste von Listen von
Integer-Objekten.
[1..]
potentiell unendliche Liste [1,2,3,...]
Grundlagen der Programmierung 2 (1.B)
- 62 -
Listen und Listenfunktionen
zwei Schreibweisen für Listen:
[0, 1, 2]
schöne Darstellung
Druckbild einer Liste
(0 : (1 : (2 : [])))
interne Darstellung mit
zweistelligem Infix-Listen-Konstruktor : “
”
und dem Konstruktor []
Eingebaute, listenerzeugende Funktionen:
[n..]
[n..m]
[1..10]
[n,m..k]
erzeugt die Liste der Zahlen ab n.
erzeugt die Liste von n bis m
ergibt [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
erzeugt die Liste von n bis k mit Schritten m − n
Grundlagen der Programmierung 2 (1.B)
- 63 -
Darstellung von Listen
Listen sind aufgebaut mittels zwei Konstruktoren:
[]
:
Konstante für die leere Liste
Zweistelliger Infix-Konstruktor
Linkes Argument: erstes Element der Liste
Rechtes Argument: Restliste
Beispiel für Haskells Listenerzeugung:
8:[]
9:(8:[])
10:(9:(8:[]))
Liste [8] mit dem Element 8
Liste [9.8] mit zwei Elementen 8,9
Liste [10,9,8] mit drei Elementen
Grundlagen der Programmierung 2 (1.B)
- 64 -
Baum-Bild einer Liste
zz
zz
z
zz
z} z
: @@@
10
@@
@@
@@
9
: <<<
<<
<<
<

8
Grundlagen der Programmierung 2 (1.B)
: ;;;
;;
;;
;
[]
- 65 -
Einfache Listenfunktionen
Definitionen
head (x:xs)
tail (x:xs)
= x
= xs
--Erstes Element
--Restliste
Auswertungen
head []
head [1]
tail []
tail [1]
Grundlagen der Programmierung 2 (1.B)
- 66 -
Beispiel lengthr
lengthr []
= 0
lengthr (x:xs) = 1 + (lengthr xs)
Auswertung
lengthr (10:(9:(8:[])))
1+ (lengthr (9:(8:[])))
1+(1+ (lengthr (8:[])))
1+(1+ (1+ (lengthr [])))
1+(1+ (1+ (0)))
3
Grundlagen der Programmierung 2 (1.B)
Zweiter Fall; [10/x,(9:(8:[]))/xs]
Zweiter Fall; [9/x, (8:[])/xs]
Zweiter Fall; [8/x, ([])/xs]
Erster Fall;
3 × Addition
- 67 -
Herunterladen