52
Kapitel 6 Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten hat. Dieses Kapitel geht nun darauf ein, ob ein Problem überhaupt algorithmisch erfassbar ist, ob eine gefundener Algorithmus auch das tut was er soll und wieviel Zeit bzw. Platz er dafür benötigt. Inhalt 1. Berechenbarkeit 2. Korrektheit 3. Komplexität Teile dieses Kapitels sind aus: R.Manthey: Vorlesung Informatik 1, Uni Bonn, 2

Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

Embed Size (px)

Citation preview

Page 1: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

Kapitel 6 Algorithmentheorie

Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten hat. Dieses Kapitel geht nun darauf ein, ob ein Problem überhaupt algorithmisch erfassbar ist, ob eine gefundener Algorithmus auch das tut was er soll und wieviel Zeit bzw. Platz er dafür benötigt.

Inhalt1. Berechenbarkeit

2. Korrektheit

3. Komplexität

Teile dieses Kapitels sind aus:R.Manthey: Vorlesung Informatik 1, Uni Bonn, 2001

Page 2: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1 Berechenbarkeit

Wir haben den Begriff und die Elemente eines Algorithmus vorgestellt und Algorithmen zur Lösung von Problemen verwendet.In diesem Unterkapitel werden nun einige Fragen zur Anwendbar- und Sinnhaftigkeit von Algorithmen gestellt und beantwortet.

Inhalt:1. Einige Fragen

2. Das Entscheidungsproblem

3. Die Turing-Maschine

4. Berechenbarkeit

5. Rekursive Funktionen

6. Church‘sche These

H. Ernst:“Grundlagen und Konzepte der Informatik“,Vieweg-Verlag,2000

Page 3: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.1 Einige Fragen

1. Kann jedes Problem durch einen Algorithmus beschrieben werden, d.h. prinzipiell - bei genügender Sorgfalt - gelöst werden ?

2. Kann jeder Algorithmus in ein Programm übertragen werden ? Welchen Anforderungen muss eine Programmiersprache genügen, damit

jeder Algorithmus damit formuliert werden kann ?

3. Ist ein Computer grundsätzlich in der Lage, einen bekannten, als Programm formulierten Algorithmus auszuführen ?

4. Ist ein solcher Computer formalisierbar ? Wie sieht ein solches abstraktes Model aus ? Gibt es genau ein Model oder mehrere ? Sind diese Modelle äquivalent ? Gibt es andere Modelle oder Beschreibungsformen, die diesem

formalisierten Computermodell entsprechen ?

Frage 1 und Frage 4 sind wesentlich für den Begriff der Berechenbarkeit, Frage 2 wird im anschließenden Kapitel behandelt, Frage 4 ist Gegenstand der Vorlesung „Compilerbau“

Page 4: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.2 Das Entscheidungsproblem

Bis weit ins 20ste Jahrhundert war die Mehrzahl der Mathematiker (insb. David Hilbert: 1862-1942) der Ansicht, dass man von jeder Aussage algorithmisch beweisen könne, ob sie wahr oder falsch sein.

Anders ausgedrückt: Es sei entscheidbar, ob ein Problem lösbar oder unlösbar ist.

Die Frage, ob dies entscheidbar ist oder nicht ging als Entscheidungs-problem in die Geschichte der Mathematik (und Informatik) ein.

Kurt Gödel wies in seinem Unvollständigkeits-Theorem 1931 nach, dass alle widerspruchsfreien axiomatischen Formulierungen der Zahlentheorie unentscheidbare Aussagen enthalten.

damit wurde insb. belegt, dass streng algorithmisch arbeitende Computer prinzipiell nicht jedes Problem lösen können.

Auf fast schon philosophischer Ebene wurde damit auch belegt, dass Wahrheit eine andere Qualität als Beweisbarkeit besitzt.

nicht alle „wahren“ Aussagen können auch bewiesen werden.

Page 5: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.3 Die Turing-Maschine: Definition

Als abstraktes Modell eines Computers beschrieb Alan Turing (1912-1954) 1963 - also noch vor der Erfindung des Digitalrechners - eine nach ihm benannte abstrakte Maschine

Formal kann eine Turing-Maschine wie folgt beschrieben werden: Alphabet: A = {a0, ... , an}, der Zeichenvorrat der Turing-Maschine, wobei a0 das

Leerzeichen ("blank") darstellt (Oft: a1=0, a2=1)

Bandinschrift: B: Z A eine Zuordnung, die jeder Stelle des rechtsseitig unendlichen Bandes ein Zeichen zuordnet. Dabei wird festgesetzt, dass B(k) = a0 für alle bis auf endlich viele .

Kopfposition: k Z Zustände: eine endliche Menge von Maschinenzuständen.Q = {q0, ..., qm}

Darunter sind q0, der Anfangszustand und H Q , die Menge der

Haltezustände, ausgezeichnet. Statt Haltzustände wird oft auch eine Halteaktion angegeben

Turing-Tabelle:eine Übergangsrelation: d : A Q A Q {r, l, n, h}, das jedem (gelesenen) Zeichen in Abhängigkeit eines Zustandes ein neues Zeichen, einen Folgezustand und eine Aktion (r,l,n,h} zuordnet

Page 6: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.3 Die Turing-Maschine: Programm

Die Aktionen: r (right): das Verschieben des Kopfes nach rechts l (left): das Verschieben des Kopfes nach links optional n (none): keine Bewegung des Kopfes optional h (halt): Impliziter Übergang in einen Endzustand

a1 a2 a3 a4 ... a6

dieMaschineim Zustand

das unter demKopf geleseneZeichen

dieAktion

der neueZustand

q q‘r oder lak

das neueZeichen

falls so ist

al

Page 7: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.3 Die Turing-Maschine: Beispiel

