Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

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

Ähnliche Präsentationen


Präsentation zum Thema: "Kapitel 6Algorithmentheorie Im vorangegangenen Kapitel wurde beschrieben, mit welchen Elementen Algorithmen aufgebaut werden, und was man dabei zu beachten."—  Präsentation transkript:

1

2 Kapitel 6Algorithmentheorie 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 fassbar 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, 2001

3 6.1Berechenbarkeit 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.Churchsche These H. Ernst:Grundlagen und Konzepte der Informatik,Vieweg-Verlag,2000

4 6.1.1Einige 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

5 6.1.2Das Entscheidungsproblem Bis weit ins 20ste Jahrhundert war die Mehrzahl der Mathematiker (insb. David Hilbert: ) 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 entscheibar 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.

6 6.1.3Die Turing-Maschine: Definition Als abstraktes Modell eines Computers beschrieb Alan Turing ( ) also noch vor der Erfindung des Digitalrechners - eine nach ihm benannte abstrakte Maschine Formal kann eine Turing-Maschine wie folgt beschrieben werden: Alphabet: A = {a 0,..., a n }, der Zeichenvorrat der Turing-Maschine, wobei a 0 das Leerzeichen ("blank") darstellt (Oft: a 1 =0, a 2 =1) Bandinschrift: B: Z A eine Zuordnung, die jeder Stelle des rechtsseitig unendlichen Bandes ein Zeichen zuordnet. Dabei wird festgesetzt, dass B(k) = a 0 für alle bis auf endlich viele. Kopfposition: k Z Zustände: eine endliche Menge von Maschinenzuständen.Q = {q 0,..., q m } Darunter sind q 0, 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}, das jedem (gelesenen) Zeichen in Abhängigkeit eines Zustandes ein neues Zeichen, einen Folgezustand und eine Aktion (r,l,n} zuordnet

7 6.1.3Die Turing-Maschine: Programm Die Aktion: "a j " das Überschreiben des unter dem Kopf befindlichen Zeichens durch a j, r: das Verschieben des Kopfes nach rechts l: das Verschieben des Kopfes nach links. a1a1 a2a2 a3a3 a4a4...a6a6 falls die Maschine im Zustand das unter dem Kopf gelesene Zeichen so ist die Aktion der neue Zustand q q a j, r oder lakak

8 6.1.3Die Turing-Maschine: Beispiel Das Busy beaver-Problem: Wieviele 1-en kann ein terminierendes Touring-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 en (J.Buntrock, H.Marxen, 1989) Es wurde gezeigt, dass es möglich ist, mehr als en zu generieren - allerdings nicht wie. 11 Schritte, 6 Einsen 96 Schritte, 13 Einsen

9 6.1.4Definition: Berechenbarkeit Ein Problem ist genau dann algorithisch 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

10 6.1.5Beispiel: 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, und für beliebige gegebene Eingabeparameter entscheidet, ob das gegebene Programm anhält. Beweis:Geg. Programm P mit Quelltext(P) als Eingabe Annahme:Es gibt ein solches Programm (Test) Test(P) janein P stoppt mit P yn Test1(P) stoppe Test = ja yn Test(P) Test(Test1)=ja Test1(Test1) läuft endlos Test(Test1)=nein Widerspruch !

11 6.1.6Rekursive 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

12 6.1.6Churchsche 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 Turingmaschinm, die wiederum eine Abstraktion eines Computers darstellt Dies legt die Formulierung einer der Churchschen 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 Churchsche These nicht beweisbar.

13 6.2Korrektheit 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 Inhalt 1.Ansatz 2.Definition 3.Logik zur Verifikation (C.A.R. Hoare) 4.Regeln 5.Terminierung 6.Beispiele 7.Beweis des Euklidschen Algorithmus 8.Kritische Anmerkungen U.Kastens:Modellierung, Vorlesung WS00/01, Uni Paderborn

14 6.2.1Ansatz 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 Z i (V) zur Nachbedingung abgeleitet Also: P(V) Z 1 (V)... Z n (V) Q(V)

