Grundlagen der informatik 1 thema 6 generative rekursion
This presentation is the property of its rightful owner.
Sponsored Links
1 / 67

Grundlagen der Informatik 1 Thema 6: Generative Rekursion PowerPoint PPT Presentation


  • 58 Views
  • Uploaded on
  • Presentation posted in: General

Grundlagen der Informatik 1 Thema 6: Generative Rekursion. Prof. Dr. Max Mühlhäuser Dr. Guido Rößling. Inhaltsverzeichnis. Einführung in generativ rekursive Funktionen Sortieren mittels generativ rekursiver Prozeduren Richtlinien für den Entwurf von generativ rekursiven Prozeduren

Download Presentation

Grundlagen der Informatik 1 Thema 6: Generative Rekursion

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Grundlagen der informatik 1 thema 6 generative rekursion

Grundlagen der Informatik 1Thema 6: Generative Rekursion

Prof. Dr. Max Mühlhäuser

Dr. Guido Rößling


Inhaltsverzeichnis

Inhaltsverzeichnis

  • Einführung in generativ rekursive Funktionen

  • Sortieren mittels generativ rekursiver Prozeduren

  • Richtlinien für den Entwurf von generativ rekursiven Prozeduren

  • Strukturelle versus generative Rekursion

  • Backtracking-Algorithmen: Durchlaufen von Graphen


Generative rekursion

Generative Rekursion

  • Bisher haben wir strukturelle Rekursion verwendet, um strukturell rekursive Daten zu verarbeiten

    • Wir haben die Eingabedaten in ihre direkten strukturellen Komponenten zerlegt

    • Wir haben die Komponenten verarbeitet und die Ergebnisse kombiniert

  • Allerdings:

    • Nicht alle Probleme lassen sich mit strukturell rekursiven Funktionen lösen

    • Auch wenn es geht, ist strukturelle Rekursion nicht immer die beste Lösung

  • In dieser Vorlesung werden wir eine neue Funktionsart kennen lernen

    • Generativ rekursive Funktionen


Generative rekursion1

Generative Rekursion

  • Teile und herrsche (Divide & Conquer)

    • Wenn das Problem trivial lösbar ist, wird die entsprechende Lösung zurückgeliefert

    • Ansonsten:

      • Teiledas Problem in neue kleinere Teilprobleme (es werden kleinere Probleme generiert)

      • Herrsche: Die kleineren Probleme werden gelöst

      • Kombinieredie Lösungen der kleineren Probleme zu einer Lösung für das Ursprungsproblem

  • Design von generativ rekursiven Funktionen (Algorithmen) ist eher eine kreative Aktivität, die einen Einblick braucht – ein “Heureka, ich hab's!”.


Modellieren eines balls der auf dem tisch rollt

Modellieren eines Balls, der auf dem Tisch rollt…

Aufgabenbeschreibung

  • Der Ball rollt mit einer konstanten Geschwindigkeit, bis er von der Tischkante herabfällt

  • Den Tisch stellen wir als einen Fläche mit einer festgelegten Länge und Breite dar

  • Den Ball stellen wir als eine Scheibe dar, welche sich auf der Fläche bewegt

  • Bewegung stellen wir durch die Wiederholung folgender Schritte dar:

    • Zeichne die Scheibe in der aktuellen Position auf der Fläche

    • Warte eine bestimmte Zeitperiode

    • Lösche die Scheibe von der aktuellen Position

    • Verschiebe sie an die aktuelle Position


Ballstruktur und operationen

Ballstruktur und -operationen

;;TeachPack: draw.ss

;; structure: (make-ball numbernumbernumbernumber)

(define-structball (x y delta-x delta-y))

;; draw-and-clear : a-ball -> true