Das „Busy beaver“-Problem:Wie viele „1“-en kann ein terminierendes Turing-Programm auf einem leeren Band mit einer vorgegebenen Anzahl von Zuständen maximal erzeugen.

In dieser Notation wird statt eines Übergangs in den Haltezustand (z.B. q5) die Aktion „halt“ ausgeführt.

Der Rekord für |Z|=5 liegt bei 4096 „1“en (J.Buntrock, H.Marxen, 1989) Es wurde gezeigt, dass es möglich ist, mehr als 4098 „1“en zu generieren -

allerdings nicht wie.

11 Schritte, 6 Einsen 96 Schritte, 13 Einsen

Page 8: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.4 Definition: Berechenbarkeit

Ein Problem ist genau dann algorithmisch lösbar, wenn es durch eine Turing-Maschine darstellbar ist.

Eine Funktion f(x) heißt berechenbar, genau dann wenn es einen Algorithmus (eine Turing-Maschine) gibt, der bei gegebenem x das Ergebnis f(x) liefert

Ein Computer ist äquivalent zu einer universellen Turing-Maschine. d.h. ein Computer ist äquivalent zu einer Turing-Maschine, die jede

andere Turing-Maschine simulieren kann. Zur Simulation einer beliebigen Turing-Maschine muss auf dem

Eingabeband eine Beschreibung der zu simulierenden Maschine codiert werden und außerdem deren Eingabeband gespeichert sein.

Die Menge verschiedener universeller Turing-Maschinen ist abzählbar - denn das Band ist binär codiert, jede Kombination lässt sich auf eine natürliche Zahl abbilden. Die Menge aller Funktionen f(x) ist überabzählbar (z.B. Funktionen die auf eine reelle Zahl abbilden) Es gibt (unendlich viele) nicht berechenbare Funktionen

Page 9: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.5 Beispiel: Das Halteproblem

Nicht berechenbare Probleme sind also keine Probleme, die noch nicht gelöst sind, sondern solche, für die es keine Lösung gibt.Das wohl bekannteste dieser Probleme ist das Halteproblem:Es gibt kein Programm, das für ein beliebiges gegebenes Programm P, und für beliebige gegebene Eingabeparameter entscheidet, ob das gegebene Programm anhält.

Gegeben: Programm P (z.B. als Quelltext)Annahme: Es gibt ein solches

Programm: Test(P)

Test (P)

ja nein

stopptmit P,Ey n

Test1 (P)

stoppe

Test = jay n

Test (P)

Test (Test1) = ja Test1 (Test1) läuft endlos Test (Test1) = nein Widerspruch !Test (Test1) = nein Test1 (Test1) stoppt Test (Test1) = ja Widerspruch !

Page 10: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.6 Rekursive Funktionen

Es gibt innerhalb der mathematischen Funktionen zwei Unterklassen: primitiv-rekursive Funktionen:

jede primitiv-rekursive Funktion ist berechenbar es gibt berechenbare Funktionen, die nicht primitiv-rekursiv sind primitiv-rekursive Funktionen lassen sich genau mit Algorithmen ohne

Schleifenkonstrukte (aber mit Blockung) darstellen.

-rekursive Funktionen jede -rekursive Funktion ist berechenbar es gibt berechenbare Funktionen, die nicht -rekursiv sind -rekursive Funktionen lassen sich mit Algorithmen mit Schleifenkonstrukte

(und Blockung) darstellen.

Es gilt folgende Beziehung innerhalb von Funktionen:

-rekursive Funktionen

primitiv-rekursive Funktionen

berechenbare Funktionen

Page 11: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.1.6 Church‘sche These

Wir haben bislang verschiedene Äquivalenzen gefunden: Primitiv und -rekursive Funktionen sind Teilmengen von berechenbaren

Funktionen. Eine Funktion ist genau dann berechenbar, wenn es eine Turing-Maschine

zu deren Berechnung gibt,. Die Darstellung mit Hilfe einer Turing-Maschine ist äquivalent mit der einer

universellen Turingmaschine, die wiederum eine Abstraktion eines Computers darstellt

Dies legt die Formulierung einer der Church‘schen These nahe:Alle im intuitiven Sinn vernünftigen Formalisierungen von Problemlösungen sind äquivalent

Wenn ein Problem nicht durch eine Turing-Maschine gelöst werden kann, so ist es algorithmisch überhaupt nicht lösbar

Da Begriffe wie „intuitiv“ und „vernünftig“ nicht definiert sind, ist die Church‘sche These nicht beweisbar.

Page 12: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2 Korrektheit

Wir haben diskutiert, ob man jede (mathematische) Funktion berechnen kann und haben dabei die Äquivalenz eines Algorithmus‘ mit berechenbaren Funktionen gesehen.In diesem Unterkapitel geht es nicht mehr nur darum, ob eine Funktion berechenbar ist, bzw. ein Algorithmus für deren Berechnung existiert, sondern ob der gegebene Algorithmus tatsächlich das macht, was er machen soll

Inhalt1. Ansatz

2. Definition

3. Logik zur Verifikation (C.A.R. Hoare)

4. Regeln

5. Terminierung

6. Beispiele

7. Beweis des Euklid‘schen Algorithmus

8. Kritische Anmerkungen

U.Kastens:“Modellierung“, Vorlesung WS‘00/‘01, Uni Paderborn

Page 13: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.1 Ansatz

Wir haben zu Beginn des Kapitels den Begriff der Korrektheit definiert: partielle Korrektheit:

Jedes berechnete Ergebnis genügt der Ausgabespezifikation, sofern die Eingaben der Eingabespezifikation genügt haben

Terminierung:Der Algorithmus hält nach endlich vielen Schritten mit einem Ergebnis an, sofern die Eingaben der Eingabespezifikation genügt haben