15 6.2.2Definition: Korrektheit Beispiel: Lösung der quadratischen Gleichung qugl (IN: p,q: real, OUT x1,x2:real) // Vorbedingung: (p*p)/4 > q // Nachbedingung: x1 = (-b + sqr(p*p/4-q)) / (2*a) // x2 = (-b - sqr(p*p/4-q)) / (2*a) { 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.

16 6.2.3C.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

17 6.2.3C.A.R. Hoare: Beispiel min (IN: a,b: integer, OUT min:integer) // Vorbedingung: a,b > 0 (nicht unbedingt notwendig) // Nachbedingung: (min=a min=b) (min a) (min b) { if a

18 6.2.3C.A.R. Hoare: Vorgehen Aussagen über den Algorithmenzustand, über Werte von Variablen werden in den Algorithmus eingefügt: { P } A1 { Q } A2 { R } bedeutet: Q 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 + 1 0} 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:

19 6.2.4Regel: 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}

20 6.2.4Regel: Zuweisung - Beispiele {P[x/expr]} x := expr {P} alle Aussagen der Vorbed. für expr, gelten für x in der Nachbedingung Aussagen der Vorb. über x gelten in der Nachbedingung nicht mehr 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) 1.{y=5}x=y{x=5} 2.{a>0 x>7}x=a{x>0 x>7}falsch ! 3.{a>0 z>0}x=a{x>0 z>0}z>0 ist nicht betroffen 4.{i+1>0}i=i+1{i>0} 5.{i 0} {i+1>0}i=i+1{i>0}passend umformen 6.{i=2} {i+1=3}i=i+1{i=3}passend umformen 7.{z=5}x=1{z=5 x=1}z nicht betroffen, x neu

21 6.2.4Regel: Konsequenz Abschwächung der Nachbedingung wenn giltunddann gilt auch {P} S {R} {R} {Q}{P} S {Q} Beispiel {a+b>0} S {x>0}{x>0} {X 0} {a+b>0} S {X 0} Verschärfung der Vorbedingung wenn giltunddann 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 {y 0}

22 6.2.4Regel: Sequenz Folgendes Schema lässt sich auf eine Sequenz von Aktionen (Statements) anwenden: wenn giltunddann gilt auch {P} S {R} {R} S 2 {Q} {P} S 1,S 2 {Q} Beispiel: {x>0 y>0} a = x; {a>0 y>0} {a>0 y>0} {a>0 y>0} b = y; {a>0 b>0} Bei trivialen Ableitungen können die Zwischenschritte (Zusicherungen, Aussagen) auch weggelassen werden: {x>0 y>0} a = x; b = y; {a>0 b>0}

23 6.2.4Regel: Bedingte Anweisung Schema: wenn giltunddann gilt auch {P B} S {Q} {P B} {Q} {P} if B then S {Q} Um die Nachbedingung einer bedingten Anweisung zu beweisen, muss 1.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 a 0 für alle a liefert: 1.{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}

24 6.2.4Regel: Bedingte Anweisung - Notation Beispiel: Gegeben: if a<0 then a = -a Beweise, dass der Algorithmus a 0 für alle a liefert: 1.{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} a = -a {P a>0} {P a 0} // leere Alternative: {P (a<0)} {P a 0} {P a 0}

25 6.2.4Regel: Einfache Alternative Schema: wenn giltunddann gilt auch {P B} S 1 {Q} {P B} S s {Q} {P} if B then S 1 else S 2 {Q} Aus der gemeinsamen Vorbedingung P muss für beide Alternativen dieselbe Nachbedingung Q nachweisbar sein Beispiel: Gegeben: a>0, b>0, a b und ein Algorithmus (s.u) Beweise, dass nach den Operationen immer noch gilt: a>o, b>0 {a>0 b>0 a b} if a>b then {a>0 b>0 a b a>b} {b>0 a-b>0} a = a-b; {b>0 a>0} else {a>0 b>0 a b a b} {a>0 b-a>0} b = b-a; {a>0 b>0} {a>0 b>0}

