Darstellung von Information

Download Report

Transcript Darstellung von Information

Algorithmen und ihre Eigenschaften
Klaus Becker
2012
2
Algorithmen und ihre Eigenschaften
3
Teil 1
Algorithmen - früher und heute
Fallstudie - Ägyptische Multiplikation
4
Fallstudie - Ägyptische Multiplikation
Algorithmen werden seit den Anfängen der
Mathematik beim Rechnen benutzt.
Im "Papyrus Rhind" wird beschrieben, wie in
Ägypten Zahlen multipliziert wurden.
Im Jahre 1858 kaufte der englische Archäologe A.H. Rhind
in Luxor ein aus zwei Stücken bestehendes Papyrus. Erst
einige Jahrzehnte später stellte sich heraus, dass das dritte,
fehlende Mittelstück sich in einem New Yorker Museum
befand. Zusammen hat das Dokument eine Länge von 5,25
m und eine Breite von 33 cm. Es wurde rund 1700 Jahre vor
Christi Geburt geschrieben und enthält viele
Mathematikaufgaben. Heute heißt dieses Schriftstück
Papyrus Rhind.
siehe:
http://buergernetz.muenster.de/mauritz//matheserver/teller
/aegypten/zahl2.html
5
Fallstudie - Ägyptische Multiplikation
Aufgaben:
(a) Versuche, anhand der Beispiele zu erschließen, wie Zahlen im alten Ägypten dargestellt
wurden.
(b) Welche Gemeinsamkeiten und welche Unterschiede gibt es zu unserer Zahldarstellung
heute?
(c) Hieroglyphenzahlen lassen sich gut schriftlich addieren und subtrahieren. Beschreibe, wie
man dabei vorgehen kann.
(d) Warum kann man unsere schriftliche Multiplikation nicht mit Hieroglyphenzahlen
nachbilden?
(e) Recht gut funktioniert das Verdoppeln und Halbieren von Hieroglyphenzahlen. Probiere das
selbst aus.
6
Fallstudie - Ägyptische Multiplikation
Aufgaben:
Finde heraus, wie die ägyptische Multiplikation funktioniert.
Berechne mit dem Verfahren die folgenden Produkte:
15 * 14 =
9 * 120 =
16 * 7 =
Überprüfe aber auch, ob die erzielten Ergebnisse stimmen.
7
Fallstudie - Ägyptische Multiplikation
 Man schreibt die beiden zu multiplizierenden Zahlen nebeneinander.
 Auf der linken Seite werden die Zahlen jeweils halbiert (Reste abgerundet) und die
Ergebnisse untereinander geschrieben, bis man zur 1 gelangt.
 Auf der rechten Seite werden die Zahlen verdoppelt und untereinander geschrieben.
 Die rechts stehenden (verdoppelten) Zahlen werden gestrichen, wenn die links stehende
Zahl gerade ist.
 Die Summe der nicht gestrichenen rechts stehenden Zahlen ergibt das gesuchte Produkt.
umgangssprachliche Beschreibung
Fallstudie - Ägyptische Multiplikation
8
13

6
12
12
Trace / Ablaufprotokoll
24
3

48
60
1

96
156
Bedingung
Anweisung
z1
z2
13
12
p = 0
z1 > 0
z1 ungerade
Algorithmus in Struktogrammform
24
3
48
60
1
96
(w)
(w)
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
z1 > 0
6
(w)
(w)
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
z1 > 0
z1 ungerade
12
(w)
(f)
z1 = z1 // 2
z2 = z2 * 2
z1 > 0
z1 ungerade
0
(w)
(w)
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
z1 > 0
z1 ungerade
p
(f)
156
0
192
9
Fallstudie - Ägyptische Multiplikation
Aufgaben:
Entwickle ein Python-Programm zum Algorithmus. Teste das Programm mit verschiedenen
Eingaben.
Fallstudie - Ägyptische Multiplikation
10
Bedingung
13 = 6*2+1
Anweisung
= (3*2+0)*2+1
z1 > 0
z1 ungerade
= (((0*2+1)*2+1)*2+0)*2+1
13
12
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
13 * 12 =
(1*2^3 + 1*2^2 + 0*2^1 + 1*2^0) * 12 =
8*12 + 4*12 + 0 + 1*12 =
z1 > 0
z1 ungerade
96 + 48 + 12 =
156
z1 > 0
z1 ungerade
12
12
6
24
3
48
(w)
(w)
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
1
60
p = p + z2
z1 = z1 // 2
z2 = z2 * 2
0
96
(w)
(w)
24
z1 > 0
0
(w)
(f)
z1 = z1 // 2
z2 = z2 * 2
z1 > 0
z1 ungerade
p
(w)
(w)
= 0*2*2*2*2 + 1*2*2*2 + 1*2*2 + 0*2 + 1
6
z2
p = 0
= ((1*2+1)*2+0)*2+1
13 
z1
156
192
(f)
3

48
1