Zum Beweis der Korrektheit gehen wir also von der Eingabespezifi-kation aus und versuchen, mit den Aktionen (Statements) des Algorithmus die Ausgabespezifikation abzuleiten.

Die Eingabespezifikation wird dabei als Vorbedingung P(V) oder {P} und die Ausgabespezifikation Q(V) oder {Q} als Nachbedingung mathematisch formuliert

Über die Aktionen des Algorithmus wird die Vorbedingung über Zusicherungen Zi(V) zur Nachbedingung abgeleitet

Also: P(V) Z1(V) ... Zn(V) Q(V)

Page 14: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.2 Definition: Korrektheit

Beispiel: Lösung der quadratischen Gleichungqugl (IN: p,q: real, OUT x1,x2:real)// Vorbedingung: (p*p)/4 q// Nachbedingung: x1 = (-p/2 + sqr(p*p/4-q)) // x2 = (-p/2 - sqr(p*p/4-q)) { w : real; w = sqr(p*p/4 - q); x1 = -p/2 + w; x2 = -p/2 - w:}

Ein Algorithmus heißt korrekt bezüglich seiner Spezifikation, wenn für jeden Aufruf, der die Vorbedingung erfüllt, nach dem Aufruf des Algorithmus‘ die Nachbedingung erfüllt ist (und er terminiert)

Achtung:Die Vorbedingung ist vom Aufrufer zu erfüllen, die Nachbedingung ist durch den Algorithmus (bzw. den Implementierer) zu erfüllen.

Page 15: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.3 C.A.R. Hoare: Logik zur Verifikation

C.A.R. Hoare formulierte 1969 ein Kalkül zum Beweis von Aussagen über Algorithmen und Programme

damit sind - im Gegensatz zum Testes - statische Aussagen über Zustände des Algorithmus ( Werte der Variablen) möglich. Diese Aussagen gelten für alle Ausführungen des Algorithmus

Durch logisch Schlüsse über die Elemente eines Algorithmus kann gezeigt werden, dass

an einer bestimmten Stelle im Algorithmus eine bestimmte Aussage gilt. eine Aussage an jeder Stelle eines Teils des Algorithmus invariant gilt Schleifen terminieren.

Also: ein Algorithmus aus jeder zulässigen Eingabe die geforderte Ausgabe

berechnet

Page 16: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.3 C.A.R. Hoare: Beispiel

min (IN: a,b: integer, OUT min:integer)// Vorbedingung: a,b > 0 (nicht unbedingt notwendig)// Nachbedingung: (min=a min=b) (mina) (minb){ if a<b then { // Z1: a<b min = a; // Z2: a<b min=a Z3: min=a mina minb } else { // Z4: ba min = b; // Z5: ba min=b Z6: min=b minb mina } // Z7: (min=aminaminb) (min=bminbmina) // Z8: (min=a min=b) (mina) (minb) = Q}

Damit ist aus der Vorbedingung P mit Hilfe der Anweisung in min() die Nachbedingung Q formal abgeleitet worden.

Page 17: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.3 C.A.R. Hoare: Vorgehen

Aussagen über den Algorithmenzustand, über Werte von Variablen werden in den Algorithmus eingefügt:

{ P } A1 { R } A2 { Q } bedeutet: R gilt immer zwischen der Ausführung von A1 und der

Ausführung von A2 Beispiel: { i + 1 0} i := i + 1; { i 0 } a [i] := k; {...}

Zur Verifikation eines Algorithmus muss für jede Anweisung S ein Nachweis geführt werden:

{ Vorbedingung P } S { Nachbedingung Q } nachweisen: Wenn vor der Ausführung des Schrittes S die P gilt, dann

gilt Q nach der Ausführung von S, falls S terminiert. Beispiel: { i + 10} i := i + 1; {i 0} mit Zuweisungsregel nachweisen

Die Aussagen werden entsprechend der Struktur von S verknüpft. Für jede Anweisungsform wird eine spezielle Schlussregel angewandt.

Die Spezifikation liefert Vorbedingung und Nachbedingung des gesamten Algorithmus:

Page 18: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Zuweisung

Die Zuweisung x = expr wertet den Ausdruck expr aus und weist das Ergebnis der Variablen x zu.Es gilt dann:

{P[x/expr]} x := expr {P}oder

{P(x)} x = f(x) {P(f--1(x))}

P[x/expr] steht für die Substitution von x durch expr in P Die Nachbedingung P erhält man dadurch, dass man jedes Vorkommen von

expr in der Vorbedingung durch x (die linke Seite der Zuweisung) ersetzt Wenn man also zeigen will, dass nach der Zuweisung eine Aussage P für x

gilt, muss man zeigen, dass vor der Zuweisung dieselbe Aussage P für expr gilt.

