Drei Semester sind schon wieder ins Land gegangen seit meinem ersten Aufruf zu mehr Sorgfalt beim Verwenden mathematischer Symbole. Es war natürlich nur ein Tropfen auf den heißen Stein. Noch immer kann die Einstellung "`Das wollen wir jetzt mal nicht so genau nehmen."', zu deutsch: "`Korrekte Schreibweisen würde doch sofort jeder verstehen!"', einen großen Fanclub um sich vereinen. Es ist also an der Zeit, neues Futter nachzuschieben. Wie wäre es zur Abwechslung mit der beliebten -Notation?
Wir wollen die Laufzeiten verschiedener Algorithmen bei verschiedenen Eingaben untersuchen,
und weil wir über diesen Zusammenhang jetzt öfter sprechen werden,
geben wir ihm einen Namen:
Um die Laufzeiten bestimmter Algorithmen zu vergleichen, hat man die Symbole , , eingeführt. In der Mathematik verwendet man die ähnlichen Landau-Symbole und oder auch , . Nehmen wir ein Beispiel:
"` braucht zur Lösung seines Problems im Großen und Ganzen weniger als oder genau so viel Zeit wie "'durch
Fangen wir von vorne an. Es ist zum Beispiel sinnvoll als "`kleiner als oder gleich"' zu bezeichnen, wenn der Algorithmus bei jeder Problemgröße mindestens genaus so schnell wie Algorithmus ist, kurz:
Eigentlich können wir aber ganz gut damit leben, wenn erst bei großen Problemen schneller als ist, denn erst bei großen Problemen und mithin langen Laufzeiten wird es kritisch. Begnügen wir uns damit, dass es ein gibt, ab dem immer kleiner als ist:
Zum Schluss wollen wir noch ein weiteres Auge zudrücken (mehr als zwei haben die meisten von uns ohnehin nicht (Hühneraugen, Fettaugen, Würfelaugen zählen nicht mit!)) und es zudem tolerieren, wenn Algorithmus um einen konstanten Faktor langsamer ist als , weil wir uns zum Beispiel nicht darauf festlegen wollen, wie lange die Grundoperationen in den Algorithmen und dauern. könnte zum Beispiel mit Multiplikationen zum Ziel kommen und mit Hilfe von Vergleichsoperationen. Um wie viel schneller Vergleiche als Multiplikationen sind, wollen wir also offen lassen und in einer nebulösen Konstanten zusammenfassen. Damit wären wir angelangt bei:
Das werden wir nun als Definition für unser verwenden:
So in etwa läuft meistens die Einführung dieses Symbols in der Informatik-Vorlesung ab, dann aber passiert nicht selten etwas ganz scheußliches: Der Dozent meint, dass er ab jetzt der korrekten Schreibweise
Es gilt offensichtlich (mit der "`vereinfachten"' Notation)
| ||
Wenn "`="' eine Äquivalenzrelation bezeichnet, gilt die Symmetrie, konkret
| ||
und die Transitivität
| ||
In diesem Beispiel war der Fehler offensichtlich, denn wenn man korrekt
Nehmen wir der Vollständigkeit halber noch die Definitionen der anderen beiden Funktionsmengen hinzu:
Eine Äquivalenzrelation zwischen Funktionen und Funktionenmengen zu basteln ist sicher nicht so glorreich, aber vielleicht bekommt man eine Äquivalenzrelation zwischen zwei Funktionen zu Stande. Die Relation
Bleiben wir im Folgenden besser bei der korrekten Schreibweise mit dem Enthaltensein-Zeichen. Sie liefert im übrigen auch den Vorteil, viele sonst geläufige Notationen im Zusammenhang mit Mengen direkt weiterverwenden zu können.
Lasst uns doch mal schauen, was man noch für Unfug mit dieser -Notation anstellen kann. Mit kann man alle Laufzeitfunktionen bezeichnen, welche zu Algorithmen gehören, deren Bearbeitungszeit überhaupt nicht von der Größe des Problems abhängt. Diese kann man guten Gewissens als Grundoperationen bezeichnen. Beispielsweise benötigt ein Rechner für die Addition zweier Zahlen immer die gleiche Zeit (sofern die Addition überhaupt korrekt, also ohne Überlauf ausführbar ist). Benötigt die Addition in der Wirklichkeit Sekunden, dann setzt man in der Definition von eben , und es ist sofort klar, dass die zur Addition gehörige Laufzeitfunktion in enthalten ist.
Auf die gleiche Weise überprüft man leicht, dass folgende Beziehungen
gelten:
Um nicht in Konflikt mit den Variablennamen in der Definition von zu kommen, benennen wir in um und skizzieren nun den Beweis für . Die Behauptung ist also:
Manche Dozenten mögen diese simple Tatsache (in Worten: ) nicht einsehen, aber sie stimmt einfach, wir haben doch den Beweis! Ja aber ...das kann doch nicht stimmen! Das widerspricht doch dem gesunden Menschenverstand!
Ich räume zumindest ein, dass es unserer Intuition widerspricht. Aber an welcher Stelle hat uns die Intuition auf das Glatteis geführt? Kommt Ihr selber darauf? Argh, wie ich Euch kenne, habt Ihr heute sicher keine Lust zum Nachdenken und lest einfach weiter.
Sei's drum. Das Problem ist bereits die Uneindeutigkeit der Notation . In durchdachten Programmiersprachen wie Modula ist man gewohnt, den Typ einer Variablen genau festzulegen und sich nachher auch daran halten zu müssen, bei C/C++ muss man ihn nur noch festlegen, sich aber nicht daran halten (characters, booleans, integers, sets (welche als integers implementiert werden müssen) dürfen alle bunt durcheinandergewürfelt werden), na und bei Skriptsprachen gibt es gleich gar keine Deklarationen mehr. Die Strafe folgt auf dem Fuße:
Ihr habt in wahrscheinlich einen Ausdruck gesehen, der von abhängt, eine lineare Funktion also. Warum aber? hängt doch auch von jeder anderen denkbaren Variable ab, wie zum Beispiel . ist bezüglich konstant, also ist eine konstante "`Funktion"', und deswegen hat auch mein Beweis geklappt. Wenn wir genau hinschauen, stellen wir aber fest, dass überhaupt keine Funktion ist! Ursprünglich hatte ich zur natürlichen Zahl erklärt, und natürliche Zahlen sind ganz gewiss keine Funktionen. Zwar steht es einer Funktion frei, immer dieselbe natürliche Zahl zurückzuliefern (also ), aber die Funktion an sich ist eben nicht identisch mit der Zahl . Die Funktion beschreibt nur die Tatsache, dass ein paar bestimmte Argumente in ein paar bestimmte Ergebnisse überführt werden.
Beispielsweise kann eine Funktion so beschaffen sein, dass sie das übergebene Argument quadriert. Die Funktion, die dazu das übergebene Argument mit sich selbst multipliziert, könnte man nennen. Eine andere Funktion , die für alle Argumente die ungeraden Zahlen von bis addiert, erledigt das Gleiche. Es gilt also
In der Analysis gibt es das gleiche Theater, weil zum Beispiel die Bezeichnung für die partielle Ableitung einer Funktion voraussetzt, dass eine bestimmte "`Dimension"' mit bezeichnet ist. Dummerweise verwendet man dann aber auch gleich weiter als Variable, die die Stelle bezeichnet, an der man die Ableitung wissen möchte, etwa . Das führt spätestens dann zum Chaos, wenn man noch mit einem weiteren Wert auf der -Achse, vielleicht oder arbeiten möchte. Ebenso ist bei Funktionen in mehreren Veränderlichen oft nicht genau zu erkennen, über welches Funktionsargument sich eigentlich ein Skalarprodukt oder eine Norm erstreckt. Oder es gibt Schwierigkeiten, weil bei der unbestimmten Integration der gleiche Bezeichner als Integrationsvariable und als Argument der entstehenden Stammfunktion eingesetzt wird:
Wieder zurück zum -Symbol. Wie können wir denn nun das Beispiel mit der quadratischen Funktion retten? Man könnte vielleicht den Kunstgriff ansetzen, und als Identitätsfunktion deklarieren, also
Man kann aber auf eine der vielfältigen Schreibweisen zurückgreifen, welche Terme in Funktionen konvertieren. Die Operation, mehrere Werte zu einer Funktion zusammenzufügen, ist gewissermaßen die Umkehrung zum Einsetzen eines Funktionsargumentes und Ablesen des Funktionswertes.
Jo, wer nicht mutig genug ist, eine der obigen Methoden zu verwenden, der muss eben zu Fuß zwei Funktionen einführen, um wieder zum Beispiel zurückzukommen und , die eine linear, die andere quadratisch, also
...doch nein, da braut sich schon wieder eine neue Gewitterwolke zusammen! Der Kampf zwischen und ist noch nicht entschieden! Gebt mir noch einen Versuch, und ich beweise Euch endgültig, dass nichts als die Wahrheit ist ( und wie eben vorgeschlagen)!
Dazu brauchen wir die vollständige Intuition (na Ihr wisst schon, wie es
richtig heißt) und folgendes
Nur als Hinweis: Mit Beendigung des Lemmas haben wir auch den Sichtbarkeitsbereich für die lokalen Bezeichner des Lemmas wie , und verlassen und und sind wieder unsere beiden Funktionen, die lineare und die quadratische.
Ich werde mir jetzt eine Folge von Funktionen definieren. Die erste Funktion wird die Identitätsfunktion sein. Diese ist ihrerseits identisch zu und damit auch in enthalten. Alle weiteren Funktionen streben gegen die quadratische, bleiben aber trotzdem in ! Jede Funktion der Folge besteht bis zur Stelle aus der quadratischen Funktion und geht danach mit dem gleichen Anstieg in eine lineare Funktion über:
Nun zum
Induktionsschritt Induktionsvoraussetzung
Bis einschließlich zur Stelle sind und identisch, bis dort kann man also den Faktor ansetzen. Nach der Stelle gehen die beiden Funktionen in bzw. über.
Das heißt, dass wir ab der Stelle den Faktor benötigen, welcher im "Ubrigen größer als ist. Deswegen ist der Gesamtfaktor . Damit ist gezeigt, dass
gilt, und mit der Induktionsvoraussetzung
| ||
erhalten wir über unser Lemma die Induktionsbehauptung
| ||
Da seid Ihr baff, was? Ich habe jetzt jedenfalls die Nase voll, und wenn jemand von Euch des Rätsels Lösung herausfindet, kann er diese an mich schicken!
Kleiner Tip: Versucht bei dem Beweis einmal ohne Induktion auszukommen.