26 6.2.4Regel: Schleife Schema: wenn giltdann gilt auch {P I B} S {P} {I} while B { S } {I B Q}// I = Schleifeninvariante Schleifeninvarianten sind Zusicherungen in Schleifen, die beim Durchlaufen des Schleifenkörpers erhalten bleiben. Es gelte PZusicherung über Variable vor Schleifeneintritt QZusicherung über Variable nach Schleifenende ISchleifeninvariante BWiederholbedingung der Schleife SStatements (Aktionen) im Schleifenkörper Die Nachbedingung einer Schleife ist über die Invariante nachgewiesen nachzuweisen, wenn gilt: P I die Invariante muss vor Schleifeneintritt wahr sein (I B) Idie Invariante darf in Schleife nicht verändert werden (I B) Qdie Nachbedingung muss sich nach Verlassen der Schleife aus der Invariante nachweisen lassen

27 6.2.4Regel: Schleife - Schema Das Schema der Gültigkeit von Aussagen sei anhand des Flussdiagramms für Schleifen verdeutlicht: B ? S P I I B I f w Q(V) Um Q(V) zu beweisen, muss man also I(V) so wählen, dass Q(V) aus I(V) B(V) ableitbar ist

28 6.2.4Regel: Schleife - Beispiel Algorithmus zum Potenzieren // Vorbedingung: b 0 (positive Exponenten) // Nachbedingung: z = a b x=a, y=b, z=1; { x=a, y=b, z=1; y 0} {INV: z * x y = a b y 0} while y>0 { { INV y>0 z*x (y-1)+1 =a b (y-1)+1 > 0 } y = y-1; { z*x y +1 =a b y+1>0 } { ((z*x)/x)*x y +1 = a b y 0 } z = z*x; { z/x*x y +1 = a b y 0 } { z * x y = a b y 0 INV } } { INV B z * x y = a b y 0 y 0 z*x 0 = z = a b Q } B ? S P I I B I f w Q

29 6.2.4Regel: Schleife - Schleifeninvariante Das Finden der richtigen Invariante kann ganz schön kniffelig sein: Ein paar Tips: Gegeben:Vorbedingung b 0 Zu beweisen:Nachbedingung z = a b 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 * x y Setze Ein- und Ausgabevariablen in Bezug zueinander z * x y = a b Beachte, dass aus INV und B(V) Q(V) ableitbar sein soll Das bedeutet, dass man die In variante aus der Nachbedingung konstruieren kann, indem man die negierte Bedingung mit berücksichtigt z * x y = a b y=0 z*x 0 = z = a b Q

30 6.2.5Terminierung 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 0 E 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 R B eine Invarianz der Schleife ist (also R in die Schleife geht) und dass es eine Variablenbelegung gibt, so dass R B 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.

31 6.2.5Terminierung - Beispiele { a>0 b>0 } while a b { while a>b { a=a-b } while a0 b>0 } while a b { while a b { a=a-b } while a1 } while n>1 if n gerade then n = n/2 else n=3*n+1 // Terminierung unbewiesen

32 6.2.6Beispiel: Multipl. durch fortgesetze Addition // Vorbedingung P: a 0 b 0, Beh.: Nachbedingung Q: z = a*b x = a; y = b; z = 0; { x 0 b 0 z=0 } // Auch hier: Die Summe von x*y+z bleibt konstant a*b { INV: z+xy = ab, x,y 0 } while x > 0 { { INV x>0 } { (z+y)-y+xy = ab, x>0,y 0 } z = z + y; { z-y+xy = ab, x>0,y 0 } { z-y+((x-1)+1)y = ab, (x-1)+1>0,y 0 } x = x - 1; { z-y+(x+1)y = ab, x+1>0,y 0 } { z-y+xy+y = z+xy = ab, x,y 0 } INV } { INV B = (z+x*y=a*b) (x=0) z+0*y=a*b Q } B ? S P I I B I f w Q