96
Aufgabe:
156
Erkläre, warum der Algorithmus das Multiplikationsverfahren
korrekt beschreibt.
11
Fallstudie - Ägyptische Multiplikation
Obwohl das Multiplikationsverfahren der Ägypter heute kaum noch benutzt wird, hat der
Algorithmus und die dahinter steckende Idee nichts an ihrer Bedeutung verloren. Die Idee wird
heute beim "schnellen Potenzieren" benutzt.
Aufgabe:
In der freien Enzyklopädie Wikipedia findet man unter dem Stichwort "schnelles Potenzieren"
die folgende Verfahrensbeschreibung:
"Der Exponent wird schrittweise halbiert (das Ergebnis wird abgerundet) und die Basis
schrittweise quadriert. Man streicht die Zeilen mit geradem Exponenten. Das Produkt der
nichtgestrichenen rechten Zahlen ist die gesuchte Potenz."
Teste erst einmal dieses Verfahren zum schnellen Potenzieren. Entwickle anschließend ein
Struktogramm zur Beschreibung des Verfahrens. Du kannst dich am Algorithmus zur
ägyptischen Multiplikation orientieren.
12
Fallstudie - Ägyptische Multiplikation
Das Rechnen mit Zahlen ist eine bedeutende Kulturleistung der Menschheit, die gewaltige
Auswirkungen hat. Viele Bereiche unseres Lebens wären kaum noch oder gar nicht denkbar,
wenn sie nicht von Zahlen und Berechnungen mit diesen Zahlen begleitet wären.
Schon sehr früh hat man versucht, das Rechnen mit Zahlen zu automatisieren. So sind z.B.
unsere Verfahren zum schriftlichen Rechnen Verfahren, die man schematisch durchführen
kann, ohne sie im geringsten Maße verstanden zu haben. Diese Form der Automatisierung
ermöglicht es, sehr viele Berechnungen ohne Nachdenken schnell auszuführen.
Algorithmen wurden also schon entwickelt und benutzt, lange bevor es Computer gab. Zu
diesen algorithmischen Verfahren gehört auch das von den Ägyptern benutzte Verfahren zur
Multiplikation von Zahlen. Ohne algorithmische Rechenverfahren wäre es den Ägyptern wohl
kaum möglich gewesen, eine funktionierende Gesellschaft aufzubauen, die sogar in der Lage
war, riesige Pyramiden zu bauen.
13
Teil 2
Algorithmen - früher und heute
Fallstudie - PageRank
14
Fallstudie - PageRank
Wenn man im Internet nach Information sucht, dann
benutzt man sehr häufig eine Suchmaschine. Hier gibt man
den Suchbegriff ein - es können natürlich auch mehrere
sein, die Suchmaschine liefert dann die Adressen von
Webseiten zu diesem Suchbegriff.
Die hier benutzte Suchmaschine Ixquick hat (ungefähr)
2877 Suchergebnisse gefunden. Die ersten 10 dieser
Suchergebnisse werden in Kurzform angezeigt.
Beachte, dass es weit mehr als 2877 Webseiten gibt, auf
denen der Begriff "Algorithmus" vorkommt. So liefert die
Suchmaschine Google derzeit (ungefähr) 2.640.000
Suchergebnisse zu diesem Suchbegriff. Die Suchmaschine
Ixquick liefert also nur eine Auswahl von Webseiten zum
eingegebenen Suchbegriff. Hier ergibt sich das Problem,
nach welchen Kriterien Ixquick die relevanten Webseiten
auswählt.
Ein weiteres Problem ergibt sich bei der Präsentation der
Suchergebnisse. Wie sollen die Kurzbeschreibungen zu den
2877 gefundenen Webseiten angeordnet werden? Für den
Benutzer wäre es hilfreich, wenn wichtige Seiten zuerst
aufgelistet würden.
15
Fallstudie - PageRank
Die gesamte "Welt der verlinkten Webseiten" besteht aus sehr vielen Webseiten. Zur Lösung
des Ranking-Problems muss man (zum Glück) nicht diese Gesamtheit betrachten. Es reicht,
wenn man das Ranking-Problem für eine "kleine Welt" vernetzter Webseiten löst - im großen
funktioniert es dann genauso.
Aufgabe:
Schaue dir die Webseitenwelt in der Darstellung genauer an. Welche der dort gezeigten
Webseiten würdest du (ohne Berücksichtigung der Seiteninhalte) eine größere / geringere
Relevanz einräumen? Woran orientierst du dich bei der Einschätzung der Relevanz?
16
Fallstudie - PageRank
Modellierung des Surfverhaltens:
(A1) Zu Beginn verteilen sich alle
Besucher gleichmäßig auf die
Webseiten.
(A2) Alle Besucher folgen jeweils im
gleichen Takt einem Link auf eine
weitere Webseite. Wenn auf einer
Webseite mehrere Links vorkommen,
dann verteilen sich die Besucher
gleichmäßig auf die verschiedenen
Links.
(A3) Besucher, die in eine Sackgasse
geraten (d.h. Webseiten besuchen, die
keine Links auf weitere Seiten
enthalten), besuchen im nächsten
Schritt irgend eine der gegebenen
Webseiten. Sie teilen sich dabei
gleichmäßig auf alle zur Verfügung
stehenden Webseiten auf.
Aufgabe:
Wie viele Nutzer besuchen unter den veränderten
Annahmen nach einem Takt die verschiedenen
Webseiten?
17
Fallstudie - PageRank
Modellierung des Surfverhaltens:
(A1) Zu Beginn verteilen sich alle
Besucher gleichmäßig auf die Webseiten.
(A2) Alle Besucher folgen jeweils im
gleichen Takt einem Link auf eine weitere
Webseite. Wenn auf einer Webseite
mehrere Links vorkommen, dann
verteilen sich die Besucher gleichmäßig
auf die verschiedenen Links.
(A3) Besucher, die in eine Sackgasse
geraten (d.h. Webseiten besuchen, die
keine Links auf weitere Seiten enthalten),
besuchen im nächsten Schritt irgend eine
der gegebenen Webseiten. Sie teilen sich
dabei gleichmäßig auf alle zur Verfügung
stehenden Webseiten auf.
(A4) Ein bestimmter Prozentsatz der
Nutzer (z.B. 20%) springt in jedem Takt
zu einer beliebigen anderen Webseite.
Sie teilen sich dabei gleichmäßig auf alle
zur Verfügung stehenden Webseiten auf.
Aufgabe:
Erkläre, wie die in der Abbildung gezeigten
Zahlen gemäß Annahmen zustande kommen
18
Fallstudie - PageRank
Aufgaben:
(a) Führe die Berechnungen für
mehrere Takte durch. Benutze
(gerundete) Dezimalzahlen, wenn
die Divisionen nicht aufgehen - auch,
wenn das der Wirklichkeit nicht mehr
entspricht.
(b) Beschreibe die Berechnungen mit
einem Algorithmus.
19
Fallstudie - PageRank
# Simulation des Surfverhaltens
Aufgabe:
# Surf- und Sprunganteile
Implementiere und teste den PageRankp = 0.8
Verfahren.
q = 1-p
# Initialisierung
a = 300
...
b = 300
# wiederholte Berechnung der Besucherzahlen
c = 300
for i in range(10):
d = 300
# Bestimmung der neuen Besucherzahlen nach einen Takt
e = 300
a1 = (p*c)/3 + q*(a+b+c+d+e+f)/6 + (p*f)/6
f = 300
b1 = (p*a)/2 + p*e + q*(a+b+c+d+e+f)/6 + (p*f)/6
# Ausgabe
c1 = (p*a)/2 + (p*b)/2+ p*d + q*(a+b+c+d+e+f)/6 + (p*f)/6
...
d1 = (p*c)/3 + (p*b)/2 + q*(a+b+c+d+e+f)/6 + (p*f)/6
e1 = (p*0) + q*(a+b+c+d+e+f)/6 + (p*f)/6
f1 = (p*c)/3 + q*(a+b+c+d+e+f)/6 + (p*f)/6
a = a1
b = b1
c = c1
d = d1
e = e1
f = f1
# Ausgabe
...
20
Fallstudie - PageRank
# Simulation des Surfverhaltens
Aufgabe: Die Suchmaschine Google benutzt - in
# Surf- und Sprunganteile
einer Grundversion - das folgende
p = 0.8
Simulationsprogramm.
q = 1-p
# Initialisierung
n = 1000
...
a = n/6
# wiederholte Berechnung der Besucherzahlen
b = n/6
for i in range(10):
c = n/6
# Bestimmung der neuen Besucherzahlen nach einen Takt
d = n/6
a1 = (p*c)/3 +
(q*n)/6
e = n/6
b1 = (p*a)/2 + p*e +
(q*n)/6
f = n/6
c1 = (p*a)/2 + (p*b)/2+ p*d +
(q*n)/6
# Ausgabe
d1 = (p*c)/3 + (p*b)/2 +
(q*n)/6
...
e1 = (p*0) +
(q*n)/6
f1 = (p*c)/3 +
(q*n)/6
a = a1
Vergleiche die hier
b = b1
benutzte Modellierung
c = c1
des Surfverhaltens mit
d = d1
der oben entwickelten
e = e1
Modellierung.
f = f1
# Ausgabe
...
21
Fallstudie - PageRank
Viele Menschen nutzen das Internet (genauer: WWW),
wenn sie Information über ein bestimmtes Thema
suchen. Meist geben sie ein oder mehrere Stichwörter in
eine Suchmaschine ein - und schon kann es mit der
Informationsaufnahme losgehen.
Suchmaschinen finden oft eine riesige Anzahl von
Webseiten, die die eingegebenen Suchbegriffe enthalten.
Suchmaschinen nutzen dann eingebaute Strategien, um
diese Webseiten dem Nutzer zu präsentieren. Mit Hilfe
vorgegebener Algorithmen - zu denen auch das hier
entwickelte Verfahren gehört - werden die Webseiten mit
Rankingzahlen bewertet und dann entsprechend dieser
Rankingwerte nach ihrer Relevanz sortiert angezeigt. Das
ist sicher sinnvoll, hat aber auch Konsequenzen.
Viele Nutzer schauen sich die ersten Suchergebnisse
genauer an, die weiteren - so glaubt man - werden wohl
nicht viel Neues bringen. Das hat zur Folge, dass viele
Nutzer nur das finden, was von eingebauten RankingAlgorithmen für besonders relevant befunden wurde.
Ranking-Algorithmen steuern auf diese Weise die
Informationsaufnahme der Nutzer.
22
Fallstudie - PageRank
"Die perfekte Suchmaschine versteht genau das, was man meint, und liefert genau das,
wonach man sucht.« Das war die Vision von Larry Page, als er Google im Jahre 1998
mitgründete. Seither arbeiten die Kalifornier daran, diesem Ziel näher zu kommen.
Vor drei Jahren ist ihnen ein großer Schritt gelungen. Tippten bis dahin zwei Nutzer die
gleichen Wörter in Googles Suchmaske, bekamen diese dieselbe Antwort. Heute bekommt
jeder Suchende eine individuell auf ihn zugeschnittene Reaktion des Computers. Doch so
beginnt sich die Welt des Suchenden auf die beschauliche Sammlung seiner Vorlieben zu
verengen. Aus dem Tor ins World Wide Web wird ein Tor, das letztlich zu ihm selbst
zurückführt. In seinem Buch Filter Bubble kritisiert der Netzpublizist Eli Pariser, dass man sich
im Internet in vorgefilterten Blasen bewege: »Mehr und mehr wird dein Computermonitor zum
Spiegel, der deine eigenen Interessen reflektiert, während algorithmische Aufseher
beobachten, was du anklickst!«"
Quelle: http://www.zeit.de/2012/32/Zensur-Google-Internetsuche
23
Teil 3
Algorithmen - früher und heute
Fallstudie - Turnierplanung
24
Fallstudie - Turnierplanung
Zum alljährlichen Schulschachturnier haben sich angemeldet: Alina, Betül, Chris, Dominik,
Elisabeth und Florian. Gespielt wird wie jedes Jahr - jeder gegen jeden. Jedes Spiel dauert
maximal 15 Minuten.
Runde 1: A:F, B:D, C:E
Runde 2: A:E, B:F, C:D
Runde 3: A:D, B:E, C:F
...
Aufgaben:
(a) Ein Turnierplan muss her. Kannst du den gezeigten
Turnierplan fortsetzen? Welche Schwierigkeit tritt hier
auf?
(b) Schaffst du es, einen Turnierplan zu entwickeln, der
mit 5 Spielrunden auskommt?
Tipp: Bei der Entwicklung eines Turnierplans verliert man
leicht den Überblick, wer bereits gegen wen gespielt hat.
Hier hilft es, wenn man sich die Spielpaarungen
veranschaulicht, z.B. so: Die Spielpaarungen der 1.
Runde werden mit roten Verbindungslinien markiert, die
der 2. Runde mit gelben, die der 3. Runde mit grünen
usw..
25
Fallstudie - Turnierplanung
Kurz vor dem Turnier fragen Georg und
Hannah, ob sie nicht auch noch mitspielen
können. Der gesamte Turnierplan muss
jetzt schnell umgestrickt werden. Schaffst
du das?
Runde 1: H:A, G:B, F:C, E:D
Runde 2: H:B, A:C, G:D, F:E
Runde 3: H:C, ...
...
Aufgaben:
(a) Ergänze den dargestellten Turnierplan.
(b) Erkennst du hier bereits ein
"Planungsmuster"?
26
Fallstudie - Turnierplanung
Ordne A, B, ..., G zu einem 7-Eck an.
Setze H in die Mitte des 7-Ecks.
# Runde 1
Verbinde H mit A.
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
# Runde 2
Verbinde H mit B.
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
# Runde 3
Verbinde H mit C.
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
Verbinde die Ecken des 7-Ecks, die von
usw.
A aus in 1 Schritt erreichbar sind.
A aus in 2 Schritten erreichbar sind.
A aus in 3 Schritten erreichbar sind.
B aus in 1 Schritt erreichbar sind.
B aus in 2 Schritten erreichbar sind.
B aus in 3 Schritten erreichbar sind.
C aus in 1 Schritt erreichbar sind.
C aus in 2 Schritten erreichbar sind.
C aus in 3 Schritten erreichbar sind.
Aufgabe: Überprüfe zunächst die vorgegebene
Beschreibung. Wie muss sie fortgesetzt werden,
um Runde 4 zu erhalten?
27
Fallstudie - Turnierplanung
# Erzeugung eines Turnierplans mit n Teilnehmern
Ordne die Teilnehmer 0, 1, ..., (n-2) zu einem (n-1)-Eck an.
Setze den Teilnehmer n-1 in die Mitte des (n-1)-Ecks.
# Runde 1
Verbinde n-1 mit 0.
Verbinde die Ecken des (n-1)-Ecks, die von 0 aus in 1 Schritt erreichbar sind.
Verbinde die Ecken des (n-1)-Ecks, die von 0 aus in 2 Schritten erreichbar sind.
...
Verbinde die Ecken des (n-1)-Ecks, die von 0 aus in n/2-1 Schritten erreichbar sind.
# Runde 2
Verbinde n-1 mit 1.
Verbinde die Ecken des (n-1)-Ecks, die von 1 aus in 1 Schritt erreichbar sind.
Verbinde die Ecken des (n-1)-Ecks, die von 1 aus in 2 Schritten erreichbar sind.
...
Verbinde die Ecken des (n-1)-Ecks, die von 1 aus in n/2-1 Schritten erreichbar sind.
# Runde 3
Verbinde n-1 mit 2.
Verbinde die Ecken des (n-1)-Ecks, die von 2 aus in 1 Schritt erreichbar sind.
Verbinde die Ecken des (n-1)-Ecks, die von 2 aus in 2 Schritten erreichbar sind.
...
Verbinde die Ecken des (n-1)-Ecks, die von 2 aus in n/2-1 Schritten erreichbar sind.
# ...
...
Fallstudie - Turnierplanung
28
Runde 1:
7
0-1+7
|
|
0
0+1
0-2+7
|
0+2
0-3+7
|
0+3
Runde 2:
7
1-1
|
|
1
1+1
1-2+7
|
1+2
1-3+7
|
1+3
Runde 3:
7
2-1
|
|
2
2+1
2-2
|
2+2
2-3+7
|
2+3
Runde 4:
Aufgabe:
Runde 5:
Runde 6:
7
5-1
|
|
5
5+1
Runde 7:
Analysiere das Verfahren. Welche Muster kannst
du erkennen? Ergänze die noch fehlenden Runden.
5-2
|
5+2-7
5-3
|
5+3-7
Fallstudie - Turnierplanung
29
Runde 1:
7
0-1+7
|
|
0
0+1
0-2+7
|
0+2
0-3+7
|
0+3
Runde 2:
7
1-1
|
|
1
1+1
1-2+7
|
1+2
1-3+7
|
1+3
Runde 3:
7
2-1
|
|
2
2+1
2-2
|
2+2
2-3+7
|
2+3
Runde 4:
Aufgabe:
Runde 5:
Runde 6:
7
5-1
|
|
5
5+1
Runde 7:
# Erzeugung eines Turnierplans mit 8 Teilnehmern
Für i von 0 bis 6:
# Runde i+1
Ausgabe des Spielpaars: 7:i
Für j von 1 bis 3:
Setze a auf i-j.
Setze b auf i+j.
Wenn a < 0:
Erhöhe a um 7.
Wenn b > 6:
Verringere b um 7.
Ausgabe des Spielpaars: a:b
Erläutere die folgende Verfahrensbeschreibung anhand der
oben gezeigten "Berechnungen" für die einzelnen
Spielrunden.
5-2
|
5+2-7
5-3
|
5+3-7
Wie müsste man die Verfahrensbeschreibung abändern,
damit sie für n Teilnehmer funktioniert?
Fallstudie - Turnierplanung
30
Runde 1:
7
0-1+7
|
|
0
0+1
0-2+7
|
0+2
0-3+7
|
0+3
Runde 2:
7
1-1
|
|
1
1+1
1-2+7
|
1+2
1-3+7
|
1+3
Runde 3:
7
2-1
|
|
2
2+1
2-2
|
2+2
2-3+7
|
2+3
Runde 4:
Aufgabe:
Runde 5:
Runde 6:
7
5-1
|
|
5
5+1
Runde 7:
# Erzeugung eines Turnierplans mit 8 Teilnehmern
Für i von 0 bis 6:
# Runde i+1
Ausgabe des Spielpaars: 7:i
Für j von 1 bis 3:
Setze a auf i-j.
Setze b auf i+j.
Wenn a < 0:
Erhöhe a um 7.
Wenn b > 6:
Verringere b um 7.
Ausgabe des Spielpaars: a:b
Implementiere das verallgemeinerte Verfahren in Python.
5-2
|
5+2-7
5-3
|
5+3-7
31
Fallstudie - Turnierplanung
Turnierplanung spielt in etlichen Bereichen unseres Lebens eine Rolle, z.B. bei der Planung von
Sportveranstaltungen. So müssen die Spiele der Fußball-Bundesliga genau geplant werden,
damit ein so komplexes System bestehend aus Mannschaften, Zuschauern, Parkleitsystemen,
Polizeieinsätzen etc. funktioniert.
Bei der Planung der Fußball-Bundesliga-Begegnungen muss - zumindest vom Prinzip her dasselbe Problem gelöst werden wie beim Schulschachturnier: In 17 Spielrunden muss jede
der 18 Mannschaften gegen jede andere Mannschaft antreten. Beachte, dass die Planung des
Bundesligaturnier deutlich komplexer ist als die Planung des Schulschachturniers: Es wird eine
Hin- und eine Rückrunde so gespielt, dass jede Mannschaft einmal Heim- und einmal
Gastmannschaft ist. Nach Möglichkeiten sollten sich Heim- und Gastspiele abwechseln. An
manchen Spieltagen steht das Stadion durch eine andere Großveranstaltung nicht zur
Verfügung, usw..
32
Fallstudie - Turnierplanung
Früher wurde eine solch komplexe Turnierplanung "von Hand" gemacht - wobei die Köpfe der
Personen das Planungsteams die entscheidende Rolle gespielt haben. Turnierplanung war eine
anspruchsvolle geistige Tätigkeit, die viel Zeit in Anspruch genommen hat.
Heute kann eine komplexe Turnierplanung mit Hilfe geeigneter Algorithmen automatisiert
durchgeführt werden. Man gibt die Rahmenbedingungen in geeigneter Form vor, ein Rechner
ermittelt dann in kurzer Zeit mögliche Turnierabläufe.
Das Beispiel Turnierplanung zeigt, dass geistige Tätigkeiten heute zunehmend automatisiert
werden. Algorithmen spielen dabei eine entscheidende Rolle und bestimmen so zunehmend
große Teile unseres Lebens. Inwieweit das gut oder schlecht ist, musst du selbst beurteilen.
33
Teil 4
Algorithmusbegriff
34
Fallstudie - Robotersteuerung
Ein Roboter soll Ziegel transportieren. Die Ziegel sind (wie in der Abbildung zu sehen) alle auf
einem Feld aufeinder gestapelt. Der Roboter soll den gesamten Ziegeltum zwei Felder weiter in
Richtung Süden transportieren.
Wie könnte der Roboter das machen? Warum ist es schwierig, ein Verfahren zur
Robotersteuerung exakt zu beschreiben?
35
Fachkonzept - Algorithmus
Ein Algorithmus ist eine Verarbeitungsvorschrift, die so präzise formuliert ist, dass sie auch
von einer Maschine abgearbeitet werden kann.
36
Problemlöseverfahren - Version 1
Was
soll
ich
tun?
Gehe zum Ziegelturm.
Trage den Ziegelturm zwei
Felder weiter in Richtung
Süden.
Gehe zurück zur
Ausgangsposition.
Aufgabe:
Welche Schwierigkeit wird hier beschrieben?
37
Problemlöseverfahren - Version 2
Anweisungen:

um 90° nach rechts drehen (kurz: R)

um 90° nach links drehen (kurz: L)

einen Schritt vorwärts gehen (kurz: S)

einen Ziegel aufheben (kurz: A)

einen Ziegel hinlegen (kurz: H)
R,
A,
A,
A,
A,
L,
S,
L,
L,
L,
L,
S,
L,
S,
S,
S,
S,
R
S,
S,
S,
S,
R,
R,
R,
R,
H,
H,
H,
H,
R,
R,
R,
R,
S,
S,
S,
S,
S,
S,
S,
S,
L,
L,
L,
L,
Etwas
stimmt hier
nicht!
Klappt
wunderbar
!
Aufgabe:
Welche Schwierigkeit
wird hier beschrieben?
Problemlöseverfahren - Version 3
38
Anweisungen:

um 90° nach rechts drehen (kurz: R)

um 90° nach links drehen (kurz: L)

einen Schritt vorwärts gehen (kurz: S)

einen Ziegel aufheben (kurz: A)

einen Ziegel hinlegen (kurz: H)
Wie
geht es
hier
weiter?
R
S
L
L
S
R
Aufgabe:
Welche Schwierigkeit wird hier beschrieben?
L
S
S
R
A
H
L
S
S
R
39
Problemlöseverfahren - Version 4
Bedingungen:
So eine
lange
Vorschrift!
Aufgabe:
Welche Schwierigkeit wird hier beschrieben?

