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:
"`durchbraucht zur Lösung seines Problems im Großen und Ganzen weniger als oder genau so viel Zeit wie
"'
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.