33 6.2.6Beispiel: Die ägyptische Bauernmultiplikation // Vorbedingung P: a 0 b 0, Beh.: Nachbedingung Q: z = a*b x = a; y = b; z = 0; { x,y 0 z=0 x=a y=b } // Schleife verdoppelt x und halbiert y: Invariante: INV INV = { z+x*y = a*b x,y 0 } while x > 0 { { INV x>0 } if (odd(x) then { (z+y)-y+x*y = a*b) x>0,y 0 } z = z+y; { odd(x) z-y+x*y = a*b x>0,y 0 } // leere Anweisung { even(x) z+x*y = a*b x>0,y 0 } { 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/2 0 even(x) z+x*y/2 = a*b x>0,y/2 0 } { odd(x) z-y/2+(2(x div 2)+1)*y/2 = a*b (2(x div 2)+1)>0,y 0 even(x) z+(2(x div 2))*y/2 = a*b 2(x div 2) >0,y 0 } x = x div 2; // div = Ganzzahldivision { odd(2x+1) z-y/2+(2x+1)*y/2 = a*b (2x+1)>0,y/2 0 even(2x) z+ 2x *y/2 = a*b 2x >0,y/2 0 } { 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 }

34 6.2.6Beispiel: Euklidscher Algorithmus (ggT) // Vorbedingung P: a>0 b 0, Beh.: Nachbed. Q: x=ggT(a,b) x = a; y = b; // Z 1 : x>0 b 0 // Die Summe von x*y+z bleibt konstant a*b { INV: (ggT(x,y) = ggT(a,b)) (x>0 y 0) } while y > 0 { { INV (y>0) } r = x mod y; // r ist Rest aus x/y x = y; y = r; { ggT(y,x mod y) = ggT(x,y) = ggT(a,b) } { INV } } // I(A) B(V) = (ggT(x,y) = ggT(a,b)) (y=0) // (ggT(x,0) = x = ggT(a,b)) = Q(V)

35 6.2.7Beweis Euklidscher Algorithmus I Zu beweisen: ggT(y,x mod y) = ggT(x,y), x>0, y 0 Der Beweis stützt sich auf einen Hilfssatz, der zunächst bewiesen wird Hilfssatz: Seien a 0, b. Dann gilt für alle d ( |: Ist Teiler von) a)d | a d | b d | (a mod b) b)d | b d | (a mod b) d | a Beweis: a)Es sei a mod b = r. Dann ist a - r durch b teilbar. Also ist a - r auch durch d teilbar. Da a durch d teilbar ist, muss auch r durch d teilbar sein, also gilt d | (a mod b). b)Wiederum sei a mod b = r. Dann ist a - r durch b und damit durch d teilbar. Da r durch d teilbar ist, muss auch a durch d teilbar sein, d.h. es gilt d | a.

36 6.2.7Beweis Euklidscher Algorithmus II Beweis: Es wird gezeigt, dass ggt(a, b) und ggt(b, a mod b) sich gegenseitig teilen und daher gleich sein müssen. 1.Sei d = ggt(a, b). Dann gilt d | a und d | b und nach dem Hilfssatz d | (a mod b) Nach Definition des ggt gilt d | b d | (a mod b) d | ggt(b, a mod b) 2.Sei nun umgekehrt d = ggt(b, a mod b). Dann gilt d | b und d | (a mod b) und nach dem Hilfssatz d | a Nach Definition des ggt gilt d | a d | b d | ggt(a, b) Mit1. d=ggt(a,b) | ggt(b,a mod b) und 2. d=ggt(b,a mod b) | ggt(a,b) ist gezeigt, dass ggt(a, b) = ggt(b, a mod b)

37 6.2.8Kritische 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 Programmes) 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-Engineerings.

38 6.3Komplexitä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. Inhalt 1.Wie gut ist ein Algorithmus 2.Die O-Notation 3.Häufige O-Ausdrücke 4.Einige Regeln 5.Quantitatives 6.Platzbedarf

39 6.3.1Qualität eines Algorithmus Die Abarbeitung eines Algorithmus benötigt Resourcen, vor allem: ZeitLaufzeit des Algorithmus PlatzSpeicherplatzbedarf des Algorithmus Problem bei der Resourcenermittlung - der Resourcenbedarf 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 Resourcenbedarf festmachen (aber das ist eine andere Geschichte...) Wartbarkeit Robustheit Eleganz...