Beispiele: {a>0} x = a {x>0} {i+1>0} i=Succ(i) {i>0}: f(x)=Succ, f-1(x)=Pred(x), {P(Pred(x+1)}=(i+1-1>0) {i+1>0} i = i+1 {i>0}

Page 19: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Zuweisung - Beispiele

{P[x/expr]} x := expr {P}1. alle Aussagen der Vorbedingung für expr, gelten für x in der Nachbedingung2. Aussagen der Vorb. über x gelten in der Nachbedingung nicht mehr3. Die Nachbedingung P erhält man dadurch, dass man jedes Vorkommen

von expr in der Vorbedingung durch x ersetzt ggf. ist die Vorbedingung so umzuformen, dass expr explizit Teil der

Vorbedingung ist (auf der linken Seite einer Aussage)

„Alles was vorher für die rechte Seite der Zuweisung galt, gilt hinterher für die linke - Alles was vorher für die linke galt, gilt nicht mehr - Alle anderen Aussagen gelten weiterhin“

1. {y=5} x=y {x=5}2. {a>0 x>7} x=a {x>0 x>7} falsch wg. Punkt 23. {a>0 z>0} x=a {x>0 z>0} z>0 ist nicht betroffen4. {i+1>0} i=i+1 {i>0}5. {i0} {i+1>0} i=i+1 {i>0} passend umformen6. {i=2} {i+1=3} i=i+1 {i=3} passend umformen7. {z=5} x=1 {z=5 x=1} z nicht betroffen, x neu

Page 20: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Konsequenz

Abschwächung der Nachbedingungwenn gilt und dann gilt auch

{P} S {R} {R} {Q} {P} S {Q}

Beispiel

{a+b>0} S {x>0} {x>0} {X0} {a+b>0} S {X0}

Verschärfung der Vorbedingung wenn gilt und dann gilt auch

{P} {R] {R} S {Q} {P} S {Q} Beispiel (Notation: Im Algorithmus können Implikationen () in

Ausführungsrichtung eingefügt werden)

{a+b>0}x = a+b;{x>0} {2*x 0}y = 2 * x{y0}

Page 21: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Sequenz

Folgendes Schema lässt sich auf eine Sequenz von Aktionen (Statements) anwenden:

wenn gilt und dann gilt auch

{P} S {R} {R} S2 {Q} {P} S1,S2 {Q}

Beispiel:{x>0 y>0} {x>0 y>0}

a = x; a = x;

{a>0 y>0} {a>0 y>0} {a>0 y>0}

b = y; b = y;

{a>0 b>0} {a>0 b>0}

Bei trivialen Ableitungen können die Zwischenschritte (Zusicherungen, Aussagen) demnach auch weggelassen werden:

{x>0 y>0}

a = x; b = y;

{a>0 b>0}

Page 22: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Bedingte Anweisung

Schema:wenn gilt und dann gilt auch

{P B} S {Q} {PB} {Q} {P} if B then S {Q}

Um die Nachbedingung einer bedingten Anweisung zu beweisen, muss1. aus der Vorbedingung und der Anweisungs-Bedingung über die

Anweisung die Nachbedingung nachgewiesen werden

2. aus der Vorbedingung und der Negation der Anweisung die Nachbedingung direkt folgen

Beispiel: Gegeben: if a<0 then a = -a Beweise, dass der Algorithmus a0 für alle a liefert:

1. {P a<0} {P -a>0} a=-a {P a>0} {P a 0}

2. {P (a<0)} {P a 0}

dann gilt auch

{P} if a<0 then a=-a {P a 0}

Page 23: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Bedingte Anweisung - Notation

Beispiel: Gegeben: if a<0 then a = -a Beweise, dass der Algorithmus a0 für alle a liefert:

1. {P a<0} {P -a>0} a=-a {P a>0} {P a 0}

2. {P (a<0)} {P a 0}

dann gilt auch

{P} if a<0 then a=-a {P a 0}

Notation:{P}if a<0 then {P a<0} {P -a>0} a = -a {P a>0} {P a 0}// leere Alternative: {P (a<0)} {P a 0}{P a 0}

Page 24: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Einfache Alternative

Schema:wenn gilt und dann gilt auch

{P B} S1 {Q} {PB} Ss {Q} {P} if B then S1 else S2 {Q}

Aus der gemeinsamen Vorbedingung P muss für beide Alternativen dieselbe Nachbedingung Q nachweisbar sein

Beispiel: Gegeben: a>0, b>0, ab und ein Algorithmus (s.u) Beweise, dass nach den Operationen immer noch gilt: a>0, b>0

{a>0 b>0 ab}if a>b then {a>0 b>0 ab a>b} {b>0 a-b>0} a = a-b; {b>0 a>0}else {a>0 b>0 ab ab} {a>0 b-a>0} b = b-a; {a>0 b>0}

{b>0 a>0} {a>0 b>0} {a>0 b>0}

Page 25: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Schleife

Schema:wenn gilt dann gilt auch{P I B} S {I} {I} while B { S } {I B Q} // I =

Schleifeninvariante Schleifeninvarianten sind Zusicherungen in Schleifen, die beim

Durchlaufen des Schleifenkörpers erhalten bleiben. Es gelte P Zusicherung über Variable vor Schleifeneintritt Q Zusicherung über Variable nach Schleifenende I Schleifeninvariante B Wiederholbedingung der Schleife S Statements (Aktionen) im Schleifenkörper

Die Nachbedingung einer Schleife ist über die Invariante nachgewiesen, wenn gilt:

1. P I die Invariante muss vor Schleifeneintritt wahr sein2. (I B) I die Invariante darf in Schleife nicht verändert

werden3. (I B) Q die Nachbedingung muss sich nach Verlassen der

Schleife aus der Invariante nachweisen lassen

Page 26: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Schleife - Schema

Das Schema der Gültigkeit von Aussagen sei anhand des Flussdiagramms für Schleifen verdeutlicht:

B ?

S

P

I

I B

I

fw

I B Q(V)

Um Q(V) zu beweisen, mussman I(V) so wählen, dassQ(V) aus I(V) B(V) ableitbarist

Hier muss man beweisen,dass sich I in S aus I Bableiten lässt

I muss ausP ableitbarsein

Page 27: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Schleife - Beispiel

Algorithmus zum Potenzieren// Vorbedingung: b 0 (positive Exponenten)// Nachbedingung: z = ab

x=a, y=b, z=1;{ x=a y=b z=1 y 0}{INV: z * xy = ab y0}while y>0{ { INV y>0 z*x(y-1)+1=ab (y-1)+1 > 0 } y = y-1; { z*xy+1=ab y+1>0 } { ((z*x)/x)*xy+1 = ab y 0 } z = z*x; { z/x*xy+1 = ab y 0 } { z * xy = ab y 0 INV }}{ INV B z * xy = ab y0 y0 z*x0 = z = ab Q }

B ?

S

P

I

I B

I

fw

I B Q

Page 28: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.4 Regel: Schleife - Schleifeninvariante

Das Finden der „richtigen“ Invariante kann ganz schön kniffelig sein: Ein paar „Tips“:

Wenn die Nachbedingung nicht gegeben ist, versuche die Semantik des Algorithmus‘ zu verstehen, z.B. anhand von Beispielen.

Betrachte die Anweisungen in der Schleife:Meist wird etwas vergrößert (z.B. die Variable der Abbruchbedingung), während etwas anderes verkleinert wird - oder umgekehrt. Kombiniere diese: z * xy

Setze Ein- und Ausgabevariablen in Bezug zueinander z * xy = ab

Verwende die Schleifenbedingung zum „Einklemmen“ der Schleifenvariable.

Beachte, dass aus INV und B(V) Q(V) ableitbar sein soll Das bedeutet, dass man die Invariante aus der Nachbedingung konstruieren kann, indem man die negierte Bedingung mit berücksichtigt

z * xy = ab y=0 z*x0 = z = ab Q

Page 29: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.5 Terminierung

Die Terminierung einer Schleife muss separat nachgewiesen werden Beweis der Terminierung

1. Gib einen ganzzahligen Ausdruck E an über Variablen, die in der Schleife vorkommen und zeige, dass E bei jeder Iteration durch S verkleinert wird

2. Zeige, dass E nach unten begrenzt ist, z.B. dass 0E eine Invariante der Schleife ist

3. Zeige, dass die Grenze auch erreicht wird. E kann auch monoton vergrößert und nach oben begrenzt sein

Beweis der Nicht-Terminierung: Beweise,1. dass RB eine Invarianz der Schleife ist (also R in die Schleife geht) und

dass es eine Variablenbelegung gibt, so dass RB vor der Schleife gilt

2. dass R einen speziellen Zustand charakterisiert, in dem die Schleife nicht anhält

Es gibt Schleifen, für die man nicht entscheiden kann, ob sie für jede Vorbedingung terminieren.

Page 30: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.5 Terminierung - Beispiele

{ a>0 b>0 }while ab { while a>b { a=a-b } while a<b { b=b-a }} // terminiert

{ a>0 b>0 }while ab { while ab { a=a-b } while a<b { b=b-a }} // terminiert nicht immer (a = 2*b)

{ n n>1 }while n>1 if n gerade then n = n/2 else n=3*n+1 // Terminierung unbewiesen

Page 31: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.6 Beispiel: Multipl. durch fortgesetze Addition

// Vorbedingung P: a0 b0, Beh.: Nachbedingung Q: z = a*b x = a; y = b; z = 0; { x0 b0 z=0 }// Auch hier: Die Summe von x*y+z bleibt konstant a*b { INV: z+xy = ab, x,y0 } while x > 0 {

{ INV x>0 } { (z+y)-y+xy = ab, x>0,y0 } z = z + y;

{ z-y+xy = ab, x>0,y0 } { z-y+((x-1)+1)y = ab, (x-1)+1>0,y0 } x = x - 1;

{ z-y+(x+1)y = ab, x+1>0,y0 } { z-y+xy+y = z+xy = ab, x,y0 } INV

}