steht vor einem Ziegel (kurz: vZ)

...
R, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn ...:
...
sonst:
...
sonst:
L, S, R
sonst:
L, S, R
sonst:
L, S, R
40
Anforderungen an Algorithmen
Ein Algorithmus ist eine Verarbeitungsvorschrift, die so präzise formuliert ist, dass sie auch
von einer Maschine abgearbeitet werden kann.
drehe dich um 90° nach rechts
gehe einen Schritt vorwärts
drehe dich um 90° nach links
solange du vor einem Ziegel stehst, tue Folgendes:
hebe einen Ziegel auf
drehe dich um 90° nach links
gehe einen Schritt vorwärts
gehe einen Schritt vorwärts
drehe dich um 90° nach rechts
lege den Ziegel hin
drehe dich um 90° nach rechts
gehe einen Schritt vorwärts
gehe einen Schritt vorwärts
drehe dich um 90° nach links
drehe dich um 90° nach links
gehe einen Schritt vorwärts
drehe dich um 90° nach rechts
Kriterien:
 Ausführbarkeit,
d. h. der Prozessor muss die
Einzelschritte abarbeiten
können
 Eindeutigkeit,
d. h. die Abfolge der Schritte
ist eindeutig festgelegt
 Endlichkeit,
d. h. seine Beschreibung
besteht aus einem Text
endlicher Länge
 Allgemeinheit,
