Effizienz von Algorithmen Letzte Bearbeitung: Jan 211 Ein wichtiger Aspekt bei Algorithmen sind seine "Kosten". Wir wollen uns hier ausschließlich mit der Laufzeit des gewählten Algorithmus beschäftigen. Neben der Laufzeit ist auch der Speicherbedarf eine wichtige Größe. Wir vereinbaren zunächst: Ein Algorithmus heißt effizient, wenn er "wenig" Betriebsmittel (Zeit, Speicherplatz) benötigt. Wir beschränken uns hier auf die Abschätzung für die Laufzeit des Algorithmus im schlechtest möglichen Fall. Vorgehensweise 1. Finde einen Algorithmus, der das gegebene Problem löst. 2. Finde, wenn möglich, einen effizienteren Algorithmus bezüglich seiner Laufzeit. Potenzbildung x n Wir wollen die Kosten der Potenzbildung x n bestimmen: x n = x x... x Wenn wir zur Berechnung eine Schleife einsetzen, sind n - 1 Multiplikationen durchzuführen. Wir untersuchen am Beispiel n = 13, ob die Potenzbildung mit weniger als 12 Multiplikationen erreicht werden kann. x 13 = x x12 = x (x 6 ) 2 = x ( ( x x 2 ) 2 ) 2 5 Multiplikationen Frage: Gibt es eine Mindestzahl von Multiplikationen, die nicht unterschritten werden kann? Start: Wir nehmen x (Grad 1 des Polynoms) Schritt 1: x x (Eine Multiplikation führt zu Grad 2) Wir besitzen nun die Zwischenresultate x und x 2 Schritt 2: Jede Multiplikation unter den Zwischenresultaten führt maximal zu Grad : x x, x x 2, x 2 x 2 7.2.11 / 1
Schritt 3: Wir gelangen durch Verwendung der neuen Zwischenergebnisse maximal zum Grad 8: x x Ergebnis Jeder Schritt führt maximal zu einer Verdopplung des Grades. Für n = 13 gilt Die untere Schranke zur Berechnung von x 13 besteht aus Schritten! Ob es einen Algorithmus mit Schritten gibt, ist damit nicht bewiesen. Mit weniger als Schritten kann es jedenfalls keinen Algorithmus geben. Aufgabe Für welche Exponenten werden die unteren Schranken erreicht? Wie viele Schritte sind für n = 2 (, 6, 8, 1) notwendig? 7.2.11 / 2
Berechnung von Polynomwerten Gegeben ist das Polynom 3x + 2x 3-5x 2 +6x + 2 Wie viele Rechenoperationen sind notwendig, um den Wert an der Stelle x zu berechnen? Idee Berechnung der Potenzen x 2, x 3, x Berechnung der Produkte 6x, -5x 2, 2x 3, 3x Berechnung der Summe 3x + 2x 3-5x 2 + 6x + 2 3 Multiplikationen Multiplikationen Additionen Wenn wir jede Addition und Multiplikation als einen Schritt bezeichnen, müssen wir 11 Schritte zur Berechnung ausführen. Schrittzahl S(n) für ein Polynom vom Grad n Berechnung aller Potenzen x 2, x 3, x... x n n -1 Schritte Berechnung aller Produkte: n Schritte Berechnung der Summe: n Schritte S(n) = 3n - 1 Schritte Wir erinnern uns an das Hornerschema zur Berechnung von Polynomwerten: Wir benötigen nur 8 Schritte ( Multiplikationen und Additionen)! 7.2.11 / 3
Allgemein Um zur Summe unter der Position a n-1 zu gelangen, benötigen wir eine Multiplikation mit x und eine Addition. Insgesamt sind n solcher Doppelschritte erforderlich, was zu S(n) = 2n führt, wobei n der Grad des Polynoms ist. Anmerkung: Im Jahr 195 bewies der Mathematiker OSTROWSKI, dass immer mindestens n Multiplikationen und n Additionen notwendig sind, d.h. das Hornerverfahren arbeitet optimal! Einen besseren Algorithmus kann es nicht geben. 7.2.11 /
Schritte eines Algorithmus Für ein Problem gibt es oft mehrere Algorithmen, welche das Problem lösen. Allerdings werden sich die Algorithmen in ihrer Laufzeit unterscheiden. Um den besten Algorithmus zu ermitteln, muss man Tests mit konkreten Eingabedaten durchführen, was sehr zeitaufwändig ist. Man kann dieses Verfahren erheblich abkürzen, wenn wir die Algorithmen einer mehr theoretischen Betrachtung unterwerfen. Theoretischer Weg Idee: Bestimme zu jedem Algorithmus die Zahl der Schritte, die er in Abhängigkeit von der Größe der Eingabedaten auszuführen hat. Algorithmus Schritte Eingabegröße Potenzieren Polynomwert berechnen 2n Exponent n Grad des Polynoms Wenn der Algorithmus mehr Schritte benötigt, wird auch die Laufzeit auf einer Maschine mehr Zeit beanspruchen! Deshalb sprechen wir auch unter Verwendung der Schrittzahl von der Laufzeit, dem Aufwand, der Zeitkomplexität des Algorithmus: Die Zeitkomplexität S(n) eines Algorithmus ist die Anzahl der Schritte, die der Algorithmus (im schlechtesten Fall) ausführen muss. Man spricht von der Laufzeit des Algorithmus. Anmerkungen Die Zeitkomplexität ist ein maschinenunabhängiges Maß, da sie die Zahl der Schritte erfasst. In vielen Fällen genügt eine Abschätzung der Schrittzahl für den Fall, dass die (für die Laufzeit) ungünstigsten Eingabedaten verwendet werden. Wir erhalten dann eine obere Schranke für die Laufzeit des Algorithmus, welche nicht überschritten wird (obere Schranke der Laufzeit). Wir versuchen nicht, die beste obere Schranke zu finden, die tatsächlich erreicht wird. Dies ist oft ein sehr schwieriges Problem, welches wir hier nicht betrachten wollen. Unsere Vorgehensweise ist die, dass wir durch grobe Abschätzung der Schrittzahl eine "sinnvolle" obere Schranke für die Laufzeit des Algorithmus ermitteln. Diese Schranke dient zur Klassifikation der Algorithmen (s. später). 7.2.11 / 5
Was verstehen wir unter einem Schritt? Ein Dauer eines Schrittes eines Algorithmus auf einer realen Maschine hängt davon ab, was in diesem Schritt passiert. Eine Multiplikation, eine Addition, der Vergleich zweier Zahlen, Kopieren von Variablenwerten,... Oft kennt man die Ausführungszeit nicht genau, da diese z.b. auch von der Größe der beteiligten Zahlen abhängt: Es ist nicht gleichgültig, ob die Maschine eine 32Bit-Zahl oder eine 6Bit-Zahl multipliziert. Wir gehen noch weiter: Uns interessiert die Dauer einer Maschineninstruktion nicht, trotzdem werden wir Aussagen über das Laufzeitverhalten eines Algorithmus machen können: Es ist uns sogar gleichgültig, ob der Schritt in einer Multiplikation, einer Division, dem Vergleich zweier Zahlen oder einer anderen Operation besteht. Wir sagen einfach: Der Algorithmus benötigt eine gewisse Anzahl von Schritten, unabhängig davon, dass diese Schritte auf einer realen Maschine unterschiedlich lange dauern. Wir definieren: Ein Schritt ist eine (abstrakte) Operation, bei der wir nicht mehr zwischen Multiplikation, Addition, usw. unterscheiden, da sich die Ausführungszeiten auf einer realen Maschine nur durch konstante Faktoren unterscheiden. Der Aufwand des Algorithmus ist die Anzahl S(n) der benötigten Schritte in Abhängigkeit von der Problemgröße n. Wir interessieren uns also nicht für die tatsächliche Laufzeit des Programms auf der Maschine, sondern für die Laufzeit des Algorithmus, die wir mit Hilfe der Schrittzahl S(n) erfassen. Wenn der Algorithmus mehr Schritte benötigt, wird auch seine Laufzeit auf einer Maschine mehr Zeit beanspruchen! Aus der Sicht der Schritte sprechen wir von der Zeitkomplexität (Laufzeit) des Algorithmus. Wenn wir den schlechtesten Fall für die Anzahl der Schritte betrachten, erhalten wir eine obere Schranke für die Laufzeit des Algorithmus. 7.2.11 / 6