40 6.3.2Die 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 n 0 gibt, so dass: g(n) c f(n), für fast alle n > n o ist f(n) ist damit eine obere Schranke für die Laufzeit des Algorithmus (allerdings nur ab einem bestimmten c und n 0 ) Beispiel: Bei der Analyse eines Algorithmus hat sich herausgestellt, dass die Laufzeit g(n) = 3n 2 + 7n - 1 ist. Behauptung: Die Laufzeit von g(n) ist O(n 2 ), also f(n)=n 2, Beweis: Es muss Konstanten c und n 0 geben, so dass gilt 3n 2 +7n-1 c n 2, für alle n > n 0 setze n 0 =7 und c=4, dann gilt: 3n 2 +7n-1 3n 2 +7n 3n 2 +n 2 = 4n 2

41 6.3.2Die 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) = 3n 2 + 7n - 1 ist auch O(n 3 ), 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: lim n h(n)/f(n) = 1 Eine untere Schranke ist die Zeit, die jeder Algorithmus (ab einem n>n 0 ) benötigt Das ist im Allgemeinen viel schwieriger !

42 6.3.2Die O-Notation: Achtung Achtung ! Die Konstanten c und n 0 werden üblicherweise nicht angegeben und können sehr groß sein Beispiel: Algorithmus A habe eine Laufzeit von O(n 2 ) Algorithmus B für das gleiche Problem eine Laufzeit von O(1,5 n ) 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 c A =1000 und c B =0,001 nc A n 2 c B 1,5 n , , ,3 502, , , Bis hier ist B besser als A

43 6.3.3Häufige O-Ausdrücke: O(1) - konstanter Aufwand 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) Beispiel: max, i, y : integer; max = 0; y << Tastatur; if (y < 20) then max=10 else 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)

44 6.3.3Hä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 b = c log b ist O(ld b)=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.right,found) else if (n == node.value) found=true; } Zeitbedarf: T n = T n/2 +1 (T n = Zeitbedarf für n, n 2, T 1 =0) Annahme (o.B.d.A.): n = 2 k, T 2 k = T 2 k-1 +1 = T 2 k =... = T k = k T n = k = ld n

45 6.3.3Hä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

46 6.3.3Hä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 Ende search (IN: x:integer; list:*liste; OUT: found:boolean) { i : integer; found = false; // initialize OUT-value i=1; while (list[i] <> 0)) { i=i+1; } if (list[i] == 0) then found = false; else found = true; } Anmerkung: Dieser Algorithmus funktioniert auch mit unsortierten Listen Warum dann einen rekursiven, teilenden Algorithmus ? Anzahl eingeschränkter Vergleiche O(n) Anzahl vollständige Vergleiche O(log n)

47 6.3.3Hä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: T n = 2T n/2 + 1 (T n = Zeitbedarf für n, n 2, T 1 =0) Annahme (o.B.d.A.): n = 2 k, T 2 k = 2T 2 k /2 T 2 k = T 2 k-1 + 1/2 = 2T 2 k /2 1/4 T 2 k = T 2 k-2 + 1/2 + 1/4... 1/2 k T 2 k = T /2 + 1/ /2 k = 1 - 1/2 k T 2 k = 2 k -1 T n = n-1 Laufzeit O(n)

48 6.3.3Hä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 index i,j,x : integer; // i,j: indexes, x,y: elemets i=l; j=r; // initialize i with left, j with right index x = a[(l+r)/2}] // get element in the middle repeat { // walk with i from left, with j from right while a[i] o { j=j-1 } // skip larger elements from right if (i j // i is now right of j -> stop loop if l

49 6.3.3Häufige O-Ausdrücke: O(n 2 ) - rekursiv Rekursive Algorithmen, die die Eingabedaten jeweils um eins verringern, dabei aber alle Daten betrachten müssen, haben eine Laufzeit von O(n 2 ) 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

50 6.3.3Häufige O-Ausdrücke: O(n 2 ), O(n 3 ) - 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(n 2 ) 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]