d. h. es wird eine ganze Klasse
von Problemen gelöst
41
Anforderung - Ausführbarkeit
Ausführbarkeit bedeutet, dass der "Prozessor" jeden Einzelschritt des Algorithmus ausführen
kann. Beachte, dass die Ausführbarkeit eines Algorithmus immer von den Möglichkeiten des
"Prozessors" abhängt.
Was
soll
ich
tun?
Gehe zum Ziegelturm.
Trage den Ziegelturm zwei
Felder weiter in Richtung
Süden.
Gehe zurück zur
Ausgangsposition.
Prozessor: Maschine, Person oder
auch gedachte Einheit, die den
Algorithmus ausführen soll
42
Anforderung - Eindeutigkeit
Eindeutigkeit bedeutet, dass die Abfolge der einzelnen Schritte genau festgelegt ist. Bei der
Abarbeitung der Anweisungen eines Algorithmus muss also immer genau feststehen, wie es
weitergeht. Hieraus ergibt sich, dass ein Algorithmus bei denselben Ausgangsdaten immer zum
selben Ergebnis kommt. Beachte, dass wir im Rahmen der theoretischen Informatik auch eine
Form der Mehrdeutigkeit bei Algorithmen zulassen.
Wie
geht es
hier
weiter?
R
S
L
L
S
R
L
S
S
R
A
H
L
S
S
R
43
Anforderung - Endlichkeit
Endlichkeit bedeutet, dass die Beschreibung aus einem Text endlicher Länge besteht. Die
Endlichkeit der Darstellung ist eigentlich eine Selbstverständlichkeit, da eine unendlich lange
Beschreibung in der Praxis nicht vorkommen kann.
So eine
lange
Vorschrift!
R, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn vZ dann:
A, L, S, S, R, H, R, S, S, L
wenn ...:
...
sonst:
...
sonst:
L, S, R
sonst:
L, S, R
sonst:
L, S, R
44
Anforderung - Allgemeinheit
Allgemeinheit bedeutet, dass nicht nur ein singuläres Problem, sondern eine ganze Klasse von
Problemen gelöst werden soll. Die Forderung nach der Allgemeinheit der Problemstellung lässt
man natürlich fallen, wenn man nur an der Lösung eines Einzelfalls interessiert ist.
Etwas
stimmt hier
nicht!
R,
A,
A,
A,
A,
L,
S,
L,
L,
L,
L,
S,
L,
S,
S,
S,
S,
R
S,
S,
S,
S,
R,
R,
R,
R,
H,
H,
H,
H,
R,
R,
R,
R,
S,
S,
S,
S,
S,
S,
S,
S,
L,
L,
L,
L,
45
Experimente mit Karol
Aufgabe:
(a) Im Fenster links unten kannst du dir die Anweisungen, Bedingungen und Kontrollstrukturen
anzeigen lassen, die man zur Steuerung von Karol verwenden kann. Benutze diese
Informationen, um ein Steuerungsverfahren exakt zu formulieren. Der Anfang eines möglichen
Steuerungsverfahrens ist im Fenster links oben zu sehen.
(b) Teste dein Steuerungsverfahren mit verschiedenen Ziegeltürmen. Dann siehst du direkt, ob
das Verfahren korrekt ist.
(c) Wenn das Steuerungsverfahren fertig formuliert ist, dann benutze den Menupunkt
[Struktogramm], um das Verfahren grafisch in Form eines Struktogramms darzustellen. Wie
"liest" man ein solches Struktogramm?
46
Experimente mit Karol
Aufgabe:
Der Roboter soll alle Ziegel, die auf dem Weg zur nächsten Wand liegen, einsammeln und
anschließend zurück zur Ausgangsposition laufen. Wir setzen hier voraus, dass Ziegel immer
nur einzeln (also nicht aufeinanderliegend) vorkommen.
Entwickle einen geeigneten Algorithmus.
47
Bausteine von Algorithmen
Problem:
Der Roboter soll alle Ziegel, die auf dem Weg zur nächsten Wand liegen, einsammeln und
anschließend zurück zur Ausgangsposition laufen. Wir setzen hier voraus, dass Ziegel immer
nur einzeln (also nicht aufeinanderliegend) vorkommen.
solange NichtIstWand tue
wenn IstZiegel dann
Aufheben
Schritt
sonst
Schritt
*wenn
*solange
RechtsDrehen
RechtsDrehen
solange NichtIstWand tue
Schritt
*solange
RechtsDrehen
RechtsDrehen
48
Bausteine von Algorithmen
Elementaranweisungen sind Anweisungen, die als Basisaktionen des Prozessors angesehen
werden können.
Kontrollanweisungen sind Anweisungen, deren Aufgabe es ist, die Ablauflogik festzulegen.
Hierzu gehören Anweisungen zur Beschreibung von Wiederholungen, Fallunterscheidungen und
zur Sequenzbildung.
solange NichtIstWand tue
wenn IstZiegel dann
Aufheben
Schritt
sonst
Schritt
*wenn
*solange
RechtsDrehen
RechtsDrehen
solange NichtIstWand tue
Schritt
*solange
RechtsDrehen
RechtsDrehen
49
Darstellung von Algorithmen
Umgangssprachlich formulierte Algorithmen versuchen, die Idee eines Algorithmus zu
beschreiben, ohne strenge Formalien in der Darstellung zu beachten.
Solange die Wand noch
nicht erreicht ist, tue
Folgendes:
Wenn ein Ziegel im Weg
liegt,
dann hebe ihn auf und
gehen einen Schritt
weiter.
Ansonsten gehe direkt
einen Schritt weiter.
Drehe dich um 180° Grad.
Solange die Wand noch
nicht erreicht ist, gehe
einen Schritt weiter.
Drehe dich um 180° Grad.
50
Darstellung von Algorithmen
Algorithmen, die in einer Programmiersprache verfasst sind, können direkt getestet werden
(sofern ein Ausführsystem für die Programmiersprache bereitsteht).
solange NichtIstWand tue
wenn IstZiegel dann
Aufheben
Schritt
sonst
Schritt
*wenn
*solange
RechtsDrehen
RechtsDrehen
solange NichtIstWand tue
Schritt
*solange
RechtsDrehen
RechtsDrehen
51
Darstellung von Algorithmen
Struktogramme benutzt man, um den strukturellen Aufbau eines Algorithmus deutlich zu
machen. Hier ist insbesondere die Schachtelung der Kontrollstrukturen zur Ablaufmodellierung
besonders gut zu erkennen.
52
Darstellung von Algorithmen
Flussdiagramme eigen sich sehr gut,
um den Ablauf bei Wiederholungen
und Fallunterscheidungen zu
veranschaulichen.
53
Algorithmen im Alltag
ZUTATEN für 5 Portionen:
650g Erdbeeren
150g Zucker
2 Pk Vanillezucker
5 EL Weinbrand
400 ml Sahne (gut gekühlt)
Rezept
ZUBEREITUNG
Erdbeeren kalt abbrausen, abtropfen lassen und trocken
tupfen. Blütenansatz entfernen. 150 Gramm der Früchte
zugedeckt beiseite stellen.
Restliche Erdbeeren in Stücke schneiden. Zucker,
Vanillezucker und Weinbrand darunterheben und alles 30
Minuten zugedeckt ziehen lassen. Dann mit dem Mixstab
fein pürieren. Die Hälfte der Sahne steif schlagen und
unter das Püree ziehen. Die Creme im Gefrierfach oder in
der Tiefkühltruhe gefrieren lassen.
Restliche Sahne halbsteif schlagen. Mit einem Esslöffel
Nocken von der Mousse abstechen und auf Dessertteller
verteilen. Die halbsteife Sahne angießen und das Dessert
mit den ganzen Erdbeeren garnieren.
Bedienungsanleitung
Quelle: www.daskochrezept.de
Auch im Alltag gibt es Verfahrensbeschreibungen, die algorithmische Züge aufweisen. Die
Anforderungen an den "Prozessor" sind aber in der Regel nicht so hoch wie bei Algorithmen in
der Informatik.
54
Al-Khwarizmi
Die Bezeichnung „Algorithmus“ leitet sich aus
dem Namen „Al-Khwarizmi“ – einem arabischen
Mathematiker – ab.
Abu Abd Allah Mohammed Ibn Musa Al-Khwarizmi lebte etwa von 780 bis 850 n. Chr. Er
stammte aus Choresm (arab. Khwarizmi), eine Gegend südlich des Aralsees, die heute Teil
von Usbekistan und Turkmenistan ist. Für seinen Namen sind mehrere Schreibweisen
gebräuchlich, z.B. Alhwarizmi, Al-Hwarizmi, al-Khowarizmi oder auch Mohammed ben Musa.
Al-Khwarizmi beschäftigte sich u. a. mit Verfahren zur Lösung von Gleichungen. Er verfasste
Bücher, die sich mit Algebra, Astronomie und Geographie beschäftigten, sowie Werke über
indische Ziffern und den Jüdischen Kalender.
55
Teil 2
Korrektheit von Algorithmen
56
Wechselwegnahme
Auf dem Tisch liegen zwei Reihen von Streichhölzern. Von der jeweils längeren Reihe sollen
so viele weggenommen werden, wie in der kürzeren vorkommen. Aufgehört wird, wenn
beide Streichholzreihen gleich lang sind.
Aufgaben:
Führe den Algorithmus mit
verschiedenen Ausgangszahlen /
Streichholzreihen durch und notiere die
jeweiligen Ausgaben.
 x = 15 ; y = 7
 x = 10; y = 21
 x = 3; y = 20