{ INV B = (z+x*y=a*b) (x=0) z+0*y=a*b Q }

B ?

S

P

I

I B

I

fw

I B Q

Page 32: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.6 Beispiel: Die ägyptische Bauernmultiplikation

// Vorbedingung P: a0 b0, Beh.: Nachbedingung Q: z = a*bx = a; y = b; z = 0; { x,y0 z=0 x=a y=b }// Schleife verdoppelt x und halbiert y: Invariante: INV INV = { z+x*y = a*b x,y0 }while x > 0 { { INV x>0 } if (odd(x) then { (z+y)-y+x*y = a*b) x>0,y0 } z = z+y; { odd(x) z-y+x*y = a*b x>0,y0 } // leere Anweisung { even(x) z+x*y = a*b x>0,y0 } { ( odd(x) z-(2y/2)+x*(2y/2) = a*b x>0,(2y/2)0 ) ( even(x) z+x*(2y/2) = a*b x>0,(2y/2)0 ) } y = y * 2; { ( odd(x) z-y/2+x*y/2 = a*b x>0,y/20 ) ( even(x) z+x*y/2 = a*b x>0,y/20 ) } { (odd(x) z-y/2+(2(x div 2)+1)*y/2 = a*b (2(x div 2)+1)>0,y0 ) (even(x) z+(2(x div 2))*y/2 = a*b 2(x div 2) >0,y0 ) } x = x div 2; // div = Ganzzahldivision { ( odd(2x+1) z-y/2+(2x+1)*y/2 = a*b (2x+1)>0,y/20 ) ( even(2x) z+ 2x *y/2 = a*b 2x >0,y/20 ) } { (z-(y - y(2x+1))/2 = z-(y-2xy-y)/2 = z-(-2xy/2)= z+xy = a*b ) (z + 2x * (y*2) = z+xy = a*b )}INV } { INV B = (z+x*y=a*b) (x=0) z+0*y=a*b Q }

Page 33: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.2.7 Kritische Anmerkungen

Die Verifikation entspricht einer mathematischen Beweisführung und kann entsprechend kniffelig, aufwändig, wenn nicht gar unmöglich sein.

Durch formale Überprüfung der Korrektheit, lassen sich Schlüsselstellen eines Algorithmus‘ (eines Programms) verifizieren

Durch das Denken mit Zusicherungen, Invarianten und mathematische Folgerungen wird die Erstellung fehlerfreier Programme gefördert.

Auch wenn es semi-automatische Systeme zur formalen Verifikation von Algorithmen gibt, ist es praktisch nicht möglich, auch nur halbwegs komplexe Programmsysteme damit zu verifizieren