51 6.3.4Einige Regeln Hat ein Algorithmus eine Laufzeit, die mit einem Polynom k-ten Grades darstellbar ist (a k n k + a k-1 n k a 0 ), so ist die Laufzeit O(n k ) Beispiel:Laufzeit: 9n 3 + 7n Laufzeit O(n 3 ) 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(n 2 ), Laufzeit B ist O(n) Laufzeit A,B = O(n 2 ) + O(n) = O(n 2 ) 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(n 2 ), Laufzeit B ist O(n) Laufzeit A(B) = Laufzeit B(A) = O(n 2 ) O(n) = O(n 3 ) Beispiel:Eine Dreifach verschachtelte Schleife (O(n 3 )) ist eine Schleife O(n) in einer zweifach verschachtelten Schleife (O(n 2 )) : O(n 3 ) = O(n 2 ) O(n)

52 6.3.5Quantitatives nld n(ld n) 2 nn ld nn ,

53 6.3.6Platzbedarf 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, n 2, 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.

54 6.3.6Platzbedarf 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) = i,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.

55 6.4Zusammenfassung des Kapitels Berechenbarkeit: 1.Einige Fragen und das Entscheidungsproblem 2.Die Turing-Maschine und der Begriff der Berechenbarkeit 3.Rekursive Funktionen und die Churchsche These Korrektheit 1.Ansatz und Definition 2.Logik zur Verifikation: Die Hoareschen Regeln 3.Beispiele und Beweis des Euklidschen Algorithmus 4.Kritische Anmerkungen Komplexität 1.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

56 Übung 6.1Turing-Maschine 1.Machen Sie sich mit der Funktionsweise des Busy Beaver- Programms vertraut Vollziehen sie die 11 Schritte der ersten Turing-Tebelle. 2.Versuchen Sie sich selbst am Turing Simulator der IGS (Link auf meiner Homepage) 3.Entwerfen Sie eine Turing-Maschine zur Multiplikation zweier natürlicher Zahlen.

57 Übung 6.2 Einfache Verifikation Gegeben ist folgender Algorithmus {a 0, c>0} // Vorbedingung P(a,b,c) a=b; d=b-a; if (c == 0) then d=5; else d=d+1; 1.Geben Sie eine Nachbedingung Q(d) für die Variable d an 2.Beweisen Sie dass sich durch den Algorithmus aus P(a,b,c) diese Nachbedingung Q(d) ableiten lässt 3.Schreiben Sie einen zweiten Algorithmus, der ebenfalls die Nachbedingung Q(d) aus P(a,b,c) ableiten kann 4.Verifizieren Sie Ihren Algorithmus

58 Übung 6.3Denksportaufgabe 1.Gegeben sei folgendes Verfahren In einem Topf seien s schwarze und w weiße Kugeln - insgesamt mindestens eine. Solange mindestens zwei Kugeln im Topf sind, nimm zwei beliebige Kugeln heraus. Falls Sie gleiche Farbe haben, wirf beide weg und lege eine neue schwarze Kugel in den Topf. Falls sie verschiedene Farben haben, wirf die schwarze weg und lege die weiße zurück in den Topf. 1.Welche Farbe hat die letzte Kugel 2.Welche Aussage - die einen Hinweis auf die Antwort gibt - gilt vor, in und nach der Schleife (Invariante) 3.Terminiert die Schleife ? Begründen Sie ihre Antwort.

59 Übung 6.4Invariante 1.Betrachten Sie nochmals das Verfahren aus der vorgegangenen Übung: In einem Topf seien s schwarze und w weiße Kugeln - insgesamt mindestens eine. Solange mindestens zwei Kugeln im Topf sind, nimm zwei beliebige Kugeln heraus. Falls Sie gleiche Farbe haben, wirf beide weg und lege eine neue schwarze Kugel in den Topf. Falls sie verschiedene Farben haben, wirf die schwarze weg und lege die weiße zurück in den Topf. 1.Beschreiben Sie das Verfahren als Algorithmus 1.Das Nehmen dürfen Sie als Block voraussetzen. 1.Entwerfen Sie den Kopf dieses Blocks, 2.Beschreiben Sie seine Parameter 3.beschreiben Sie sein Verhalten in Form einer Vor- und Nachbedingung 2.Bestimmen Sie die Invariante 3.Beweisen Sie die Korrektheit Ihrer Nachbedingung