Was leistet der Algorithmus? Wie hängen
die Ausgaben von den Eingaben ab?
Ändert sich etwas am Verfahren, wenn
man es wie unten beschreibt?
57
Spezifikation
Das Verhalten eines Algorithmus lässt sich mit einer Spezifikation präzise beschreiben. Die
Spezifikation besteht aus einer Vorbedingung, die den Ausgangszustand beschreibt, sowie
einer Nachbedingung, die den Endzustand beschreibt.
Vorbedingung
vorher:
{ x = a (nat. Zahl) und y = b (nat. Zahl) }
nachher:
{ x = y = ggT(a, b) }
Nachbedingung
58
Korrektheit
Ein Algorithmus heißt terminierend bzgl. einer Spezifikation, wenn er bei jedem
Ausgangszustand, der die Vorbedingung erfüllt, nach endlich vielen Verarbeitungsschritten zu
einem Ende kommt.
Ein Algorithmus heißt (total) korrekt bzgl. einer Spezifikation, wenn er terminierend ist und
jeden Ausgangszustand, der die Vorbedingung erfüllt, in einen Endzustand überführt, der die
Nachbedingung erfüllt.
vorher:
{ x = a (nat. Zahl) und y = b (nat. Zahl) }
vorher:
{ x = a (nat. Zahl) und y = b (nat. Zahl) }
korrekt
nicht
terminierend
nachher:
{ x = y = ggT(a, b) }
nachher:
{ x = y = ggT(a, b) }
59
Korrektheitsnachweis über Testen
Beim Testen eines Algorithmus wird der Algorithmus bei bestimmten vorgegebenen Testdaten
ausgeführt und dabei überprüft, ob er in diesen Fällen das gewünschte Verhalten zeigt. Mit
dieser Methode kann man das Vorhandensein von Fehlern entdecken. Man kann aber in der
Regel nicht nachweisen, dass der Algorithmus korrekt bzgl. der gegebenen Spezifikation ist.
vorher:
{ x = a (nat. Zahl) und y = b (nat. Zahl) }
vorher:
{ x = a (nat. Zahl) und y = b (nat. Zahl) }
x = 8; y = 8:
nicht terminierend
x = 15; y = 7: ok
x = 8; y = 8:
ok
...
nachher:
{ x = y = ggT(a, b) }
nachher:
{ x = y = ggT(a, b) }
60
Teststrategien
Testdaten sollten immer sorgfältig ausgewählt werden. Man sollte sowohl typische als auch
untypische Eingabewerte betrachten. Besondere Aufmerksamkeit ist auf Sonderfälle und
Grenzwerte zu richten. Unter letzteren versteht man Werte, die gerade noch als Eingabewerte
zugelassen sind (z. B. größter und kleinster Wert, leerer Text, leere Eingabe usw.). Oft ist es
auch günstig, zufällig erzeugte Testdaten zu verwenden.
Bei der Durchführung von Tests sollte man vorher notieren, welche Ausgabe das Programm
laut Spezifikation liefern soll. Danach überprüft man, ob der Algorithmus tatsächlich dieses
Verhalten zeigt. In einem Exkurs zur Testausführung mit Python zeigen wir, wie solche
Testfälle in lauffähige Implementierungen von Algorithmen integriert werden können.
61
Testen mit Python
Es gibt verschiedene Möglichkeiten, einen Algorithmus in Python zu testen.
# Implementierung des Algorithmus
Wechselwegnahme
def ggt(x, y):
while x != y:
if x > y:
x=x-y
else:
y=y-x
return x
>>>
ggt(44, 12) = 4
ggt(7, 13) = 1
ggt(4, 4) = 4
ggt(1, 6) = 1
ggt(6, 18) = 6
Testergebnisse
# Test
print("ggt(44, 12) = ", ggt(44, 12))
print("ggt(7, 13) = ", ggt(7, 13))
print("ggt(4, 4) = ", ggt(4, 4))
print("ggt(1, 6) = ", ggt(1, 6))
print("ggt(6, 18) = ", ggt(6, 18))
Testfälle
Testen mit Python
62
Es gibt verschiedene Möglichkeiten, einen Algorithmus in Python zu testen.
def ggt(x, y):
""" groesster gemeinsamer Teiler
>>> ggt(44, 12)
4
>>> ggt(7, 13)
1
>>> ggt(4, 4)
4
"""
while x != y:
if x > y:
x=x-y
else:
y=y-x
return x
vorher festgelegte
Testfälle mit erwarteten
Ergebnissen
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
>>>
Trying:
ggt(44, 12)
Expecting:
4
ok
Trying:
ggt(7, 13)
Expecting:
von Python
1
erzeugtes
ok
Testprotokoll
Trying:
ggt(4, 4)
...
1 items had no tests:
__main__
1 items passed all tests:
3 tests in __main__.ggt
3 tests in 2 items.
3 passed and 0 failed.
Test passed.
63
Exkurs: Verifikation von Algorithmen
Behauptung:
Der Wechselwegnahme-Algorithmus ist korrekt bzgl. der
angegebenen Spezifikation.
Beweis:
Wir zeigen zunächst, dass die Bedingung {ggT(x, y) = ggT(a, b)}
vor dem ersten und nach jedem Schleifendurchlauf erfüllt ist.
Vor dem ersten Schleifendurchlauf gilt selbstverständlich diese
Bedingung, da hier x = a und y = b gilt.
Als nächstes zeigen wir, dass die genannte Bedingung nach einem
Schleifendurchlauf noch gilt, sofern sie vorher bereits erfüllt war.
Wir nehmen also an, dass die Bedingung ggT(x, y) = ggT(a, b)
vor der Ausführung der Anweisungen der Schleife gilt. Die Werte
der Variablen x und y nach der Ausführung der Schleife
bezeichnen wir mit x' und y'. Es gilt x' = x - y und y' = y oder x' =
x und y' = y - x. Jetzt nutzen wir eine allgemeine Eigenschaft des
ggT aus: Für beliebige natürliche Zahlen m und n mit m > n gilt:
ggT(m, n) = ggT(m-n, n). Diese Eigenschaft kann man leicht
mathematisch beweisen. Aus ihr folgt, dass in jedem Fall ggT(x',
y') = ggT(x, y) gelten muss. Da ggT(x, y) = ggT(a, b)
vorausgesetzt war, folgt, dass ggT(x', y') = ggT(a, b) gilt.
Zusatzüberlegung:
Für m > n gilt:
Wenn a | m und a | n,
dann a | (m-n).
Wenn a | (m-n) und
a | n, dann a | m.
Hieraus folgt:
ggT(m, n) =
ggT(m-n, n).
64
Exkurs: Verifikation von Algorithmen
Fortsetzung des Beweises:
Kommt es zum Verlassen der Schleife, so gilt einerseits
ggT(x, y) = ggT(a, b), da diese Bedingung vor dem ersten
Schleifendurchlauf gilt und wie gezeigt nach jedem weiteren
Durchlauf. Andererseits gilt auch x = y, da nur bei dieser
Bedingung die Schleife verlassen wird. Da der ggT bei zwei
gleichen Zahlen mit dieser Zahl übereinstimmt, muss also
ggT(a, b) = ggT(x, y) = x = y gelten.
Hiermit ist gezeigt, dass die Nachbedingung erfüllt ist, sofern die
Vorbedingung gilt und der Algorithmus bei den gegebenen Daten
terminiert. Zuletzt muss jetzt nur noch gezeigt werden, dass der
Algorithmus bei sämtlichen möglichen Eingabedaten tatsächlich
terminiert.
Dies kann man sich aber schnell klar machen. Man beginnt mit
zwei natürlichen Zahlen x = a und y = b. In jedem
Schleifendurchlauf wird eine der beiden Zahlen verkleinert. Man
kann nicht unendlich oft eine der beiden Zahlen verkleinern, so
dass beide größer als Null und auch verschieden bleiben.
65
Teil 3
Effizienz von Algorithmen
66
ggT-Berechnung
Der ggT von x = 3642431875 und y = 15 soll berechnet werden.
Aufgaben:
Würde man hier wirklich den
Wechselwegnahme-Algorithmus
ausführen? Was spricht dagegen?
Wie könnte man effizienter vorgehen?
Bedenken Sie, mit welcher
Rechenoperation man wiederholte
Subtraktionen schneller ausführen kann.
Entwickeln Sie einen geeigneten
Algorithmus.
67
Effizienz
Der ggT von x = 3642431875 und y = 15 soll berechnet werden.
x = 3642431875; y = 15
x = 3642431875; y = 15
x = 3642431860; y = 15
x = 15; y = 5
x = 3642431845; y = 15
x = 5; y = 0
...
x = 5; y = 5
äquivalent
effizienter
68
Effizienz
Zwei Algorithmen heißen äquivalent, wenn sie bei gleichen Ausgangszuständen jeweils gleiche
Endzustände erzeugen. Von zwei äquivalenten Algorithmen heißt der effizienter, der mit
weniger Ressourcen (d. h. Rechenzeit oder Speicherplatz) auskommt.
äquivalent
effizienter
69
Laufzeitmessung mit Python
Es gibt verschiedene Möglichkeiten, den Aufwand eines Algorithmus in Python zu messen.
# Deklaration
def ggt(x, y):
while x != y:
if x > y:
x=x-y
else:
y=y-x
return x
# Test mit Laufzeitmessung
from time import *
t1 = clock()
z = ggt(3642431875, 15)
t2 = clock()
t = t2 - t1
print("ggt(3642431875, 15) = ", z)
print("Rechenzeit: ", t=
>>>
ggt(3642431875, 15) = 5
Rechenzeit: 160.503182108
"interne Uhr"
70
Laufzeitmessung mit Python
Aufgabe:
(a) Probiere das selbst aus. Bestimme entsprechend die Rechenzeit für a = 44 und b = 8
beim Euklidischen Algorithmus.
(b) Bestimme die Rechenzeiten bei beiden Algorithmen für a = 3642431875 und b = 15.
Kannst du erklären, warum es hier zu einem so großen Unterschied kommt?
71
Aktionen zählen mit Python
Es gibt verschiedene Möglichkeiten, den Aufwand eines Algorithmus in Python zu messen.
def ggt(x, y):
z=0
while x != y:
z=z+1
if x > y:
x=x-y
else:
y=y-x
return x, z
Zähler für
Schleifendurchläufe
if __name__ == "__main__":
zahl1 = 3642431875
zahl2 = 15
(ergebnis, anzahl) = ggt(zahl1, zahl2)
print("Zahl 1: ", zahl1, "Zahl 2: ", zahl2, "ggt: ", ergebnis)
print("Schleifendurchlaeufe: ", anzahl)
>>>
Zahl 1: 3642431875 Zahl 2: 15 ggt: 5
Schleifendurchlaeufe: 242828793
Ausgabe der Ergebnisse
72
Aktionen zählen mit Python
Aufgabe:
(a) Probiere das selbst aus. Bestimme entsprechend die Anzahl der Schleifendurchläufe für a
= 44 und b = 8 beim Euklidischen Algorithmus.
(b) Bestimme die Anzahl der Schleifendurchläufe bei beiden Algorithmen für a = 3642431875
und b = 15. Kannst du erklären, warum es hier zu einem so großen Unterschied kommt?
73
Teil 5
Rekursive Algorithmen
74
Türme von Hanoi
Einer Geschichte zufolge soll im Tempel zu Benares - das ist eine "heilige Stadt" in Indien - ein
Turm aus 64 goldenen, der Größe nach geordneten Scheiben stehen. Die Mönche des Tempels
erhalten die Aufgabe, die Scheiben an einen anderen Ort zu bringen. Dabei müssen sie einige
Regeln beachten: Es darf immer nur eine Scheibe transportiert werden. Scheiben können auf
einem (einzigen) Hilfsstapel zwischenzeitlich abgelegt werden. Auch auf dem (teilweise
abgebauten) Ausgangsturm können Scheiben zwischenzeitlich abgelegt werden. Es darf aber
nie eine größere Scheibe auf eine kleinere gelegt werden. Wenn der neue Turm fertig ist, dann
ist das Ende der Zeit erreicht.
75
Türme von Hanoi
Aufgabe: Versuche, einen Turm mit 5 Scheiben nach den vorgegebenen Regeln umzustapeln.
Wenn das nicht klappt, dann versuche erst einmal, Türme mit 3 bzw. 4 Scheiben umzustapeln.
Ausgangszustand
Zielzustand
Benutze hierzu Münzen unterschiedlicher Größe oder ein Simulationsprogramm.
z. B.: http://www.mpg-trier.de/d7/prog/hanoi/hanoi.htm
76
Türme von Hanoi
Aufgabe: Überlege dir auch eine Strategie, mit der man Türme mit 6, 7, ... Scheiben umstapeln
kann.
Ausgangszustand
Zielzustand
77
Lösungsidee
transportiere einen 5-Scheiben-Turm von A über B nach C
Ausgangszustand
transportiere einen 4-Scheiben-Turm von A über C nach B
Zwischenzustand
transportiere eine Scheibe von A nach C
Zwischenzustand
transportiere einen 4-Scheiben-Turm von B über A nach C
Zielzustand
78
Verallgemeinerung
transportiere einen n-Scheiben-Turm von X über Y nach Z
Ausgangszustand
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
Zwischenzustand
transportiere eine Scheibe von X nach Z
Zwischenzustand
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
Zielzustand
Algorithmus
79
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
Rekursive Problemreduktion
80
Rekursive Problemreduktion ist eine Problemlösestrategie, bei der ein Problem auf ein
strukturgleiches Problem (in verkleinerter Form) zurückgeführt wird.
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
Ein rekursiver Algorithmus ruft sich (eventuell über Umwege) selbst auf und nutzt sich so
selbst zur Beschreibung der Lösung des gegebenen Problems.
Um Rekursion als Problemlösestrategie nutzen zu können, benötigt man ein Ausführsystem,
das in der Lage ist, rekursive Algorithmen wiederholt aufzurufen und auf diese Weise die
eigentliche Lösung zu generieren.
81
Ausführung des Algorithmus
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
transportiere einen 3-Scheiben-Turm von A über B nach C:
transportiere einen 2-Scheiben-Turm von A über C nach B
transportiere eine Scheibe von A nach C
transportiere einen 2-Scheiben-Turm von B über A nach C
Ausführungstiefe: 1
82
Ausführung des Algorithmus
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
transportiere einen 3-Scheiben-Turm von A über B nach C:
transportiere einen 2-Scheiben-Turm von A über C nach B:
transportiere einen 1-Scheiben-Turm von A über B nach C
transportiere eine Scheibe von A nach B
transportiere einen 1-Scheiben-Turm von C über A nach B
transportiere eine Scheibe von A nach C
transportiere einen 2-Scheiben-Turm von B über A nach C:
transportiere einen 1-Scheiben-Turm von B über C nach A
transportiere eine Scheibe von B nach C
transportiere einen 1-Scheiben-Turm von A über B nach C
Ausführungstiefe: 2
83
Ausführung des Algorithmus
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
transportiere einen 3-Scheiben-Turm von A über B nach C:
transportiere einen 2-Scheiben-Turm von A über C nach B:
transportiere einen 1-Scheiben-Turm von A über B nach C:
transportiere eine Scheibe von A nach C
transportiere eine Scheibe von A nach B
transportiere einen 1-Scheiben-Turm von C über A nach B:
transportiere eine Scheibe von C nach B
transportiere eine Scheibe von A nach C
transportiere einen 2-Scheiben-Turm von B über A nach C:
transportiere einen 1-Scheiben-Turm von B über C nach A:
transportiere eine Scheibe von B nach A
transportiere eine Scheibe von B nach C
transportiere einen 1-Scheiben-Turm von A über B nach C:
transportiere eine Scheibe von A nach C
Ausführungstiefe: 3
84
Ausführung des Algorithmus
transportiere einen 3-Scheiben-Turm von A über B nach C:
transportiere einen 2-Scheiben-Turm von A über C nach B:
transportiere einen 1-Scheiben-Turm von A über B nach C:
transportiere eine Scheibe von A nach C
transportiere eine Scheibe von A nach B
transportiere einen 1-Scheiben-Turm von C über A nach B:
transportiere eine Scheibe von C nach B
transportiere eine Scheibe von A nach C
transportiere einen 2-Scheiben-Turm von B über A nach C:
transportiere einen 1-Scheiben-Turm von B über C nach A:
transportiere eine Scheibe von B nach A
transportiere eine Scheibe von B nach C
transportiere einen 1-Scheiben-Turm von A über B nach C:
transportiere eine Scheibe von A nach C
Basisaktionen
85
Implementierung in Python
Algorithmus: transportiere einen n-Scheiben-Turm von X über Y nach Z
wenn n > 1:
transportiere einen (n-1)-Scheiben-Turm von X über Z nach Y
transportiere eine Scheibe von X nach Z
transportiere einen (n-1)-Scheiben-Turm von Y über X nach Z
sonst:
transportiere eine Scheibe von X nach Z
def transportiereTurm(n, x, y, z):
if n > 1:
transportiereTurm(n-1, x, z, y)
print("transportiere eine Scheibe von ", x, " nach ", z)
transportiereTurm(n-1, y, x, z)
else:
print("transportiere eine Scheibe von ", x, " nach ", z)
Algorithmus
Python-Programm
Aufgabe:
Teste die Implementierung des Algorithmus "Türme von Hanoi" mit verschiedenen n-Werten.
86
Implementierung in Python
Aufgabe:
Die Prozedur aus Aufgabe 1 ist um eine print-Anweisung erweitert worden. Kannst du ohne es
auspobiert zu haben vorhersagen, welche Ausgaben die Prozedur beim Aufruf
transportiereTurm(3, 'A', 'B', 'C') auf dem Bildschirm macht? Überprüfe dein Ergebnis.
def transportiereTurm(n, x, y, z):
print("transportiere einen ", n, " -Scheiben-Turm von ", x, " nach ", z)
if n > 1:
transportiereTurm(n-1, x, z, y)
print("transportiere eine Scheibe von ", x, " nach ", z)
transportiereTurm(n-1, y, x, z)
else:
print("transportiere eine Scheibe von ", x, " nach ", z)
87
Teil 6
Fallstudie - Selbstähnliche Figuren
88
Einstieg - Selbstähnliche Figur
Eine Figur ist selbstähnlich, wenn sie sich in Teile zerlegen lässt, die zur ihr ähnlich sind.
89
Einstieg - Selbstähnliche Figur
Eine Figur ist selbstähnlich, wenn sie sich in Teile zerlegen lässt, die zur ihr ähnlich sind.
zeichne_Baum(200):
gehe_vorwaerts(200)
drehe_dich_nach_rechts(45)
zeichne_Baum(100)
drehe_dich_nach_links(90)
zeichne_Baum(100)
drehe_dich_nach_rechts(45)
gehe_rueckwaerts(200)
rekursive
Problemreduktion
ALG zeichne_Baum(x):
wenn x >= 2:
gehe_vorwaerts(x)
drehe_dich_nach_rechts(45)
zeichne_Baum(x/2)
drehe_dich_nach_links(90)
zeichne_Baum(x/2)
drehe_dich_nach_rechts(45)
gehe_rueckwaerts(x)
rekursiver
Algorithmus
Exkurs - Turtle-Grafik
90
Turtle-Grafik basiert auf der Vorstellung, dass eine Schildkröte mit bestimmten Anweisungen
auf einer Zeichenfläche bewegt wird und dass die Schildkröte dabei eine Spur hinterlässt.
vorwaerts(100)
Turtle-Befehle
zeichne_Quadrat(laenge):
wiederhole 4 mal:
gehe_vorwaerts(laenge)
drehe_dich_nach_links(90)
Turtle-Algorithmus
 stift_hoch
 stift_runter
 gehe_vorwaerts(betrag)
 gehe_rueckwaerts(betrag)
 drehe_dich_nach_links(winkel)
 drehe_dich_nach_rechts(winkel)
 gehe_zu_punkt(punkt)
...
91
Exkurs - Turtle-Grafik in Python
Turtle-Grafik basiert auf der Vorstellung, dass eine Schildkröte mit bestimmten Anweisungen
auf einer Zeichenfläche bewegt wird und dass die Schildkröte dabei eine Spur hinterlässt.
zeichne_Quadrat(laenge):
wiederhole 4 mal:
gehe_vorwaerts(laenge)
drehe_dich_nach_links(90)
 stift_hoch
 stift_runter
 gehe_vorwaerts(betrag)
 gehe_rueckwaerts(betrag)
 drehe_dich_nach_links(winkel)
 drehe_dich_nach_rechts(winkel)
 gehe_zu_punkt(punkt)
...
Turtle-Programm
from turtle import *
# Deklaration einer
Zeichenprozedur
def quadrat(laenge):
for i in range(4):
t.forward(laenge)
t.left(90)
# Erzeugung eines Turtle-Objekts
t = Turtle()
# Test der Zeichenprozedur
quadrat(100)
Turtle-Klasse
t.forward(100)
>>>
>>>
>>>
>>>
from turtle import *
t = Turtle()
t.forward(100)
bye()
92
Exkurs - Turtle-Grafik in Python
from turtle import *
# Deklaration einer
Zeichenprozedur
def baum(stamm):
if stamm >= 2:
t.forward(stamm)
t.right(45)
baum(stamm/2)
t.left(90)
baum(stamm/2)
t.right(45)
t.backward(stamm)
# Erzeugung eines Turtle-Objekts
t = Turtle()
# Test der Zeichenprozedur
t.left(90)
baum(200)
ALG zeichne_Baum(x):
wenn x >= 2:
gehe_vorwaerts(x)
drehe_dich_nach_rechts(45)
zeichne_Baum(x/2)
drehe_dich_nach_links(90)
zeichne_Baum(x/2)
drehe_dich_nach_rechts(45)
gehe_rueckwaerts(x)
93
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
94
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
95
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
96
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
97
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
98
Übungen
Wählen Sie eine der folgenden selbstähnlichen Figuren aus. Entwickeln Sie mit Hilfe einer
rekursive Problemreduktion einen rekursiven Algorithmus zum Zeichnen der Figur. Testen Sie
den Algorithmus mit einer Python-Implementierung.
99
Teil 6
Übungen - Rekursive Verarbeitung von Listen
100
Einstieg - Geschachtelte Listen
Eine Gästeliste soll mit einem Programm verwaltet und verarbeitet werden.
gaeste = ["Ursula", "Winfried", "Ulrike", "Klaus", ...]
def ausgabe(liste):
i=0
while i < len(liste):
element = liste[i]
print(element)
i=i+1
iterativ
# Test
ausgabe(gaeste)
def ausgabe(liste):
if len(liste) == 0:
pass
else:
erstesElement = liste[0]
restListe = liste[1:]
print(erstesElement)
ausgabe(restListe)
rekursiv
101
Einstieg - Geschachtelte Listen
Eine Gästeliste soll mit einem Programm verwaltet und verarbeitet werden.
gaeste = [
["Ursula", "Winfried"],
["Ulrike", "Klaus"],
["Christiane", "Tim"],
["Andreas"],
["Ulrike", "Peter", ["Kea", "Lena", "Paula"]],
...
]
?
iterativ
# Test
ausgabe(gaeste)
def ausgabe(liste):
if len(liste) == 0:
pass
else:
erstesElement = liste[0]
restListe = liste[1:]
if type(erstesElement) == list:
ausgabe(erstesElement)
else:
print(erstesElement)
ausgabe(restListe)
rekursiv
102
Einstieg - Geschachtelte Listen
ausgabe([["Ursula", "Winfried"], ["Ulrike", "Klaus"], ["Christiane", "Tim"], ...])
ausgabe(["Ursula", "Winfried"])
print("Ursula")
ausgabe(["Winfried"])
print("Winfried")
ausgabe([])
pass
ausgabe([["Ulrike", "Klaus"], ["Christiane", "Tim"], ...]
ausgabe(["Ulrike", "Klaus"])
print("Ulrike")
ausgabe(["Klaus"])
print("Klaus")
def ausgabe(liste):
ausgabe([])
if len(liste) == 0:
pass
pass
ausgabe([["Christiane", "Tim"], ...])
else:
...
erstesElement = liste[0]
restListe = liste[1:]
Ausführung
if type(erstesElement) == list:
ausgabe(erstesElement)
else:
print erstesElement
rekursiver Algorithmus
ausgabe(restListe)
103
Liste als rekursive Datenstruktur
Eine Liste ist entweder eine leere Liste, oder besteht aus einem ersten Element und einer
(Rest-)Liste.
def ausgabe(liste):
if len(liste) == 0:
# liste == []
pass
else:
# liste == [erstesElement] + restListe
erstesElement = liste[0]
restListe = liste[1:]
print(erstesElement)
ausgabe(restListe)
def ausgabe(liste):
if len(liste) == 0:
# liste == []
pass
else:
# liste == [erstesElement] + restListe
erstesElement = liste[0]
restListe = liste[1:]
if type(erstesElement) == list:
ausgabe(erstesElement)
else:
print(erstesElement)
ausgabe(restListe)
104
Entwicklung rekursiver Algorithmen
Problem: Es soll gezählt werden, wie oft ein Element in einer Liste vorkommt.
Fall 1: Bearbeite eine leere Liste
anzahl('b', []) ->
0
Reduktionsanfang:
Löse das Problem direkt
Fall 2: Bearbeite eine nicht-leere Liste
anzahl('b', ['b', 'b', 'd', 'a', 'c', 'b']) ->
1 + anzahl('b', ['b', 'd', 'a', 'c', 'b'])
Rekursionsschritt:
Löse ein entsprechendes Problem
anzahl('b', ['a', 'b', 'b', 'd', 'a', 'c', 'b']) ->
anzahl('b', ['b', 'b', 'd', 'a', 'c', 'b'])
Rekursive Problemreduktion: Reduziere des Problems auf ein entsprechendes, aber
„verkleinertes“ Problem.
105
Entwicklung rekursiver Algorithmen
Problem: Es soll gezählt werden, wie oft ein Element in einer Liste vorkommt.
anzahl('b', []) ->
0
anzahl('b', ['b', 'b', 'd', 'a', 'c', 'b']) ->
1 + anzahl('b', ['b', 'd', 'a', 'c', 'b'])
anzahl('b', ['a', 'b', 'b', 'd', 'a', 'c', 'b']) ->
anzahl('b', ['b', 'b', 'd', 'a', 'c', 'b'])
(rekursive) Reduktionsschritte
def anzahl(element, liste):
if len(liste) == 0:
return 0
else:
if liste[0] == element:
return (1 + anzahl(element, liste[1:]))
else:
return anzahl(element, liste[1:])
(rekursive) Reduktionsregeln
Rekursive Problemreduktion: Reduziere des Problems auf ein entsprechendes, aber
„verkleinertes“ Problem.
106
Entwicklung rekursiver Algorithmen
Problem: Es soll gezählt werden, wie oft ein Element in einer Liste vorkommt.
anzahl('b', ['a', 'b', 'd', 'a', 'b']) ->
anzahl('b', ['b', 'd', 'a', 'b']) ->
1 + anzahl('b', ['d', 'a', 'b']) ->
1 + anzahl('b', ['a', 'b']) ->
1 + anzahl('b', ['b']) ->
1 + (1 + anzahl('b', [])) ->
1 + (1 + 0) ->
2
Reduktionskette
def anzahl(element, liste):
if len(liste) == 0:
return 0
else:
if liste[0] == element:
return (1 + anzahl(element, liste[1:]))
else:
return anzahl(element, liste[1:])
(rekursive) Reduktionsregeln
>>> anzahl('b', ['a', 'b', 'd', 'a', 'b'])
2
107
Übungen
Rekursionsgymnastik: Bearbeite die Aufgaben auf inf-schule.
108
Fallstudie - geometrische Objekte
In den folgenden Aufgaben geht es um die Verwaltung und Verarbeitung geometrischer
Objekte. Wir betrachten vereinfachend nur geometrische Objekte, die aus Streckenzügen mit
Punkten mit ganzzahligen Koordinaten bestehen. Die folgende Abbildung (Logo des
Fachbereichs Informatik der TU Kaiserslautern) ist aus solchen geometrischen Objekte
aufgebaut.
stuetzelinks = [[0, 0],[20, 0],[50, 100],[30, 100],[0, 0]]
blockunten = [[90, 10],[110, 10],[110, 30],[90, 30],[90, 10]]
blockoben = [[90, 70],[110, 70],[110, 90],[90, 90],[90, 70]]
raute = [[80, 50],[100, 40],[120, 50],[100, 60],[80, 50]]
verbindung1 = [[100, 110], [100, 90]]
verbindung2 = [[100, 70], [100, 60]]
verbindung3 = [[100, 40], [100, 30]]
verbindung4 = [[100, 10], [100, 0]]
verbindung5 = [[80, 50], [70, 50], [70, 100], [100, 100]]
stuetzerechts = [verbindung1, blockoben, verbindung2, raute, \
verbindung5, verbindung3, blockunten, verbindung4]
dach = [[10, 110],[130, 110],[130, 125],[70, 140],[10, 125],[10, 110]]
tor = [stuetzelinks, stuetzerechts, dach]
rahmen = [[0, 0],[140, 0],[140, 140],[0, 140],[0, 0]]
logo = [tor, rahmen]
Bearbeite die Aufgaben auf inf-schule.