Selbst wenn es möglich wäre, Algorithmen vollständig formal zu beweisen, so wäre dies keine Garantie, dass ein Programmsystem entsprechend den Wünschen eines „Kunden“ funktioniert. Dazu gehören alle Mechanismen eines ordentlichen Software-Engineering.

Page 34: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3 Komplexität

In diesem Kapitel haben wir den Begriff „Berechenbarkeit“ definiert als all das, was algorithmisch beschreibbar ist. Wir haben eine Methode vorgestellt, mit der man (meist) zeigen kann, dass ein Algorithmus das tut was er soll. Was noch fehlt - und hier behandelt werden soll - ist die Frage nach dem Zeit- und Platzbedarf eines Algorithmus.

Inhalt1. Wie „gut“ ist ein Algorithmus

2. Die O-Notation

3. Häufige O-Ausdrücke

4. Einige Regeln

5. Quantitatives

6. Platzbedarf

Page 35: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.1 Qualität eines Algorithmus

Die Abarbeitung eines Algorithmus benötigt „Ressourcen“, vor allem: Zeit Laufzeit des Algorithmus Platz Speicherplatzbedarf des Algorithmus

Problem bei der Ressourcenermittlung - der Ressourcenbedarf ist Abhängig von:

der Problemgröße (z.B. Multiplikation einer 10x10 bzw. 100x100 Matrix) der Eingabewerte (z.B. Sortieren einer bereits sortierten Menge) der Fragestellung (bester, mittlerer, schlechtester Fall) der Güte der Implementierung (z.B. (un-)geschickte Typwahl) der Hard- und Software (z.B. Schneller Rechner, optimierter Compiler)

Es gibt auch Qualitätsmerkmale eines Algorithmus, der sich nicht am Ressourcenbedarf festmachen (aber das ist eine andere Geschichte ...)

Wartbarkeit Robustheit „Eleganz“ ...

Page 36: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.2 Die O-Notation: Definition

Definition:Eine Funktion g(n) wird O(f(n)) genannt („Die Laufzeit, der Aufwand, die Zeitkomplexität von g(n) ist O(f(n))“), falls es Konstanten c und n0 gibt, so dass: g(n) cf(n), für fast alle n > no ist

f(n) ist damit eine obere Schranke für die Laufzeit des Algorithmus (allerdings nur zusammen mit einem festen c und ab bestimmten n0)!

Beispiel: Bei der Analyse eines Algorithmus hat sich herausgestellt, dass die Laufzeit

g(n) = 3n2 + 7n - 1 ist. Behauptung: Die Laufzeit von g(n) ist O(n2), also f(n)=n2, Beweis:

Es muss Konstanten c und n0 geben, so dass gilt:3n2+7n-1 c n2, für alle n > n0

setze n0=7 und c=4, dann gilt:

3n2+7n-1 3n2+7n 3n2+n2 = 4n2

Page 37: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.2 Die O-Notation: Schranken

Die Notation gibt nur eine obere Schranke der Komplexität , das muss nicht notwendigerweise die beste Schranke sein.

Beispiel: Eine weitere obere Schranke für g(n) = 3n2 + 7n - 1 ist auch O(n3), welche sicher nicht die beste ist.

Bei der Suche nach der Größenordnung von f(n) wird man versuchen, das kleinste f(n) zu finden, für das g(n) < c . f(n)

Dieses ist dann eine kleinste, obere Schranke für den Aufwand Zur Bestimmung des tatsächlichen asymptotischen Aufwands wird

man also noch eine größte, untere Schranke h(n) = (g(n)) suchen für die gilt: limn h(n)/f(n) = 1

Eine untere Schranke ist die Zeit, die jeder Algorithmus (ab einem n>n0) benötigt

Das ist im Allgemeinen viel schwieriger !

Page 38: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.2 Die O-Notation: Achtung

Achtung !Die Konstanten c und n0 werden üblicherweise nicht angegeben und können sehr groß sein

Beispiel:Algorithmus A habe eine Laufzeit von O(n2)Algorithmus B für das gleiche Problem eine Laufzeit von O(1,5n)Welcher Algorithmus ist besser ?

schnelle Antwort: A (das stimmt auch für große n) bessere Antwort: Wie groß ist n ? Wie groß sind die Konstanten ? z.B. für cA=1000 und cB=0,001

n cAn2 cB1,5n

1 103 1,5 10-3

10 105 1,8 10-2

20 4 105 3,350 2,5 106 6,4 105

100 107 4,1 1014

Bis hier ist B besser als A

Page 39: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(1)

Teile von Ausdrücken, die eventuell ein „paar“ Mal durchlaufen werden, wobei die (maximale) Anzahl der Durchläufe nicht abhängig von den Eingabewerten sind, haben konstante Laufzeit: O(1) (c * 1)

Beispiel:

max, i, y : integer;max = 0;y << Tastatur;if (y < 20) then max=10else max=100;for i=1 to max{ y = y+1;}

Die Anzahl der Schleifendurchläufe ist zwar abhängig von y (entweder 20 oder 100), die maximale Anzahl aber nicht (immer 100, egal wie groß oder klein y ist)

Page 40: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(log n) - rekursiv

Rekursive Algorithmen, die in jedem Schritt die Menge der Eingabedaten halbieren haben eine Laufzeit von O(log n)

eigentlich O(ld n), aber da ld n 3,322 log n = c log n ist O(ld n)=O(log n)

Beispiel: Suche in einem sortierten Binärbaum

