Telecooperation/RBG
Technische Universität Darmstadt
Copyrighted material; for TUD student use only
Grundlagen der Informatik 1Thema 8: Akkumulation von Wissen
Prof. Dr. Max MühlhäuserDr. Guido Rößling
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Rekursive Funktionen
• Die rekursiven Funktionen, die wir bisher gesehen haben, sind kontextfrei– Sie kümmern sich um ihr Subproblem, ohne
etwas von dem Gesamtproblem zu wissen• Vorteil: Solche Funktionen sind einfach zu
entwickeln, einfach wartbar etc.• Nachteil: Manche Funktionen werden dadurch
ineffizient oder kompliziert
2
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Beispiel
• Gegeben: Liste von Punkten mit relativer Distanz zwischen Punkten
• Aufgabe: Absolute Distanzen vom Ursprung berechnen
3
0 50 90 160 190 220
0 50 40 70 30 30
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Lösung mit struktureller Rekursion
4
;; relative-2-absolute : (listof number) -> (listof number);; to convert a list of relative distances to a ;; list of absolute distances; the first item on the list ;; represents the distance to the origin(define (relative-2-absolute alon) (cond [(empty? alon) empty] [else (cons (first alon)
(add-to-each (first alon) (relative-2-absolute (rest alon))))]))
;; add-to-each : number (listof number) -> (listof number);; to add n to each number on alon(define (add-to-each n alon) …)
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Lösung mit struktureller Rekursion
Bevor wir die Nachteile diskutieren, wollen wir kurz unser Wissen über Funktionen höherer Ordnung anwenden
– (add-to-each n alon)-> (map (lambda (m) (+ n m)) alon))
– (relative-2-absolute alon) -> (foldr
(lambda (x xs) (cons x (add-to-each x xs))) empty alon))
• Beachte: die Funktion, die gefaltet wird, ist nicht assoziativ– foldl anstelle von foldr ergibt ein anderes Ergebnis!
– Wie kommt man auf die letzte Gleichung? 5
;; add-to-each : number (listof number) -> (listof number);; to add n to each number in alon(define (add-to-each n alon) (cond [(empty? alon) empty] [else (cons (+ (first alon) n) (add-to-each n (rest alon)))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Zur Erinnerung: foldr
• Wie kann man foldr spezialisieren, um relative-2-absolute zu erhalten?
• f = (lambda (x xs) (cons x (add-to-each x xs)))6
;; foldr : (X Y -> Y) Y (listof X) -> Y ;; (foldr f base (list x-1 ... x-n)) = ;; (f x-1 ... (f x-n base)) (define (foldr f base alox) (cond [(empty? alox) base] [else (f (first alox) (foldr f base (rest alox)))]))
(define (relative-2-absolute alon) (cond [(empty? alon) empty] [else (cons (first alon)
(add-to-each (first alon) (relative-2-absolute (rest alon))))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Zurück zum Thema…• Was ist die Zeitkomplexität von relative-2-absolute in
Abhängigkeit von der Länge der Liste?• Sei T(n) Zeitkomplexität von relative-2-absolute,
sei U(n) Zeitkomplexität von add-to-each• U(n) = 1 + U(n-1) U(n) = n O (n)• T(n) = 1 + T(n-1) + U(n-1)
= 1 + T(n-1) + n-1= n + T(n-1)= n + (n-1) + … + 1= n*(n+1) / 2 = (n2+n)/2 O (n²)
• In der Version mit foldr, map kann man die Zeitkomplexität leicht aus der Zeitkomplexität von foldr, map folgern– foldr f base alox T(n) = n*(n), – wobei n = Länge von alox,– (n) = Zeitkomplexität von f
7
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Was ist das Problem?• Das Problem ist die “Kontextfreiheit” von relative-2-absolute– Der rekursive Aufruf für L in der Liste (cons N L) macht
genau dasselbe wie bei einer anderen Liste (cons K L) • Idee: Zusätzlicher Parameter akkumuliert das
Wissen über den Kontext, in diesem Fall die akkumulierte Distanz
8
(define (rel-2-abs alon accu-dist) (cond [(empty? alon) empty] [else (cons (+ (first alon) accu-dist)
(rel-2-abs (rest alon) (+ (first alon) accu-dist)))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Lösung• Funktion ist noch nicht äquivalent zu relative-2-
absolute– Es gibt einen zusätzlichen Parameter – Dieser ist am Anfang 0
9
(define (relative-2-absolute2 alon) (local ((define (rel-2-abs alon accu-dist) (cond [(empty? alon) empty] [else (cons (+ (first alon) accu-dist) (rel-2-abs (rest alon) (+ (first alon) accu-dist)))]))) (rel-2-abs alon 0)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Beispiel mit generativer Rekursion• Das Problem, in bestimmten Situationen Wissen zu
akkumulieren, existiert nicht nur bei struktureller, sondern auch bei generativer Rekursion
• Beispiel: Finden von Pfaden in einem einfachen Graphen, in dem jeder Knoten nur eine ausgehende Kante hat (Zyklen sind erlaubt!).
10
(define SimpleG '((A B) (B C) (C E) (D E) (E B) (F F)))
• Ein Knoten ist ein Symbol.
• Ein Paar ist eine Liste mit zwei Knoten (mit S, T Symbole): (list S T)
• Ein simple-graph ist eine Liste
von Paaren: (listof pair).
A B C D E F
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Beispiel mit generativer Rekursion• Der Kopf der Funktion ist einfach
• Für die Implementierung des Körpers brauchen wir Antworten zu den 4 Basisfragen bei generativer Rekursion:– Was ist ein trivial zu lösendes Problem?
• Das Problem ist trivial, wenn die Knoten orig und dest den selben Knoten bezeichnen
– Was ist eine dazugehörige Lösung?• Einfach: true.
– Wie erzeugen wir neue Probleme?• Wenn orig nicht denselben Knoten wie dest bezeichnet, können
wir folgendes tun: gehe zu den Knoten, mit denen orig verbunden ist und stelle fest, ob diese eine Verbindung mit dest haben.
– Wie verbinden wir die Lösungen?• Wir müssen nichts mehr tun, wenn wir das neue Problem gelöst
haben. Wenn origs Nachbar mit dest verbunden ist, gilt das auch für orig.
11
;; route-exists? : node node simple-graph -> boolean;; to determine whether there is a route from ;; orig to dest in sg(define (route-exists? orig dest sg) ...)
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Die Lösung ist nun einfach…
• …funktioniert aber leider nicht richtig!– route-exists? kann nie false zurückgeben
12
;; route-exists? : node node simple-graph -> boolean;; to determine whether there is a route from orig to dest in sg(define (route-exists? orig dest sg) (cond [(symbol=? orig dest) true] [else (route-exists? (neighbor orig sg) dest sg)]))
;; neighbor : node simple-graph -> node;; to determine the node that is connected to a-node in sg(define (neighbor a-node sg) (cond [(empty? sg) (error "neighbor: impossible")] [else (cond
[(symbol=? (first (first sg)) a-node) (second (first sg))] [else (neighbor a-node (rest sg))])]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Ursache des Fehlers• Betrachten wir einen Fall, in dem “false”
zurückgegeben werden müsste:
• Die Funktion ruft sich nach ein paar Aufrufen wieder mit denselben Parametern auf– Endlosschleife
• Ursache: Die Funktion “vergisst”, mit welchen Parametern sie schon aufgerufen wurde
13
(route-exists? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))= (route-exists? 'E 'D '((A B) (B C) (C E) (D E) (E B) (F F)))= (route-exists? 'B 'D '((A B) (B C) (C E) (D E) (E B) (F F)))= (route-exists? 'C 'D '((A B) (B C) (C E) (D E) (E B) (F F)))= …
A B C D E F
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Lösung• Akkumulation der besuchten Knoten
• Akkumulation alleine reicht natürlich nicht aus, wir müssen das akkumulierte Wissen auch nutzen!
14
;; route-exists-accu? : ;; node node simple-graph (listof node) -> boolean;; to determine whether there is a route from orig to dest in sg, ;; assuming the nodes in accu-seen have already been inspected ;; and failed to deliver a solution (define (route-exists-accu? orig dest sg accu-seen) (cond [(symbol=? orig dest) true] [else (route-exists-accu? (neighbor orig sg) dest sg
(cons orig accu-seen))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Lösung• Check hinzufügen, spezialisieren…
15
;; route-exists2? : node node simple-graph -> boolean;; to determine whether there is a route from orig->dest in sg(define (route-exists2? orig dest sg) (local ((define (re-accu? orig dest sg accu-seen) (cond [(symbol=? orig dest) true] [(contains? orig accu-seen) false] [else (re-accu? (neighbor orig sg) dest sg (cons orig accu-seen))]))) (re-accu? orig dest sg empty)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Vorläufige Zusammenfassung• Sowohl strukturelle als auch generative Rekursion
können von dem Problem betroffen sein, dass man einen Akkumulator benötigt– Bei dem Beispiel mit struktureller Rekursion haben wir die
Performanz erheblich verbessert– Das Beispiel mit generativer Rekursion funktionierte ohne
Akkumulator nicht
• Betrachten wir nun im Allgemeinen, wann man einen Akkumulator benötigt.
16
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Entwurf von Funktionen mit Akkumulatoren
• Oft erkennt man, dass man einen Akkumulator benötigt, erst nachdem man bereits eine Version der Funktion implementiert hat…
• Der Schlüssel zur Entwicklung einer Funktion im Akkumulator-Stil ist: – Erkenne, dass die Funktion einen Akkumulator benötigt,
oder von dessen Verwendung profitiert; – Verstehe, was den Akkumulator ausmacht.
17
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Erkennen, dass man einen Akkumulator benötigt
• Wir haben zwei Gründe gesehen:– Performanz– Die Funktion funktioniert ohne Akkumulator nicht korrekt.
• Das sind die wichtigsten Gründe um Akkumulator-Parameter hinzuzufügen.
• In beiden Fällen ist es entscheidend, dass wir zunächst eine vollständige Funktion auf Basis eines Design Musters entwerfen.
• Dann studieren wir diese Funktion und schauen nach den folgenden Eigenschaften…
18
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Potentieller Kandidat für AkkumulatorHeuristik: • Die Funktion ist strukturell rekursiv• Ergebnis einer rekursiven Anwendung wird durch eine
zusätzliche, rekursive Funktion bearbeitet
19
;; invert : (listof X) -> (listof X);; to construct the reverse of alox;; structural recursion (define (invert alox) (cond [(empty? alox) empty] [else (make-last-item (first alox) (invert (rest alox)))]))
;; make-last-item : X (listof X) -> (listof X);; to add an-x to the end of alox;; structural recursion (define (make-last-item an-x alox) (cond [(empty? alox) (list an-x)] [else (cons (first alox) (make-last-item an-x (rest alox)))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Funktionen im Akkumulator-StilWenn wir entschieden haben, eine Funktion im Akkumulator-Stil zu schreiben, führen wir den Akkumulator in zwei Schritten hinzu
1. Definition und Bereitstellung des Akkumulators– Welches Wissen über die Parameter muss im Akkumulator
gespeichert werden?• Für relative-2-absolute reichte es aus, die
gesamte bisherige Distanz zu akkumulieren (Akkumulator = eine Zahl)
• Für das Routenproblem mussten wir jeden Knoten, der bisher besucht wurde, speichern (Akkumulator = eine Liste von Knoten)
2. Ausnutzung des Akkumulators
20
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Definition und Bereitstellung des Akkumulators
• Füge ein Template der Akkumulatorfunktion als lokale Funktion ein.
• Benenne die Parameter der Hauptfunktion und der Hilfsfunktion unterschiedlich.
21
;; invert : (listof X) -> (listof X);; to construct the reverse of alox(define (invert alox0) (local (;; accumulator ...
(define (rev alox accumulator) (cond [(empty? alox) ...] [else
(rev (rest alox)... (first alox)... accumulator)... ]))) (rev alox0 ...)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Analyseinvert kann nichts vergessen, da es nur die Reihenfolge von Listenelementen ändert. Daher könnten wir einfach alle Elemente akkumulieren denen rev begegnet. Das bedeutet:
– accumulator steht für eine Liste und– accumulator steht für alle Elemente in alox, die dem alox-
Argument von rev vorangehen.– Der Anfangswert von accumulator ist leer. – Wenn rev rekursiv aufgerufen wird, hat es nur ein Element
bearbeitet: (first alox). Um uns an dieses Element zu erinnern, können wir es mittels cons an die aktuellen Liste accumulator einfügen.
22
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Erweiterte Version von invert
• accumulator enthält nicht einfach die Elemente von alox0 vor alox, sondern eine Liste dieser Elemente in umgekehrter Reihenfolge.
23
;; invert : (listof X) -> (listof X);; to construct the reverse of alox(define (invert alox0) (local (;; accumulator is the reversed list of all those items
;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) …] [else
…(rev (rest alox) (cons (first alox) accumulator))…])))
(rev alox0 empty)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Ausnutzen des Akkumulators• accumulator ist die Liste aller Elemente von alox0 vor alox in umgekehrter Reihenfolge…
• Sobald alox leer ist, enthält accumulator die Umkehrung von alox0.
24
;; invert : (listof X) -> (listof X);; to construct the reverse of alox(define (invert alox0) (local (;; accumulator is the reversed list of all those items
;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) accumulator] [else
(rev (rest alox) (cons (first alox) accumulator))]))) (rev alox0 empty)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
[Direkte Implementierung von invert]• Variante ohne Akkumulator…
25
;; invert : (listof X) -> (listof X);; to construct the reverse of alox(define (invert alox) (cond [(empty? alox) empty] [else
(append (invert (rest alox)) (list (first alox)))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Definition von Akkumulator-Invarianten
• Im Allgemeinen beschreibt eine Akkumulator-Invariante einen Beziehung zwischen– dem eigentlichen Argument der Funktion, – dem aktuellen Argument der Hilfsfunktion, und– dem Akkumulator
• Wir betrachten die Definition von Akkumulator-Invarianten an einem Beispiel, welches keinen Akkumulator benötigt– Ermöglicht genauen Vergleich der beiden Varianten
• Beispiel: Addition aller Zahlen einer Liste
26
;; sum : (listof number) -> number;; to compute the sum of the numbers in alon;; structural recursion (define (sum alon) (cond [(empty? alon) 0] [else (+ (first alon) (sum (rest alon)))]))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Definition von Akkumulator-Invarianten
• Erster Schritt zu einer Akkumulator-Variante: Template
• Ziel von sum ist die Summation von Zahlen• Intuitive Akkumulator-Invariante: Akkumulator
speichert die Summe der Zahlen, die schon bearbeitet wurden 27
;; sum : (listof number) -> number;; to compute the sum of the numbers on alon0(define (sum alon0) (local (;; accumulator ...
(define (sum-a alon accumulator) (cond [(empty? alon) ...] [else
... (sum-a (rest alon) ... (first alon) ... accumulator)
... ]))) (sum-a alon0 ...)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Definition von Akkumulator-Invarianten
• Erster Schritt zu einer Akkumulator-Variante: Template
28
;; sum : (listof number) -> number;; to compute the sum of the numbers in alon0(define (sum alon0) (local (;; accumulator is the sum of the numbers ;; in alon0 that preced those in alon
(define (sum-a alon accumulator) (cond [(empty? alon) ...] [else
... (sum-a (rest alon) (+ (first alon) accumulator))
... ]))) (sum-a alon0 0)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Definition von Akkumulator-Invarianten• Der Rest ist nun einfach
• Der Schlüssel ist die präzise Definition der Akkumulator-Invariante, der Rest folgt dann von selbst.
29
;; sum : (listof number) -> number;; to compute the sum of the numbers on alon0(define (sum alon0) (local (;; accumulator is the sum of the numbers ;; in alon0 that preceeded those in alon
(define (sum-a alon accumulator) (cond [(empty? alon) accumulator] [else (sum-a (rest alon)
(+ (first alon) accumulator))]))) (sum-a alon0 0)))
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Vergleich• Ursprüngliche Version
• Akkumulator-Version
30
(sum (list 10.23 4.50 5.27))= (+ 10.23 (sum (list 4.50 5.27)))= (+ 10.23 (+ 4.50 (sum (list 5.27))))= (+ 10.23 (+ 4.50 (+ 5.27 (sum empty))))= (+ 10.23 (+ 4.50 (+ 5.27 0)))= (+ 10.23 (+ 4.50 5.27))= (+ 10.23 9.77)= 20.0
(sum (list 10.23 4.50 5.27))= (sum-a (list 10.23 4.50 5.27) 0)= (sum-a (list 4.50 5.27) 10.23)= (sum-a (list 5.27) 14.73)= (sum-a empty 20.0)= 20.0
Dr. G. RößlingProf. Dr. M. Mühlhäuser
RBG / Telekooperation©
Grundlagen der Informatik I: T8
Zusammenfassung• Manche Funktionen sind nur im Akkumulator-Stil
korrekt zu implementieren– Beispiel: route-exists?
• In anderen Fällen führt der Akkumulator-Stil zu einem Effizienzgewinn– Beispiel: relative-2-absolute
• Es ist jedoch nicht so, dass Funktionen im Akkumulator-Stil immer schneller sind– Beispiel: sum
• Wir werden später sehen, dass Funktionen im Akkumulator-Stil sehr ähnlich zu Schleifen in Sprachen wie Java, Pascal etc. sind
31
Top Related