(define (draw-and-clear a-ball)

(and

(draw-solid-disk (make-posn

(ball-x a-ball)

(ball-y a-ball)) 5 'red)

(sleep-for-a-while DELAY)

(clear-solid-disk (make-posn

(ball-x a-ball)

(ball-y a-ball)) 5 'red)))


Ballstruktur und operationen1

Ballstruktur und -operationen

;; move-ball : ball -> ball

(define (move-ball a-ball)

(make-ball (+ (ball-x a-ball) (ball-delta-x a-ball))

(+ (ball-y a-ball) (ball-delta-y a-ball))

(ball-delta-x a-ball)

(ball-delta-y a-ball)))

;; Dimension ofsurface

(defineWIDTH100)

(defineHEIGHT100)

;; Delay constant

(defineDELAY.1)


Das rollen des balls

Um den Ball einige Male zu verschieben, können wir schreiben:

Das wird nach einiger Zeit langweilig.

Wir brauchen eine Funktion, die den Ball verschiebt, bis er außerhalb der Grenze ist.

Das Rollen des Balls

(definethe-ball (make-ball10 20 -5 +17))

(and

(draw-and-clearthe-ball)

(and

(draw-and-clear (move-ball the-ball))

...))


Das rollen des balls1

Herausfinden, ob ein Ball außerhalb der Grenze ist:

Schablone für die Funktion, die den Ball verschiebt, bis er außerhalb der Grenze ist:

Das Rollen des Balls

;; out-of-bounds? : a-ball -> boolean

(define (out-of-bounds? a-ball)

(not

(and

(<=0 (ball-x a-ball) WIDTH)

(<=0 (ball-y a-ball) HEIGHT))))

Der triviale Fall: wir geben true zurück

;; move-until-out : a-ball -> true

(define (move-until-out a-ball)

(cond

[(out-of-bounds? a-ball) ... ]

[else...]))

true

?


Das rollen des balls2

Das Rollen des Balls

Nachdem der Ball gezeichnet und verschoben wurde, wenden wir move-until-out wieder an: rekursive Funktion

(define (move-until-out a-ball)

(cond

[(out-of-bounds? a-ball) true]

[else (and (draw-and-clear a-ball)

(move-until-out

(move-ball a-ball)))]))

Wir können nun die Funktion wie folgt testen: Eine Fläche der richtigen Größe, und ein Ball, der sich nach links unten bewegt, werden erzeugt.

(startWIDTHHEIGHT)

(move-until-out (make-ball1020-5+17))

(stop)


Neuer typ von rekursion

Neuer Typ von Rekursion

  • Die Prozedur move-until-out verwendet einen neuen Typ von Rekursion

    • Bedingungen haben nichts mit den Eingabe-Daten zu tun

    • Die rekursive Anwendung im Rumpf verarbeitet keinen Teil der Eingabe

      • move-until-out generiert eine andere komplett neue Ball-Struktur und benutzt diese für die Rekursion

(define (move-until-out a-ball)

(cond

[(out-of-bounds? a-ball) true]

[else (and (draw-and-clear a-ball)

(move-until-out

(move-ball a-ball)))]))

Wir haben noch kein Designrezept dafür


Inhaltsverzeichnis1

Inhaltsverzeichnis

  • Einführung in generativ rekursive Funktionen

  • Sortieren mittels generativ rekursiver Prozeduren

  • Richtlinien für den Entwurf von generativ rekursiven Prozeduren

  • Strukturelle versus generative Rekursion

  • Backtracking: Durchlaufen von Graphen


Sortieren quicksort mergesort

Sortieren: Quicksort&Mergesort

Es geht erneut um das Sortieren der Elemente einer Liste…

  • Wir haben schon insertionsortkennengelernt

    • Eine strukturell rekursive Prozedur

  • Nun werden wir zwei andere Algorithmen zum Sortieren kennen lernen: Quicksort& Mergesort

    • Klassische Beispiele für generative Rekursion

    • Basieren auf der "Teile & Herrsche"-Idee


Erinnerung insertion sort

[Erinnerung: insertionsort]

;; sort : list-of-numbers  ->  list-of-numbers

;; creates a sortedlistofnumb. fromnumbers in alon

(define (insertion-sortalon)

(cond

[(empty? alon) empty]

[else (insert (firstalon)

(sort (insertion-sortrestalon)))]))

unsorted

sorted

an

an


Quicksort die idee

Quicksort: Die Idee

  • Der Verlauf eines beliebigen Zwischenschritts: das Sortieren einer beliebigen SublisteL0=(listelp…elr)

    • Teile: PartitioniereL0 in zwei (eventuell leere) Listen, L1=(listelp…elq-1) und L2=(list elq+1…elr), so dass:

      • jedes Element aus L1kleiner oder gleich elq ist,

      • jedes Element aus L2 größer als elq ist

    • Herrsche: Wende die gleiche Prozedur rekursiv an, um L1 und L2 zu sortieren

    • Kombiniere: Stelle die Elemente der sortierten Listen L1 und L2 einfach nebeneinander

Drehpunkt

elq

<= elq

> elq


Quicksort die idee1

Quicksort: Die Idee

  • Zwei offene Fragen bisher:

    • Wie wählen wir das Drehpunktelement?

      • Wir nehmen das erste Element als Drehpunkt

    • Wann hören wir auf? Mit anderen Worten: Was ist der Trivialfall für Quicksort?

      • Die leere Liste ist immer sortiert!


Quicksort vorgehensweise

Quicksort: Vorgehensweise

  • Wähle das erste Element der Liste als Drehpunkt-Element („Pivot“)

  • Bestimme die erste Teilliste mit Elementen <= Pivot

  • Sortiere diese Teilliste rekursiv mit Quicksort

  • Bestimme die zweite Teilliste mit Elementen > Pivot

  • Sortiere diese Teilliste rekursiv mit Quicksort

  • Füge die sortierten Teillisten zu einer Liste zusammen


Quicksort at work

Sortiere (list 11 8 7 14):

Wähle das erste Element von '(11 8 7 14) als Drehpunkt-Element:11

Bestimme die erste Teilliste mit Elementen <= 11: '(8 7)

Sortiere diese Teilliste

Wähle das erste Element von '(8 7) als Drehpunkt-Element: 8

Bestimme die erste Teilliste mit Elementen <= 8: '(7)

Sortiere diese Teilliste

Wähle das erste Element von '(7) als Drehpunkt-Element: 7

Bestimme die Teilliste mit Elementen <= 7: empty

Sortiere diese Teilliste  Ergebnis empty

Bestimme die zweite Teilliste mit Elementen > 7: empty

Sortiere diese Teilliste  Ergebnis empty

Füge (empty 7 empty) zu einer Liste zusammen -> (list 7)

Bestimme die zweite Teilliste mit Elementen > 8:  empty

Sortiere diese Teilliste  Ergebnis empty

Füge ((list 7) 8 empty) zu einer Liste zusammen  (list 7 8)

Bestimme…

QuicksortatWork


Quicksort at work1

QuicksortatWork

11

(list 14)

(list 8 7)

empty

14

empty

8

empty

(list 7)

empty

7

empty

(list 14)

(list 7)

(list 7 8)

(list 7 8 11 14)


Quicksort schematisch

Quicksort schematisch

Drehpunkt

(Pivot-Element)


Quicksort algorithmus

quicksortunterscheidet zwei Fälle:

Ist die Eingabe leer, wird empty zurückgegeben

Ansonsten wird eine Rekursion durchgeführt.

Jede Teilliste wird separat mit quicksortsortiert

Die beiden sortierten Versionen der zwei Listen werden dann mit append kombiniert

Quicksort Algorithmus

;; quicksort2: (listofnumber) -> (listofnumber)

(define (quicksort2 alon)

(cond

[(empty? alon) empty]

[else

(append

(quicksort2 (less-or-equal (restalon)

(firstalon)))

(list (firstalon))

(quicksort2 (greater-than (restalon)

(firstalon))))

]))


Hilfsfunktionen von quicksort

greater-thanfiltert die Elemente heraus, die größer als threshold sind:

less-or-equalfiltert die Elemente heraus, die kleiner als oder gleich threshold sind:

Hilfsfunktionen von Quicksort

(define (greater-than alonthreshold)

(filter1 > alon threshold)))

(define (less-or-equal alonthreshold)

(filter1 <= alon threshold)))


Auswertungsbeispiel quicksort

Auswertungsbeispiel Quicksort

(quicksort(list11 8 7 14))

= (append (quicksort(list8 7))

(list11)

(quicksort(list14)))

= (append (append (quicksort(list7))

(list8)

(quicksortempty))

(list 11)

(quicksort(list 14)))

= (append (append (append (quicksortempty)

(list7)

(quicksortempty))

(list 8)

(quicksortempty))

(list 11)

(quicksort(list 14)))

= ...


Auswertungsbeispiel quicksort1

Auswertungsbeispiel Quicksort

= (append (append (appendempty

(list7)

empty)

(list 8)

empty)

(list 11)

(quicksort(list 14)))

= (append (append (list7)

(list8)

empty)

(list 11)

(quicksort(list 14)))

= (append (list78)

(list11)

(quicksort(list14)))

= ...


Mergesort die idee

mergesort: Die Idee

Idee:

Teile die Liste in der Mitte

Wende die Funktion rekursiv auf die zwei Teillisten an

Mische die sortierten Teillisten zu einer neuen geordneten Liste zusammen


Zusammenmischen von zwei geordneten listen

Zusammenmischen von zwei geordneten Listen

  • Gegeben sind zwei geordnete Listen ls-1 und ls-2.

  • Wie kann man sie in einer geordneten Liste zusammenmischen?

ls-1

ls-2

1

2

4

7

3

5

6

8

Vergleichen und kopieren des kleineren Elements, dann weitergehen

sorted-list

1

2

3

4

5

6

7

8


Zusammenmischen von zwei geordneten listen1

Zusammenmischen von zwei geordneten Listen

(define (merge ls1 ls2)

(cond

[(empty? ls1) ls2]

[(empty? ls2) ls1]

[(<= (first ls1) (first ls2))

(cons (first ls1)

(merge (rest ls1) ls2))

]

[else (cons (first ls2)

(merge ls1 (rest ls2)))]

)

)


Mergesort der algorithmus

mergesort: der Algorithmus

(define (mergesortalon)

(local

((define (merge-stepleftright)

(cond

[(>= leftright) alon]

[else

(local(

(definemid (floor (/ (+ leftright) 2)))

(defineleft-list

(mergesort(extractalonleftmid)))

(defineright-list

(mergesort

(extractalon (+ mid 1) right))))

(mergeleft-listright-list)

)

]

)))

(merge-step 1 (lengthalon))))


Mergesort der algorithmus1

mergesort:der Algorithmus

(define (extract alonleft right)

(cond

[(empty? alon) empty]

[(> left right) empty]

[(> left 1)

(extract

(rest alon)

(- left 1)

(- right 1))]

[else (cons

(first alon)

(extract

alon

(+ left 1)

right))]))


Inhaltsverzeichnis2

Inhaltsverzeichnis

  • Einführung in generativ rekursive Funktionen

  • Sortieren mittels generativ rekursiver Prozeduren

  • Richtlinien für den Entwurf von generativ rekursiven Prozeduren

  • Strukturelle versus generative Rekursion

  • Backtracking: Durchlaufen von Graphen


Richtlinien f r den entwurf von generativ rekursiven prozeduren

Richtlinien für den Entwurf vongenerativ rekursiven Prozeduren

  • Verstehe die Natur der Daten der Prozedur

  • Beschreibe den Prozess bzgl. der Daten durch Entwurf einer neuen Struktur oder Partitionieren einer Liste von Zahlen.

  • Unterscheide zwischen den Eingabe-Daten

    • die trivial verarbeitet werden können, und denen,

    • die nicht trivial verarbeitet werden können.

  • Die Generierung von Problemen ist der Schlüssel zum Entwurf von Algorithmen

  • Die Lösungen der generierten Probleme müssen kombiniert werden


Zur ck zu den 6 stufen des designs

Zurück zu den 6 Stufen des Designs

  • Datenanalyse und –entwurf

    • Analysiere und bestimme Datensammlungen, welche das Problem darstellen

  • Vertrag, Absicht, Kopf (Header)

    • Lege fest, was die Funktion tut

    • Erkläre in natürlicher Sprache, wie sie funktioniert

  • Funktionsbeispiele

    • Zeige, wie der Algorithmus für bestimmte Eingaben verfährt

  • Vorlage

    • Folge einer generellen Vorlage

  • Definition

    • Beantworte die Fragen, die die Vorlage vorgibt

  • Testen

    • Teste die fertig gestellten Funktionen

    • Beseitige die Fehler


Allgemeine vorlage f r generative prozeduren

Allgemeine Vorlage für generative Prozeduren

(define (generative-recursive-funproblem)

(cond

[(trivially-solvable? problem)

(determine-solutionproblem)]

[else

(combine-solutions

... problem ...

(generative-recursive-fun

(generate-problem-1 problem))

...

(generative-recursive-fun

(generate-problem-n problem)))]))


Prozedurdefinition

Prozedurdefinition

  • Was ist ein trivial lösbares Problem und die dazugehörige Lösung?

  • Wie generieren wir neue Probleme, die leichter zu lösen sind als das ursprüngliche Problem?

    • Gibt es ein neues Problem, das wir generieren, oder gibt es viele?

  • Ist die Lösung für das gegebene Problem die gleiche wie für die (eines der) neuen Probleme?

    • Oder müssen wir die Lösungen kombinieren, um eine Lösung für das ursprüngliche Problem zu erstellen?

    • Und wenn das so ist, benötigen wir dann Teile der Daten des ursprünglichen Problems?


Terminierung strukturell rekursiver prozeduren

Terminierung strukturell rekursiver Prozeduren

  • Bisher hat jede Funktion immer eine Ausgabe für eine gültige Eingabe produziert

     Die Evaluierung der strukturell rekursiven Prozeduren hat immer terminiert.

  • Wesentliches Merkmal unseres Rezepts für strukturell rekursive Prozeduren:

    • Jeder Schritt der natürlichen Rekursion konsumiert eine direkte Komponente der Eingabe und nicht die Eingabe selbst

  • Da die Daten hierarchisch konstruiert sind, ist es sicher, dass die Eingabe in jedem Schritt kleiner wird

    • Früher oder später wird die Prozedur ein atomares Datum konsumieren und terminieren


Terminierung generativ rekursiver prozeduren

Terminierung generativ rekursiver Prozeduren

  • Dieses Merkmal gilt nicht für generativ rekursive Funktionen

    • Die interne Rekursion konsumiert nicht eine direkte Komponente der Eingabe, sondern irgendein neues Datum, das aus der Eingabe generiert wird

  • Ein Rekursionsschritt kann potenziell immer wieder die ursprüngliche Eingabe generieren und somit die Evaluierung daran verhindern, jemals ein Ergebnis zu produzieren

    • Wir sagen, dass das Programm in eine endlose Schleife gerät


Nicht terminierende programme

Nicht terminierende Programme

  • Was passiert, wenn wir die folgenden drei Ausdrücke ans Ende des Definition-Fensters von DrScheme setzen und dann auf execute klicken?

  • Produziert der zweite Ausdruck jemals einen Wert, so dass der dritte Ausdruck evaluiert werden kann, um die Fläche verschwinden zu lassen?

(startWIDTHHEIGHT)

(move-until-out (make-ball102000))

(stop)


Nicht terminierende programme1

Nicht terminierende Programme

Kleine Fehler bei der Prozessdefinition können Endlosschleifen hervorrufen:

;; less-or-equal: (list-of-numbers) number-> (list-of-numbers)

(define(less-or-equalalonthreshold)

(cond

[(empty?alon) empty]

[else (if (<= (firstalon) threshold)

(cons (firstalon)

(less-or-equalalonthreshold))

(less-or-equal(restalon) threshold))]))

statt (restalon)

Quicksort terminiert nicht mit der neuen Funktion

(quick-sort (list 5))

= (append (quicksort (less-or-equal5 (list 5)))

(list 5)

(quicksort (greater-than5 (list 5))))

= (append (quicksort(list 5))

(list 5)

(quicksort (greater-than5 (list 5))))


Terminierungsargument

Terminierungsargument

  • Das Terminierungsargument ist ein zusätzlicher Schritt im Designrezept für generativ rekursive Funktionen

  • Das Argument erklärt:

    • warum der Prozess für jede Eingabe eine Ausgabe liefert

    • wie die Funktion diese Idee implementieren kann

    • wann der Prozess eventuell nicht terminieren würde


Terminierungsargument f r quicksort

Terminierungsargument für Quicksort

Bei jedem Schritt teilt quicksortdie Liste mit less-or-equalund greater-than in zwei Teillisten.

Jede dieser Funktionen liefert eine Liste, die kleiner als die Eingabeliste (zweites Argument) ist, sogar dann, wenn das Drehpunktelement (erstes Argument) ein Element der Liste ist.

Somit verarbeitet jede rekursive Anwendung von quicksorteine Liste, die auf jeden Fall kürzer ist als die Eingabeliste.

Letztendlich bekommt quick-sort eine leere Liste und liefert empty.


Neue terminierungs f lle

Neue Terminierungs-Fälle

Das Argument der Terminierung kann eventuell zusätzliche Terminierungs-Fälle aufdecken.

Dieses Wissen kann dem Algorithmus hinzugefügt werden:

So liefert (less-or-equal N (list N))und(greater-than N (list N)) immer empty

;; quick-sort : (listofnumber) -> (listofnumber)

(define (quick-sortalon)

(cond

[(empty? alon) empty]

[(empty? (restalon)) alon]

[else

(append

(quick-sort(less-or-equal (restalon)

(firstalon)))

(list (firstalon))

(quick-sort(greater-thanalon(firstalon))))

]))


Richtlinien f r den entwurf von generativen prozeduren

Richtlinien für den Entwurf von generativen Prozeduren


Inhaltsverzeichnis3

Inhaltsverzeichnis

  • Einführung in generativ rekursive Funktionen

  • Sortieren mittels generativ rekursiver Prozeduren

  • Richtlinien für den Entwurf von generativ rekursiven Prozeduren

  • Strukturelle versus generative Rekursion

  • Backtracking: Durchlaufen von Graphen


Strukturelle rekursion als spezialfall der generativen rekursion

trivially-solvable?

empty?

generate-problem

rest

Strukturelle Rekursion alsSpezialfall der generativen Rekursion

Vorlage für generative Rekursion

(define (generative-recursive-funproblem)

(cond

[(trivially-solvable? problem)

(determine-solutionproblem)]

[else

(combine-solutions

problem

(generative-recursive-fun

(generate-problemproblem)))]))

Vorlage für Listenverarbeitung

(define (generative-recursive-funproblem)

(cond

[(empty?problem) (determine-solutionproblem)]

[else

(combine-solutions

problem

(generative-recursive-fun (restproblem)))]))


Strukturelle vs generative rekursion

Strukturelle vs. generative Rekursion

Gibt es einen Unterschied zwischen struktureller und generativer Rekursion?

  • Strukturell rekursive Funktionen scheinen lediglich Spezialfälle generativer Rekursion zu sein

  • Aber: Diese „alles ist gleich“-Einstellung hilft beim Verständnis des Entwurfsprozesses nicht weiter

    • Strukturell und generativ rekursive Funktionen werden mit jeweils anderen Ansätzen entworfen und haben unterschiedliche Konsequenzen


Gr ter gemeinsamer teiler gcd

Größter gemeinsamer Teiler (GCD)

(GCD = engl. greatest common denominator)

  • Beispiele:

    • 6 und 25 sind beides Zahlen mit mehreren Teilern:

      • 6 ist ganzzahlig teilbar durch 1, 2, 3, und 6;

      • 25 ist ganzzahlig teilbar durch 1, 5, und 25.

      • Der größte gemeinsame Teiler von 25 und 6 ist 1.

    • 18 und 24 haben viele gemeinsame Teiler:

      • 18 ist ganzzahlig teilbar durch 1, 2, 3, 6, 9, 18;

      • 24 ist ganzzahlig teilbar durch 1, 2, 3, 4, 6, 8, 12, 24.

      • Der größte gemeinsame Teiler ist 6.


Gcd auf basis struktureller rekursion

GCD auf Basis struktureller Rekursion

Testet für jede Zahl, i = [min(n,m), …,1], ob sie nundm ganzzahlig teilt und liefert die erste solche Zahl.

;; gcd-structural : N[>= 1] N[>= 1] -> N

;; structuralrecursionusingdatadefinitionof N[>= 1]

(define (gcd-structural n m)

(local

((define (first-divisor i)

(cond

[(= i 1) 1]

[(and(= (remainder n i) 0)

(= (remainder m i) 0))

i]

[else (first-divisor (- i 1))]

)

)

)

(first-divisor (min m n))))

Ineffizient bei großen Zahlen!


Analyse der strukturellen rekursion

Analyse der strukturellen Rekursion

  • gcd-structural testet blind jede natürliche Zahl kleiner als min(n,m), ob sie sowohl n als auch m ganzzahlig teilt und gibt die erste solche Zahl zurück

    • Diese Strategie funktioniert nur für kleine Zahlen gut

  • Für die folgende Berechnung muss gcd-structural 101135853 – 177 = 101135676 Zahlen testen!

    (gcd-structural 101135853 450146400)  177

    • Selbst schnelle Rechner brauchen Minuten dafür

  • Fügen Sie die Definition von gcd-structural in das Definition-Fenster ein und evaluieren Sie im Interaktions-Fenster folgenden Ausdruck … und gehen Sie dann eine Weile Kaffee trinken 

    (time (gcd-structural101135853 450146400))


Der euklidische algorithmus

Der Euklidische Algorithmus

  • Der Euklidische Algorithmus zur Bestimmung der größten gemeinsamen Teiler (GCD) zweier ganzer Zahlen ist einer der ältesten bekannten Algorithmen,

    • Erscheint in EuklidsElementenca. 300 v. Chr.

    • Der Algorithmus wurde aber wahrscheinlich nicht von Euklid entdeckt; es könnte sein, dass der Algorithmus bereits 200 Jahre früher bekannt war.

Erkenntnis: Für zwei natürliche Zahlen n und m, n>m,GCD(n, m) = GCD(m,rest(n/m)).

(gcd larger smaller) =

(gcdsmaller (remainder larger smaller))

Beispiel: GCD(24, 18) = GCD(18, remainder(24/18)) = GCD(18, 6) = GCD(6,0) = 6


Gcd generativer algorithmus

GCD: generativer Algorithmus

;; gcd-generative : N[>= 1] N[>=1] -> N

(define (gcd-generative n m)

(local

((define (clever-gcd larger smaller)

(cond

[(= smaller 0) larger]

[else (clever-gcd

smaller

(remainder larger smaller))]))

)

(clever-gcd (max m n) (min m n))))

clever-gcd basiert auf generativer Rekursion:

  • Der trivial lösbare Fall ist smaller= 0.

  • Der generative Schritt ruft clever-gcd mit smaller und (remainder larger smaller)auf

(gcd-generative101135853450146405) nur 9 Iterationen!


Der euklidische algorithmus1

Der Euklidische Algorithmus

Sei n = qm + r, dann teilt jede Zahl u, welche n und m teilt (n = su, m = tu), auch r

r = n – qm = su – qtu = (s – qt)u

Jede Zahl v, die m und r teilt (m = s'v, r = t'v ), teilt auch n

n = qm + r = qs'v+ t'v= (qs' + t')v

  • Jeder gemeinsame Teiler von n und m ist auch ein gemeinsamer Teiler von m und r.

  • gcd(n,m) = gcd(m,r)

  • Es reicht aus, den Prozess mit m und r weiterzuführen

  • Da der absolute Wert von r kleiner ist als m, werden wir r = 0 nach endlich vielen Schritten erreichen


Was sollte man benutzen

Was sollte man benutzen?

  • Frage: Soll man daraus schließen, dass generative Rekursion besser ist als strukturelle Rekursion?

  • Antwort: Nein, nicht automatisch.

    • Selbst eine gut entworfene generative Prozedur ist nicht immer schneller als die strukturelle Rekursion

      • So gewinnt quicksortgegenüber insertionsort nur für große Listen

    • Strukturelle Rekursion ist einfacher zu entwerfen

      • Generativ rekursive Prozeduren zu entwerfen erfordert oft fundierte mathematische Kenntnisse

    • Strukturelle Rekursion ist einfacher zu verstehen

      • Es könnte schwierig sein, die Idee des generativen Schritts zu verinnerlichen.


Was sollte man benutzen1

Was sollte man benutzen?

Beginne mit struktureller Rekursion.

Wenn sie zu langsam ist, versuche generative Rekursion einzusetzen.

Dokumentiere die Problemgeneration mit guten Beispielen, finde ein gutes Terminierungs-Argument.


Inhaltsverzeichnis4

Inhaltsverzeichnis

  • Einführung in generativ rekursive Funktionen

  • Sortieren mittels generativ rekursiver Prozeduren

  • Richtlinien für den Entwurf von generativ rekursiven Prozeduren

  • Strukturelle versus generative Rekursion

  • Backtracking: Durchlaufen von Graphen


Graphen traversieren

Scheme – Listen

Darstellung

(defineGraph

'((A (BE))

(B (EF))

(C (D))

(D ())

(E (C))

(F (DG))

(G ())))

B

C

D

A

E

F

G

Graphen traversieren

  • Ein Graph ist eine Sammlung von Knoten und Kanten.

  • Die Kanten repräsentieren gerichtete Verbindungen zwischen den Knoten.

  • Kann benutzt werden, um folgendes zu beschreiben:

    • Einen Plan von Einbahnstraßen in einer Stadt,

    • Beziehungen zwischen Personen,

    • Verbindungen im Internet, etc.


Graphen traversieren1

D

B

C

A

E

F

G

Graphen traversieren

;; find-route : node node graph -> (listof node)

;; to create a path from origination to destination in G

;; false, if there is no path

(define (find-route origination destination G) ...)

(find-route 'C 'DGraph) = (list 'C 'D)

(find-route 'E 'DGraph) = (list 'E 'C 'D)

(find-route 'C 'GGraph) = false


Backtracking algorithmen

Backtracking-Algorithmen

Ein Backtracking-Algorithmus folgt einer bestimmten

Vorgehensweise:

  • Verfolge einen (möglichen) Lösungsweg, bis

    • die Lösung gefunden wurde (Erfolg!terminiere)

    • oder der Weg nicht fortgesetzt werden kann.

  • Wenn der Weg nicht fortgesetzt werden kann:

    • gehe den Weg zurück bis zur letzten Verzweigungsmöglichkeit, wo es noch nicht gewählte Alternativen gibt,

    • wähle dort eine noch nicht gewählte Alternative und mache weiter bei Schritt 1.

  • Wenn der Ausgangspunkt erreicht ist und es keine Alternativen mehr gibt: Misserfolg! terminiere

    Anwendungen:

    • N-Damen-Problem, Wege in Graphen finden


Graphen traversieren beispiel

C

D

B

A

E

F

G

Graphen traversieren - Beispiel

BACKTRACK !

Finde den Weg von Knoten A nach G!


Graphen traversieren2

Graphen traversieren

  • Ist der Startknoten gleich dem Zielknoten, ist das Problem trivial; die Lösung lautet (listdestination).

  • Ansonsten: versuche einen Weg von allen Nachbarknoten des Startknotens aus zu finden

(define (find-route originationdestinationaGraph)

(cond

[(symbol=? originationdestination)

(listdestination)]

[else ...

(find-route/list

(neighborsoriginationaGraph)

destination

aGraph)

...]))


Nachbarknoten

Nachbarknoten

neighbors ist der Funktion contains-doll? ähnlich

;; neighbors : node graph -> (listof node)

;; to lookup the node in graph

(define (neighbors node graph)

(cond

[(empty? graph)

(error 'neighbors "can't happen")]

[(symbol=? (first (first graph)) node)

(second (first graph))]

[else (neighbors node (rest graph))]))


Graphen traversieren3

Graphen traversieren

  • find-route/list

    • Verarbeitet eine Liste von Knoten

    • Ermittelt für jeden von ihnen, ob ein Weg zum Zielknoten in diesem Graphen existiert

;; find-route/list :

;; (listofnode) nodegraph -> (listofnode) orfalse

(define (find-route/listlo-origdestaGraph)

...)

  • Das Ergebnis von find-route hängt vom find-route/list Ergebnis ab, das eins der folgenden sein kann:

    • Ein Weg von einem der Nachbarknoten zum Zielknoten

    • false, wenn kein Weg von einem der Nachbarn aus gefunden werden konnte


Graphen traversieren4

Graphen traversieren

(define (find-route originationdestinationaGraph)

(cond

[(symbol=? originationdestination)

(listdestination)]

[else

(local

((definepossible-route

(find-route/list

(neighborsoriginationaGraph)

destination

aGraph)))

(cond

[(boolean? possible-route) ...]

[else (cons? possible-route) ...]))]))


Graphen traversieren5

Graphen traversieren

(define (find-route origination destination aGraph)

(cond

[(symbol=? origination destination)

(list destination)]

[else

(local ((define possible-route

(find-route/list

(neighbors origination aGraph)

destination

aGraph)))

(cond

[(boolean? possible-route) false]

[else (cons origination possible-route)]))]))


Graphen traversieren beispiel1

C

D

B

A

E

F

G

Graphen traversieren - Beispiel

Finde den Weg von Knoten A nach G!

Nachbarn von A


Graphen traversieren6

Graphen traversieren

B

C

D

B

C

D

(define (find-route/list lo-Os destaG)

(cond

[(empty? lo-Os) false]

[else

(local

((define possible-route

(find-route (first lo-Os) destaG)))

(cond

[(boolean? possible-route)

(find-route/list (rest lo-Os) destaG)]

[else possible-route])

)

])

)

A

A

E

F

G

E

F

G


Graphen traversieren7

Graphen traversieren

B

C

D

B, E, C ist ein Zyklus

A

E

F

G

Die Funktion terminiert nicht in einem Graph mit einem Zyklus:

(find-route 'B 'D Cyclic-graph)

= ... (find-route/list (list 'E 'F) 'D Cyclic-graph) ...

= ... (find-route 'E 'D Cyclic-graph) ...

= ... (find-route/list (list 'C 'F) 'D Cyclic-graph) ...

= ... (find-route 'C 'D Cyclic-graph) ...

= ... (find-route/list (list 'B 'D) 'D Cyclic-graph) ...

= ... (find-route 'B 'D Cyclic-graph) ...

= ...


Zusammenfassung

Zusammenfassung

  • Es gibt Probleme, die mit der strukturellen Rekursion nicht oder nicht optimal gelöst werden

  • Generative Rekursion basiert auf dem Prinzip „Teile und Herrsche“

  • Das Design Rezept muss für generativ rekursive Funktionen angepasst werden

    • Insbesondere muss ein Terminierungsargument mitgeliefert werden

  • Strukturell rekursive Funktionen sind eine Teilmenge der generativ rekursiven Funktionen

  • Falls beide Strategien möglich sind, muss die Auswahl fallbasiert getroffen werden

    • Man kann nicht sagen, eine Klasse ist besser als die andere


  • Login