search (IN: x:integer; tree:*node; OUT: found:boolean){ if tree == nil then { // there is no tree to search => x not found found = false; return; // ATTENTION: return already here } if (x < node.value) then

search(x,node.left, found) else if (x > node.value) then

search(x,node.right,found) else if (n == node.value)

found=true;}

Page 41: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(log n) - Zeitbedarf

Block mit rekursivem Aufruf der/s halben Eingabemenge/-Wertes

rek_block (IN: Eingabemenge OUT: Ausgabewert) { if ( Trivialfall) then { Ausgabewert = Trivialwert } // optional: Aktionen mit konstantem Aufwand rek_block (Eingabemenge / 2);}

Bestimmung des Zeitbedarfs Der Zeitbedarf für das Durchlaufen ergibt sich aus:

Abfrage des Trivialfalls und (optional) Aktionen O(1) Rekursiver Aufruf mit Eingabemenge/Wert die/der halb so groß ist, also n/2. also : Tn = 1 + Tn/2 (Tn = Zeitbedarf für n, n2)

T1= 0 (eigentlich 1, kann aber vernachlässigt werden)

Annahme (o.B.d.A.): Eingabemenge/-wert ist Potenz von 2 also n = 2k, Diese Annahme kann man machen, denn falls n keine Zweierpotenz ist, erhöht

man die Eingabemenge/-wert auf die nächste 2er Potenz und bekommt noch immer eine obere Schranke.

T2k = T2

k-1 +1 = T2k-2 +1+1 = ... = T2

0 + k = k T2k = k Tn= k = ldn

Page 42: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n) - rekursiv

Rekursive Algorithmen, die in jedem Schritt die Menge der Eingabedaten halbieren aber dazu jedes Element betrachten müssen haben eine Laufzeit von O(n)

Beispiel: Suche in einer sortierter Liste (array) mit 0 am Ende

search (IN: x:integer; list:*liste; OUT: found:boolean) { i : integer; if (list[1]==0) then found = false; // list with no element i=1; while (list[i] != 0) i=i+1 // get length of list if (x==list[i/2]) then found = true; else if (x<list[i/2]) then { list[i/2+1]=0; search(x,&list[1],found} }; else search(x,&list[i/2+1],found);}

Zeitbedarf: Tn = Tn/2+ n (Tn = Zeitbedarf für n, n2, T1=0)Annahme (o.B.d.A.): n = 2k,T2

k = T2k-1 + n = T2

k-2 + n/2+n = ... = T20 +n/2+n/4 + ... + 0 = 2n-2 O(n)

Page 43: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n) - iterativ

Iterative Algorithmen die eine lineare Liste durchlaufen deren Länge abhängig von der Menge der Eingabeelemente ist (einfache Schleife), haben die Laufzeit O(n)

Beispiel: Suche in einer sortierter Liste (array) mit 0 am Endesearch (IN: x:integer; list:*liste; OUT: found:boolean) { i : integer; found = false; // initialize OUT-value i=1; while ((list[i] != 0) and (not found)) {

i=i+1; if (list[i]==x) then found = true; }}

Anmerkung: Dieser Algorithmus funktioniert auch mit unsortierten Listen Warum dann einen rekursiven, teilenden Algorithmus ?

Anzahl „eingeschränkter“ Vergleiche O(n) Anzahl „vollständiger“ Vergleiche O(log n)

Page 44: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n) - rekursiv

Rekursive Algorithmen, die die Eingabedaten in zwei Hälften aufspalten, und beide Hälften getrennt abarbeiten, haben eine Laufzeit von O(n)

Beispiel: Erstellen eines „Lineals“ (siehe auch: Skript Dr. Geisse)

linael (IN: links,rechts,höhe:integer) { mitte : integer; if (höhe>0) then { mitte = (links + rechts) / 2; zeichne (mitte,höhe); lineal (links,mitte,höhe-1); lineal (mitte,rechts,höhe-1); }}

Zeitbedarf: Tn = 2Tn/2+ 1 (Tn = Zeitbedarf für n, n2, T1=0)Annahme (o.B.d.A.): n = 2k,T2

k = 2T2k-1 + 1 1/2 T2

k = T2k-1 + 1/2 = 2T2

k-2 + 1 + 1/2 1/4 T2

k = T2k-2 + 1/2 + 1/4 ...

1/2k T2k = T2

0 + 1/2 + 1/4 + ... + 1/2k = 1 - 1/2k T2

k = 2k-1 Tn = n-1 Laufzeit O(n)

Page 45: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n log n)

Rekursive Algorithmen, die die Eingabedaten in zwei Hälften aufspalten, und die Eingabedaten einmal durchlaufen (davor, währenddessen, oder danach), haben eine Laufzeit von O(n log n)

Beispiel: Sortieren einer Liste a : array[1..max] of integer (C.A.R. Hoare)Quicksort (IN:l,r:integer) { // l left, r right indexi,j,x : integer; // i,j: indexes, x,y: elemetsi=l; j=r; // initialize i with left, j with right indexx = a[(l+r)/2}] // get element in the middledo { // walk with i from left, with j from right while a[i]<x { i=i+1 } // skip smaller elements from left while a[j]>o { j=j-1 } // skip larger elements from right if (i<=j) then { exchange(a[i],a[j]); i=i+1; j=j11 } } while i<=j // i is now right of j -> stop loopif l<j then sort(l,j); // sort left part (only if exists)if i<r then sort(i,r); // sort right part (only if exists)

Zeitbedarf: Tn = 2Tn/2+ n (Tn = Zeitbedarf für n, n2, T1=0)Annahme (o.B.d.A.): n = 2k, (d.h. k = ld n)T2

k = 2T2k-1 + 2k 1/2k T2

k = T2k-1/2k-1 + 1 = T2

k-2/2k-2 + 1 + 1 = ... = k 1/2k T2

k = k T2k = 2k k Tn = n log n Laufzeit O(n log n)

Page 46: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n2) - rekursiv