60 Übung 6.5Vollständige Verifikation 1.gegeben ist der folgende Algorithmus zum schnellen Potenzieren (Legendre Algorithmus) // Vorbedingung P(V): a>0 b 0 x = a; y = b; z = 0; while y > 0 { if odd(y) then z = z*x; y = y div 2; // Ganzzahldivision x = x*x; } 1.Was ist die Nachbedingung dieses Algorithmus 2.Bestimmen die die Schleifeninvariante 3.Beweisen Sie die Korrektheit de Legendre Algorithmus

61 Lösung 6.1.1Turing-Maschine Vollziehen sie die 11 Schritte der ersten Turing-Tebelle. 1,_ 2,1,> 1,1 3,1,< 2,_ 3,1,> 2,1 H,1,> 3,_ 1,1,< 3,1 2,_,< 4,_ H,_,> 4,1 H,_,> Ausgangszustand,Zeichen Folgezustand,schreibeZeichen,Aktion H H State

62 Lösung 6.1.2Turing-Maschine Eingabe der initialen Bandinschrift Eingabe der Turing-Tabelle Zustand x Zeichen Folgezustand x Zeichen x Aktion Beispiel: 1,_ 1,_,>

63 Lösung 6.1.3Turing-Maschine Aufgabenstellung Entwerfen Sie eine Turing-Maschine zur Multiplikation zweier natürlicher Zahlen. Spezifikation Eingabespezifikation Die Zahlen werden durch die entsprechende Anzahl von 1 am Band dargestellt Zwischen den Zahlen befindet sich ein x am Band Hinter der letzten Zahl ist ein =- Zeichen am Band Das restliche Band ist mit 0 beschrieben. Der Schreib/Lesekopf befindet sich links von der 1. Zahl. Ausgabespezifikation Das Ergebnis ist hinter dem =, durch eine entsprechende Anzahl von 1 darzustellen. Beispiel: Die zwei Zahlen 3 und 4 sind mittels eines Turing-Programmes zu multiplizieren

64 Lösung Lösung 6.1.3Turing-Maschine Idee: 1.Kopiere alles vor dem = (den 2.Multiplikator) ans Ende 2.Mache dies für jede 1 vor dem X (den 1.Multiplikator) Siehe Anhang C SucheStart0 0R 1SucheZahl20R SucheStartXEndZustandXL SucheZahl21 1R XZahl2StartXR 1GeheEnde0R Zahl2Start=Mach1Aus0=L GeheEnde1 1R =SucheNull=R 1 1R 0HolNaechsten11L 1 1L = =L 0Zahl2Start0R Mach1Aus00 1L XZahl1StartXL 1 1L 0SucheStart0R

65 Lösung 6.2 Einfache Verifikation Gegeben ist folgender Algorithmus {a 0, c>0} a=b; {a=b, b>0, c>0} d=b-a; {d=b-a, a=b, b>0, c>0} {d=0, b>0, c>0} if (c == 0) then {d=0, b>0, c>0, c=0} d=5; {d=5, b>0, falsch} {d=1} // aus falsch lässt sich alles folgern else {d=0, b>0, c>0, c<>0} {d+1=1, b>0, c>0} d=d+1; {d=1, b>0, c>0} {d=1, b>0, c>0} {d=1}

66 Lösung 6.3Denksportaufgabe 1.Denksportaufgabe 1. Welche Farbe hat die letzte Kugel ? Die Farbe der letzten Kugel ist abhängig von der Anzahl der weißen Kugeln: Ist die Anzahl gerade, so ist die letzte Kugel schwarz Ist die Anzahl ungerade, so ist die letzte Kugel weiß 2. Welche Aussage gilt vor, in und nach der Schleife (Invariante) Ist die Anzahl der weißen Kugeln gerade, so bleibt sie gerade Ist die Anzahl der weißen Kugel ungerade, so bleibt sie ungerade Es werden entweder 2 weiße Kugeln entfernt oder keine. 3.Terminiert die Schleife ? Begründen Sie ihre Antwort. JA. Die Anzahl der Kugeln vermindert sich bei jedem Zug um genau eine (nach Algorithmus: 2 nehmen, eine geben). Beim Erreichen von 2 Kugeln wird die Schleife noch einmal durchlaufen und terminiert mit einer Kugel.


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

Ähnliche Präsentationen


Google-Anzeigen