Rekursive Algorithmen, die die Eingabedaten jeweils um eins verringern, dabei aber alle Daten betrachten müssen, haben eine Laufzeit von O(n2)

Beispiel: Sortieren einer Liste a : array[1..max] of integer StraightSelection (IN:l,r:integer) { // l left, r right index i: integer; // index i = l; // start with left element while (i<r) { // walk through complete list // if an element is smaller, bring it to the left if (a[i]<a[l]) then exchange(a[i],a[l]); i = i+1; } if (l<r) then StraightSelection (l+1,r);}

Zeitbedarf: Tn = Tn-1+ n (Tn = Zeitbedarf für n, n2, T1=1)Tn = Tn-1 + n = Tn-2 + n-1 + 1 = Tn-3 + n-1 + n-2 + 1 = ... = 1+2+3+..+n Tn = (n(n+1))/2 = 1/2n2 + 1/2n Laufzeit O(n)

Page 47: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.3 Häufige O-Ausdrücke: O(n2), O(n3) - iterativ

Iterative Algorithmen die eine Liste - deren Länge abhängig von der Menge der Eingabeelemente ist - (fast) sooft durchlaufen, wie die Liste lang ist (doppelt verschachtelte Schleife), haben die Laufzeit O(n2)

Beispiel: Sortieren einer Liste a : array[1..max] of integer StraightSelection (IN:l,r:integer) { // l left, r right index i: integer; // index i = l; // start with left element for i=1 to r-1 // walk through complete list { for j=i+1 to r // walk through rest of list { if (a[j]<a[i]) then exchange(a[i],a[j]); } }}

Dreifach verschachtelte Schleifen haben eine Laufzeit von O(n3) Beispiel: Multiplikation zweier Matrizen

Page 48: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.4 Einige Regeln

Hat ein Algorithmus eine Laufzeit, die mit einem Polynom k-ten Grades darstellbar ist (aknk + ak-1nk-1 + ... + a0) , so ist die Laufzeit O(nk)

Beispiel: Laufzeit: 9n3 + 7n - 1000 Laufzeit O(n3)

Wird ein Teil A mit Laufzeit O(x) vor einem Teil B mit Laufzeit O(y) ausgeführt, so ist die Gesamtlaufzeit das Maximum der Laufzeiten.

Beispiel: Laufzeit A ist O(n2), Laufzeit B ist O(n) Laufzeit A,B = O(n2) + O(n) = O(n2)

Wird ein Teil A mit Laufzeit O(x) innerhalb eines Teiles B mit Laufzeit O(y) ausgeführt, so ist die Gesamtlaufzeit das Produkt der Laufzeiten.

Beispiel: Laufzeit A ist O(n2), Laufzeit B ist O(n) Laufzeit A(B) = Laufzeit B(A) = O(n2) O(n) = O(n3)

Beispiel: Eine Dreifach verschachtelte Schleife (O(n3)) ist eineSchleife O(n) in einer zweifach verschachteltenSchleife (O(n2)) : O(n3) = O(n2) O(n)

Page 49: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.5 Quantitatives

n ld n (ld n)2 n n ld n n2

10 3 9 3 30 100

100 6 36 10 600 1000

1000 9 81 31 9000 1000000

10000 13 169 100 130000 108

100000 16 256 316 1,6 106 1010

1000000 19 361 1000 19 106 1012

Page 50: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.6 Platzbedarf

Unter „Aufwand“ wird i.A. der zeitliche Aufwand, also die Zeitkomplexität verstanden

Manchmal ist auch die Platzkomplexität bzw. Speicherbedarf relevant.Darunter versteht man dann, ganz entsprechend zur Zeitkomplexität, eine obere Schranke für den Speicherbedarf eines Algorithmus für ein Problem mit einer Eingabemenge der Größe n.

Auch beim Speicherbedarf von Algorithmen existieren die „Komplexitätsklassen“ (n, n2, n log n, ...)

Auch beim Speicherbedarf unterscheiden sich „geschickte“ und „ungeschickte“ Algorithmen für die Lösung eines gegebenen Problems.

Da Computerspeicher endlich, die Zeit aber potentiell unendlich ist hat der Speicherbedarf oft die höhere Priorität.

Meist wird daher der Algorithmus gewählt, der sehr Nahe am minimal möglichen Speicherbedarf bei möglichst optimalem Aufwand liegt.

Page 51: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.3.6 Platzbedarf

Oft kann man eine bessere Zeitkomplexität zu Lasten des Speicherbedarfs erreichen (und umgekehrt)

Beispiel: Trivialer Hashsort (Unsortierte Liste a: array [1..n] of type)b: array [1..max(type)]// max(type) is largest element in type,// e.g. max(unsigned integer) = 65535i,j : integer;for i=1 to n { b[a[i]] = a[i];}j = 1;for i=1 to max(type) { // shift to beginning of list if ((not_empty(b[i])) and (i<>j)) then { b[j]=b[i]; j=j+1;}}

1.Schleife + 2.Schleife: O(n) + O(1) = O(n)

Man wägt daher Speicherbedarf und Zeitkomplexität gegeneinander ab.

Page 52: Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten

6.4 Zusammenfassung des Kapitels

Berechenbarkeit:1. Einige Fragen und das Entscheidungsproblem

2. Die Turing-Maschine und der Begriff der Berechenbarkeit

3. Rekursive Funktionen und die Church‘sche These

Korrektheit1. Ansatz und Definition

2. Logik zur Verifikation: Die Hoare‘schen Regeln

3. Beispiele und Beweis des Euklid‘schen Algorithmus

4. Kritische Anmerkungen

Komplexität1. Wie „gut“ ist ein Algorithmus und die O-Notation

2. Häufige O-Ausdrücke und einige Regeln bei deren Anwendung

3. Quantitatives

4. Platzbedarf