Theoretische Grundlagen der Informatik - IMN/HTWK

Werbung
Prof. Dr. Karl–Udo Jahn
HTWK Leipzig
Fakultät Informatik, Mathematik und Naturwissenschaften
Vorlesungsbegleitende Folien zur Lehrveranstaltung
Theoretische Grundlagen der Informatik
im Wintersemester 2009/2010
Gliederung
ˆ Was ist Informatik?
ˆ Problemlösungsprozess
ˆ Literaturempfehlungen
1. mathematische Grundbegriffe
1.1 Mengenbegriff, Elementrelation, Teilmengenrelation, mengentheoretische Operationen
1.2 Abbildungen, Funktionen, Operationen, Mächtigkeit von Mengen
1.3 Relationen, Halbordnungs–, Ordnungs– und Äquivalenzrelationen
2. Bits und Bytes
3. Alphabete, Zeichenketten
4. gerichtete und ungerichtete Graphen
5. Variablen– und naiver Algorithmusbegriff; Notationsformen von Algorithmen
6. zwei Beispiele für Modellbildung und Abstraktion
6.1 string–matching–Problem; Akzeptor (zunächst nur informell)
6.2 Prüfungsplanung mittels Fächerkonfliktgraph
7. Zahlen in verschiedenen Stellenwertsystemen; Konvertierungen ineinander
8. interne Darstellung von Zahlen; Gleitpunktarithmetik und Rundungsfehler
8.1 interne Darstellung ganzer und reeller Zahlen; underflow und overflow
8.2 Arithmetik und Rundungsfehler
8.3 Maschinengenauigkeit
8.4 Supercomputer
9. kontextfreie Grammatiken; erweiterte Backus–Naur–Formen; Syntaxdiagramme
10. die natürlichen Zahlen
10.1 Charakterisierung duch ein Peano–System
10.2 Modelle natürlicher Zahlen
10.3 induktive Beweise und rekursive Definitionen
10.4 Bäume; Syntax–, Aufruf– und Suchbäume; Durchlaufverfahren
10.5 natürlichzahlige Terme in infix–, präfix– und postfix–Notation; Kellerspeicher; abstrakte Datentypen
10.6 Beispiele rekursiv definierter Funktionen
10.7 abzählbare Unendlichkeit; das erste Cantorsche Diagonalverfahren
10.8 Mächtigkeit der Menge algorithmisch unlösbarer Probleme; zweites Cantorsches Diagonalverfahren
10.9 Zufallszahlen und Zufallszahlen–Generatoren
10.10 randomisierte Algorithmen
11. Laufzeit von Programmen
11.1 asymptotische Laufzeitabschätzung
11.2 die O–Notation und ihre Eigenschaften
11.3 typische asymptotische Laufzeiten
11.4 ein einfacher Sortieralgorithmus und seine Laufzeit
11.5 binäre Suche in sortierten Arrays und ihre Laufzeit
11.6 schwer lösbare Probleme
12. spezielle algorithmisch unlösbare Probleme
12.1 Halteproblem
12.2 Äquivalenzproblem für Programme
12.3 Post’sches Korrespondenzproblem
12.4 zehntes Hilbert’sches Problem
12.5 Gödelisierung
13. Grundbegriffe der Aussagenlogik
13.1 Begriff der Aussage, Beispiele
13.2 Verknüpfungen von Aussagen und deren Formalisierung
13.3 boolesche Terme (aussagenlogische Ausdrücke)
13.3.1 rekursive Definition und Definition durch EBNF
13.3.2 Semantik boolescher Terme
13.4 Boolesche Algebra
13.5 Schleifeninvarianten; Verifikation von Programmen
13.6 Struktur indirekter Beweise
14. Quantoren; Grundbegriffe der Prädikatenlogik
14.1 prädikatenlogische Terme
14.2 prädikatenlogische Ausdrücke
14.3 freie und gebundene Vorkommen von Variablen
14.4 Semantik der Prädikatenlogik
14.5 Modellbegriff, Erfüllbarkeit, Allgemeingültigkeit, Folgerungsbegriff, semantische Äquivalenz
14.6 programmiertechnische Umsetzung von prädikatenlogischen Ausdrücken
15. Automaten und Sprachen
15.1 endliche Akzeptoren
15.1.1 deterministische Akzeptoren
15.1.2 nichtdeterministische Akzeptoren
15.1.3 nichtdeterministische Akzeptoren mit Epsilon–Übergängen
15.2 reguläre Ausdrücke
15.3 Chomsky–Grammatiken
15.4 Pumping–Lemma für reguläre Sprachen
15.5 Abschlusseigenschaften regulärer und kontextfreier Sprachen
15.6 deterministische endliche Automaten mit Ausgabe
15.7 Kellerautomaten
15.7.1 nichtdeterministische endliche Kellerautomaten
15.7.2 deterministische endliche Kellerautomaten
15.8 Turing–Maschinen
15.8.1 deterministische Turing–Maschinen
15.8.2 Turing–Berechenbarkeit
15.8.3 These von Church
16. loop– und while–Berechenbarkeit
16.1 loop–Programme
16.2 while–Programme
(Änderungen und Ergänzungen vorbehalten)
Informatik
Wissenschaft von der automatischen Verarbeitung von Signalen, durch die Informationen repräsentiert werden, insbesondere mit Hilfe von elektronischen
Rechenanlagen.
Daher werden untersucht:
ˆ Struktur, Wirkungsweise, Fähigkeiten und Konstruktionsprinzipien von
Rechenanlagen
(Prozessoren, Speicher, Bussysteme, Schnittstellen, ...;
Parallelrechner, Vektorrechner, ...)
ˆ Strukturen, Eigenschaften und Beschreibungsmöglichkeiten von Informa-
tionen und von Informationsverarbeitungsprozessen
(Signale, Daten, Dateien, Datenbanken, Programme, Programmiermethoden, formale Beschreibungsmethoden, ...)
ˆ Möglichkeiten der Strukturierung, Formalisierung und Mathematisierung
von Anwendungsgebieten sowie der Modellbildung und Simulation
(Flugsimulator, Simulation von chemischen und physikalischen Prozessen,
Crashsimulation, Bild– und Spracherkennung sowie –Verarbeitung, Computertomographie, globale Wettervorhersage, e–commerce–Systeme...)
1
Einen wichtigen Platz nehmen ein
ˆ abstrakte Begriffe und Objekte (Variablen, Terme, Ausdrücke, Relationen,
Datenmodelle, Algorithmen, abstrakte Automaten, (abstrakte) Datentypen, Module, Klassen, Objekte, · · ·)
ˆ formale Strukturen (Programmablauf– und Datenflusspläne, Pseudocodes,
Datenstrukturen, Programm– und Sprachstrukturen, Syntaxdiagramme,
Graphen, Petri–Netze, Entity–Relationship–Diagramme, Entscheidungstabellen, · · ·)
und deren Transformation nach formalen Regeln
ˆ Methoden der algorithmischen Problemlösung (modulare Zerlegung von
Problemen, top–down–Analyse und bottom–up–Synthese, Rekursionsprinzipien, Prototyping, · · ·) und Programmierparadigmen; Wahl der Programmiersprache
ˆ Beurteilung von Algorithmen hinsichtlich ihrer Korrektheit und Komple-
xität; Wartbarkeit und Erweiterbarkeit von Programmen
ˆ effektive Darstellung von Datenmodellen, abstrakten Objekten und forma-
len Strukturen im Rechner und automatische Durchführung von Transformationen
”Abstraction in the sense we use it implies simplification, the replacement of a
complex and detailed real–world situation by an understandable model within
which we can solve a problem. That is, we ’abstract away’ the details whose
effect on the solution to a problem is minimal or nonexistent, thereby creating
a model that lets us deal with the essence of the problem.” (Aho/Ullman)
2
Man unterscheidet:
ˆ Technische Informatik:
funktioneller Aufbau von Computern und dazugehörigen Peripheriegeräten, Rechnernetze; logischer und technischer Entwurf von Schaltungen und
Geräten
ˆ Praktische Informatik:
Methoden und Hilfsmittel zum Entwurf und letztlich zur Umsetzung von
Problemlösungen in Computerprogramme; Beurteilung der Problemlösungen
ˆ Theoretische Informatik:
grundlegende Strukturen und Prozesse mit mathematischen Hilfsmitteln
modellieren und untersuchen; zeigt prinzipielle Grenzen des Computereinsatzes auf und schafft Voraussetzungen für neuartige Computeranwendungen
ˆ Angewandte Informatik:
Oberbegriff für Zweige anderer Fachgebiete, die sich des Computers zur
Problemlösung bedienen (medizinische Informatik, Bioinformatik, Medieninformatik, Kommunikationsinformatik, Information Brokering, ...)
3
Problemlösungsprozess
Rückinterpretation der Ergebnisse
Problem der realen Welt
Modellbildung und Abstraktion
Problemspezifikation
Strukturierung und Modularisierung
Algorithmierung
Programmierung
Problemlösung
globale Wettervorhersage
automatische Bild- und Spracherkennung, Sprachübersetzung
Simulation physikalischer und chemischer Reaktionen
Platzbuchungssysteme
e-commerce-Systeme
usw.
Die während der Modellbildung und Abstraktion verwendeten formalen Methoden und Ausdrucksmittel müssen mächtig genug und sollten einfach implementierbar sein.
”Computer scientists must create abstractions of real–world problems
that can be understood by computer users and, at the same time, that
can be represented and manipulated inside a computer.” (Aho/Ullman)
4
Literatur (einschließlich Kapitelüberschriften)
ˆ Aho, A. V. and J. D. Ullman: Foundations of Computer Science (C Edition).
W. H. Freeman and Company 2000
siehe auch http://infolab.stanford.edu/∼ullman/focs.html (am 1.9.2009 vorhanden)
Computer Science: The Mechanization of Abstraction; Iteration, Induction and Recursion;
The Running Time of Programs; Combinatorics and Probability; The Tree Data Model;
The List Data Model; The Set Data Model; The Relational Data Model; The Graph Data
Model; Patterns, Automata and Regular Expressions; Recursive Descriptions of Patterns;
Propositional Logic; Using Logic to Design Computer Components; Predicate Logic
ˆ Asteroth, A. und Ch. Baier: Theoretische Informatik. Pearson Studium 2002
Abstrakte Rechnermodelle, Entscheidungsprobleme, Komplexitätsklassen, Das P–NP–
Problem, Grammatiken, Reguläre Sprachen, Kontextfreie Sprachen, Deterministisch kontextfreie Sprachen, Entscheidungsprobleme für formale Sprachen
ˆ Eirund, H., Müller, B. und G. Schreiber: Formale Beschreibungsverfahren der
Informatik. Teubner–Verlag 2000
Grundlagen aus Mathematik und Logik, formale Sprachen, Automaten und Verfahren,
Beschreibung nebenläufiger Prozesse, Algorithmenbegriff
ˆ Gries, D.: The science of programming. Springer–Verlag 1981
Propositions and Predicates, The Semantics of a Small Language, The Development and
Verification of Programs
ˆ Hopcroft, J. E., Motwani, R. and J. D. Ullman: Einführung in die Automatentheorie, Formale Sprachen und Komplexitätstheorie. Pearson Studium 2002
Automaten: Die Methode und der Wahnsinn, Endliche Automaten, Reguläre Ausdrücke
und Sprachen, Eigenschaften regulärer Sprachen, Kontextfreie Grammatiken und Sprachen, Pushdown–Automaten, Eigenschaften kontextfreier Sprachen, Einführung in Turing–
Maschinen, Unentscheidbarkeit, Nicht handhabbare Probleme, Weitere Problemklassen
ˆ Hromkovic, J.: Algorithmische Konzepte der Informatik. Teubner–Verlag 2001
Alphabete, Wörter, Sprachen, endliche Automaten, Turingmaschinen, Berechenbarkeit,
Komplexitätstheorie, Algorithmik für schwere Probleme, Randomisierung, Kommunikation und Kryptographie
ˆ Kastens, U. und H. Kleine Büning: Modellierung: Grundlagen und formale
Methoden. Hanser–Verlag 2008
Modellierung mit Wertebereichen, Terme und Algebren, Logik, Modellierung mit Graphen, Modellierung von Strukturen, Modellierung von Abläufen, Fallstudien
5
ˆ Klaeren, H. und M. Sperber: Vom Problem zum Programm. 3. Auflage 2001,
Teubner–Verlag
was ist Informatik, was ist Programmierung, induktive Definitionen, Rekursion und Induktion, Paare und Listen, higher–order–Programmierung, Datenabstraktion, abstrakte
Datentypen, binäre Bäume, datengesteuerte Programmierung, Zuweisungen und Zustand,
objektorientiertes Programmieren, logische Kalküle, der λ–Kalkül, kontextfreie Grammatiken, metazirkuläre Interpretation, mathematische Grundlagen, Geschichte der Informatik
ˆ Meinel, Chr. und M. Mundhenk: Mathematische Grundlagen der Informatik.
Teubner–Verlag 2002
Aussagen, Mengen und Mengenoperationen, mathematisches Beweisen, Relationen, Abbildungen und Funktionen, diskrete Stochastik, Boolesche Algebra, Graphen und Bäume,
Aussagenlogik
ˆ Sander, P., Stucky, W. und R. Herschel: Automaten, Sprachen, Berechenbarkeit. Teubner–Verlag 1992
Mathematische Grundlagen, Automaten, Formale Sprachen, Turing–Maschinen, Algorithmen und berechenbare Funktionen
ˆ Schöning, U.: Logik für Informatiker. BI Wissenschaftsverlag 1992
Aussagenlogik, Prädikatenlogik, Logik–Programmierung
ˆ Schöning, U.: Theoretische Informatik kurz gefaßt. BI Wissenschaftsverlag
1992
Automatentheorie und formale Sprachen, Berechenbarkeitstheorie, Komplexitätstheorie
ˆ Schöning, U.: Ideen der Informatik. Oldenbourg–Verlag 2006
Algorithmik, Graphen, formale Sprachen, Grammatiken und Automaten, Berechenbarkeit und deren Grenzen, Aussagenlogik und Boole’sche Schaltungen, Prädikatenlogik und
Programmverifikation, Information, Codierung und Kryptologie
ˆ Vossen, G. und K.–U. Witt: Grundlagen der Theoretischen Informatik mit
Anwendungen. Vieweg–Verlag 2000
endliche Automaten, reguläre Sprachen, endliche Maschinen und Automatennetze, kontextfreie Sprachen, Kellerautomaten, Anwendungen kontextfreier Sprachen, Chomsky–
Hierarchie, Turingautomaten, Berechenbarkeit, Entscheidbarkeit, Komplexität
ˆ Wegener, I.: Theoretische Informatik – eine algorithmenorientierte Einführung. Teubner–Verlag 2005
Turingmaschinen, churchsche These und Entscheidbarkeit, Die NP–Vollständigkeitstheorie,
Endliche Automaten, Grammatiken, die Chomsky–Hierarchie und das Wortproblem, Kontextfreie Grammatiken und Sprachen, Kellerautomaten und kontextfreie Sprachen, Deterministisch kontextfreie Sprachen
6
ein paar Bemerkungen zum Studienbeginn
ˆ Lernen ist harte Arbeit
jeder muss seinen eigenen Stil finden;
bloßes Durchlesen der Aufzeichnungen, weiterer Materialien und von Büchern reicht nicht, Durcharbeiten ist angesagt
ˆ Durcharbeiten umfasst u.a.:
– Begriffe lernen, Beispiele dazu verstehen, eigene Beispiele bilden oder
nach Objekten suchen, die entsprechende oder verwandte Eigenschaften haben
– Übungsaufgaben lösen
– Methoden und Verfahren verstehen und anwenden
– sich Fragen zum Stoff notieren und diese im Seminar bzw. im Praktikum stellen
– immer wieder wiederholen
ˆ ohne Formeln und Formalismen geht es nicht
ˆ von Anfang an ”dranbleiben”
ˆ stets nach höchsten Leistungen streben
ˆ Folien: Begleitmaterial zur Lehrveranstaltung, aber kein Ersatz dafür
Akademische Freiheit bedeutet:
Es darf mehr gearbeitet werden, als verlangt wird.
(Feodor Lynen, (1911-1979), Nobelpreisträger 1964)
7
einige mathematische Grundbegriffe (Mengen, Abbildungen, Funktionen, Operationen, Relationen)
1. naiver Mengenbegriff, Elementrelation, Teilmengenrelation (Inklusion), mengentheoretische Operationen
(a) Mengenbegriff, Elementrelation (Enthaltenseinsrelation) ∈
Georg Cantor (1845–1918), Begründer der Mengenlehre: ”Unter einer Menge verstehen wir jede Zusammenfassung M von bestimmten
wohlunterschiedenen Objekten unserer Anschauung oder unseres Denkens (welche die Elemente von M genannt werden) zu einem Ganzen.”
”x ist ein Element von M” wird notiert durch ”x ∈ M”
”x ist nicht Element von M” wird notiert durch ”x ∈
/ M”
Schreibweisen für Mengen:
explizite Notation der Elemente innerhalb geschweifter Klammern, z.B.
ˆ {a} (gesprochen: Einermenge a);
es ist a ∈ {a}, aber x ∈
/ {a} für jedes x 6= a
ˆ {a,b} (gesprochen: Zweiermenge a,b);
es ist a ∈ {a, b} und b ∈ {a, b}, aber x ∈
/ {a, b} für jedes x mit
x 6= a und x 6= b
verbale Beschreibung und Einführung von Bezeichnungen,
z.B.
ˆ N:= {0 , 1 , 2 , · · · } = Menge der natürlichen Zahlen
ˆ Z:= { · · · , -2 , -1 , 0 , 1 , 2 , · · · } = Menge der ganzen Zahlen
ˆ Q:= Menge der rationalen Zahlen
ˆ R:= Menge der reellen Zahlen
ˆ ∅ := die leere Menge; stets ist x ∈
/ ∅ für alle x
Definition durch Aussonderung (aus einer schon vorhandenen
Menge), z.B.
ˆ {n | n ∈ N ∧ n ungerade} = {n ∈ N | n ungerade} = Menge der
ungeraden natürlichen Zahlen
ˆ {n ∈ N | n ≥ 2 und n hat nur sich selbst und die Zahl 1 als Teiler}
= Menge der Primzahlen
ˆ {n ∈ N | ∃i(i ∈ N ∧ n = 2i)} = Menge aller derjenigen natürlichen Zahlen, die Zweierpotenzen (mit natürlichzahligen Exponenten) sind
8
Für Mengen M1 , M2 , M3 , · · · sind auch {M1 }, {{M1}}, {M1 , M2},
{M1 , M2, M3}, {M1 , {M2, M3}}, {{M1 }, {M2, M3}}, · · · wieder Mengen.
Falls eine Menge nur Mengen als Elemente hat, so wird sie auch als
Mengensystem bezeichnet.
Definition des geordneten Paares (a,b) nach K. Kuratowski (1921):
(a, b) := {{a}, {a, b}}
Während {a, b} = {b, a} ist (es kommt nicht auf die Reihenfolge der
Notation der Elemente einer Menge an), gilt:
(a, b) = (c, d)
↔
a=c∧b=d
(b) Teilmengenrelationen ⊆ und ⊂
Für beliebige Mengen A, B sei
ˆ A ⊆ B (A ist Teilmenge von B, B ist Obermenge von A)
:↔ ∀x(x ∈ A → x ∈ B)
(jedes Element von A ist auch Element von B)
ˆ A ⊂ B (A ist echte Teilmenge von B, B ist echte Obermenge
von A)
:↔ A ⊆ B ∧ A 6= B
Beispielsweise gilt
ˆ {n ∈ N | n gerade} ⊂ N ⊂ Z ⊂ Q ⊂ R
ˆ ∅ ⊆ A für jede Menge A
ˆ A=B ↔ A⊆B∧B ⊆A
Mit Hilfe der Teilmengenrelation ⊆ wird der Begriff der Potenzmenge definiert:
PA := {X | X ⊆ A} (die P otenzmenge von A)
Wenn A n Elemente hat, so hat PA 2n Elemente.
(c) mengentheoretische Operationen
ˆ Durchschnitt A ∩ B zweier Mengen A, B
A ∩ B := {x | x ∈ A ∧ x ∈ B}
(Menge aller derjenigen Elemente, die sowohl in A als auch in B
enthalten sind)
ˆ Vereinigung A ∪ B zweier Mengen A, B
A ∪ B := {x | x ∈ A ∨ x ∈ B}
(Menge aller derjenigen Elemente, die in mindestens einer der Mengen A bzw. B enthalten sind)
ˆ Differenz A \ B zweier Mengen A, B
A \ B := {x ∈ A | x ∈
/ B}
(Menge aller derjenigen Elemente, die in A, aber nicht in B enthalten sind)
9
ˆ (kartesisches) Produkt A × B zweier Mengen A, B
A × B := {(a, b) | a ∈ A ∧ b ∈ B}
(Menge aller derjenigen geordneten Paare, deren erste Komponente
in A und deren zweite Komponente in B enthalten ist)
Wenn A n Elemente hat und B hat m Elemente, so hat A × B
m ∗ n Elemente.
Sind beispielsweise die Mengen A bzw. B durch A := {a, b} und B :=
{b, c, d} gegeben, so gilt:
A ∩ B = {b}
A ∪ B = {a, b, c, d}
A \ B = {a}
A × B = {(a, b), (a, c), (a, d), (b, b), (b, c), (b, d)}
2. Abbildungen, Funktionen, Operationen
(a) Abbildungen
Es seien A, B Mengen.
Es heißt f genau dann eine Abbildung aus A in B, wenn f ⊆ A × B
gilt.
Vorbereich (Definitionsbereich, domain) Db(f ) von f ⊆ A × B:
Db(f ) := {x ∈ A | ∃y(y ∈ B ∧ (x, y) ∈ f )}
Nachbereich (Wertebereich, codomain, range) W b(f ) von f ⊆
A × B:
W b(f ) := {y ∈ B | ∃x(x ∈ A ∧ (x, y) ∈ f )}
Damit ist auch f ⊆ Db(f ) × W b(f ).
Die zu f inverse Abbildung f −1 ist definiert durch
f −1 := {(y, x) | (x, y) ∈ f }.
f ⊆ A × B heißt Abbildung
ˆ von A in B
:↔ Db(f ) = A
ˆ aus A auf B :↔ W b(f ) = B
ˆ von A auf B :↔ Db(f ) = A ∧ W b(f ) = B
Die Verkettung (Hintereinanderausführung, Komposition) g◦f
zweier Abbildungen f , g ist wie folgt erklärt:
g ◦ f := {(x, y) | ∃z((x, z) ∈ f ∧ (z, y) ∈ g)}
(b) Funktionen
Funktionen sind spezielle Abbildungen:
Eine Abbildung f heißt genau dann eine Funktion (bzw. eindeutige
Abbildung), wenn aus (x, y1) ∈ f und (x, y2) ∈ f stets y1 = y2 folgt.
10
Schreibweisen:
f : A → B bedeute, dass f eine Funktion von A in B ist.
Für eine Funktion f : A → B wird anstelle von (x, y) ∈ f auch
y = f (x) geschrieben. Sind f und g Funktionen, so wird für (g ◦ f )(x)
auch g(f (x)) notiert.
Die Funktionen f loor : R → Z und ceil : R → Z mit
ˆ f loor(x) := max{n ∈ Z | n ≤ x}
ˆ ceil(x) := min{n ∈ Z | x ≤ n}
kommen oft in Informatik–Anwendungen vor. (Außerhalb von Programmen werden sie auch als ⌊x⌋ bzw. ⌈x⌉ geschrieben.)
Mit B A wird die Menge aller Funktionen von A in B bezeichnet.
Eine Abbildung f heißt eineindeutig (injektiv, one-to-one) oder
umkehrbare Funktion genau dann, wenn f eindeutig ist und aus
(x1, y) ∈ f und (x2, y) ∈ f stets x1 = x2 folgt.
Mit f ist auch f −1 wieder eineindeutig.
(c) Mächtigkeit von Mengen, endliche und unendliche Mengen
Zwei Mengen A und B heißen genau dann gleichmächtig oder von
gleicher Kardinalität (in Zeichen card(A) = card(B)), wenn es eine eineindeutige Abbildung von A auf B gibt (eine solche Abbildung
heißt auch eine Bijektion).
Unendlichkeitsdefinition nach Richard Dedekind (1831–1916):
A unendlich :↔ ∃X(X ⊂ A ∧ card(X) = card(A))
A heißt genau dann endlich, wenn A nicht unendlich ist.
Man kann zeigen, dass A genau dann endlich ist, wenn es eine natürliche Zahl n gibt mit card({1, · · · , n}) = card(A). Diese sogar eindeutig
bestimmte Zahl n heißt die Elementeanzahl von A. Man schreibt
dann auch card(A) = n.
Endliche Mengen sind genau dann gleichmächtig, wenn sie die gleiche
Elementeanzahl haben.
Jede Teilmenge einer endlichen Menge ist wieder endlich, und jede
Obermenge einer unendlichen Menge ist wieder unendlich.
Beispielsweise ist N eine unendliche Menge.
Genau die Mengen A mit card(A) = card(N) heißen abzählbar unendliche Mengen.
Z, Q, die Menge aller Primzahlen und die Menge aller Zeichenketten
über einem (endlichen) Alphabet sind abzählbar unendliche Mengen.
11
Eine Menge heißt genau dann abzählbar, wenn sie endlich oder abzählbar unendlich ist.
Unendliche Mengen, die nicht abzählbar unendlich sind, heißen überabzählbar unendliche Mengen.
Beispielsweise sind R, {0, 1}N und PN überabzählbar unendliche Mengen (die sogar untereinander gleichmächtig sind).
Es hat PA stets eine größere Mächtigkeit als A selbst.
(d) Operationen
Operationen sind spezielle Funktionen:
Gilt f : A → A, so heißt f auch eine einstellige (unäre) Operation
auf A.
Ist f : A × A → A, so heißt f auch eine zweistellige (binäre) Operation auf A.
Z.B. ist die Betragsfunktion f : R → R, d.h. f (x) = |x| für jedes
x ∈ R, eine einstellige Operation auf R.
Bei binären Operationen f verwendet man anstelle von f (x, y) meistens die infix–Schreibweise xf y (z.B. i + j statt +(i, j) für die Addition + auf der Menge N).
Eine nullstellige Operation f auf A, notiert als f : → A, ist nichts
anderes als ein Element von A.
Wichtige binäre Operationen auf Z sind die ganzzahlige Division div
und die modulo–Operation mod:
ˆ n div m := ⌊|n|/|m|⌋ ∗ sgn(n ∗ m)
(dabei ist sgn : R → {−1, 0, 1} mit sgn(x) := −1 für negative x,
sgn(x) := 0 für x = 0, und sgn(x) := 1 für positive x)
ˆ n mod m := n − m ∗ (n div m)
(beide nur für m 6= 0 erklärt). Es bezeichnen also n div m den ganzen
Teil des Quotienten n/m und n mod m den Rest bei der ganzzahligen
Division von n durch m.
(e) n–stellige Funktionen
Um n–stellige Funktionen bzw. Operationen für n ≥ 3 definieren zu
können, muss zunächst der Begriff des n–Tupels als Verallgemeinerung des Begriffes des geordneten Paares eingeführt werden. Dies kann
mit Hilfe einer rekursiven (auch: induktiven) Definition geschehen:
ˆ Für n = 2 und beliebige Elemente x1 , x2 sei das n–Tupel (x1 , · · · , xn)
definiert durch das bereits bekannte geordnete Paar (x1, x2) (Induktions–Anfang).
ˆ Sei jetzt n > 2 und sei (x1, · · · , xn−1) bereits definiert (Induktions–
Voraussetzung bzw. Induktions–Annahme)
Dann sei (x1, · · · , xn) := ((x1, · · · , xn−1), xn) (Induktions–Schritt).
12
Es wird also (x1, · · · , xn) definiert als das geordnete Paar mit den beiden Komponenten (x1, · · · , xn−1) und xn.
Es gilt: (x1, · · · , xn) = (y1, · · · , ym) ↔ n = m ∧ x1 = y1 ∧ · · · ∧ xn =
yn .
Ein n–Tupel (x1, · · · , xn) und ein m–Tupel (y1, · · · , ym ) sind also genau
dann einander gleich, wenn n = m ist und außerdem xi = yi gilt für
jedes i mit 1 ≤ i ≤ n (auf gleichen Plätzen befinden sich in beiden
Tupeln jeweils gleiche Elemente). Nun kann auch das n–fache Pron
dukt Xi=1
Ai (bzw. A1 × · · · × An ) für Mengen A1, · · · , An definiert
werden als die Menge aller n–Tupel (a1, · · · , an ) mit ai ∈ Ai für alle i,
1 ≤ i ≤ n. Formalisiert niedergeschrieben:
n
Xi=1
Ai := {(a1, · · · , an ) | ∀i(1 ≤ i ≤ n → ai ∈ Ai )}
n
Eine n–stellige Funktion f ist eine Funktion f : Xi=1
Ai → B für
gewisse Mengen A1 , · · · , An, B. (Analog kann f ⊆ A × B dann eine
n
n–stellige Abbildung genannt werden, wenn A = Xi=1
Ai ist für gewisse Mengen A1, · · · , An.)
n
Falls A1 = · · · = An = B ist, so wird anstelle von Xi=1
Ai auch einfach
n
B (n-te Potenz von B) geschrieben.
Eine Funktion f : An → A wird auch als eine n–stellige Operation
auf A bezeichnet.
(f) rekursive Definitionen
Der Begriff des n–Tupels wurde rekursiv bzw. durch vollständige
Induktion eingeführt. Auf analoge Weise können Operationen n–
stellig verallgemeinert werden. Zugrunde liegen solchen Definitionen
Rekursionstheoreme, von denen jetzt zwei oft benutzte Versionen
angegeben werden sollen.
Rekursionstheorem 1: Es seien A eine beliebige nichtleere Menge, a ∈ A
und g : A → A. Dann existiert genau eine Funktion f : N → A mit
f (0) := a
(Rekursions– bzw. Induktions–Anfang)
f (n′) := g(f (n))
(Rekursions– bzw. Induktions–Schritt)
′
(n : Nachfolger von n, d.h. n′ := n + 1)
Rekursionstheorem 2: Es seien A eine beliebige nichtleere Menge, a ∈ A
und g : N × A → A. Dann existiert genau eine Funktion f : N → A
mit
f (0) := a
(Rekursions– bzw. Induktions–Anfang)
′
f (n ) := g(n, f (n)) (Rekursions– bzw. Induktions–Schritt)
Bemerkung: Ist der Induktions–Anfang durch f (n0) := a gegeben und
n0 > 0, so wird die Menge {n0, n0 + 1, n0 + 2, · · ·} ⊆ N der Definitionsbereich von f .
13
3. Relationen
(a) n–stellige Relationen
Es seien n ≥ 1 eine natürliche Zahl und R, A Mengen. Dann heißt
R eine n–stellige Relation in A, falls R ⊆ An ist (n = 2: binäre
Relation).
Verallgemeinerung: R heißt n–stellige Relation, wenn es Mengen
A1, · · · , An gibt, so dass R ⊆ A1 × · · · × An ist.
Bei binären Relationen R kann man anstelle von (a, b) ∈ R auch die
infix–Schreibweise aRb benutzen.
Beispielsweise ist (3, 7) ∈≤ bzw. 3 ≤ 7 für die kleinergleich–Relation
≤ in N, und es ist (4, 16) ∈ | bzw. 4|16 für die Teiler–Relation | in Z
(”n|m” bedeute, dass n ein Teiler von m ist, d.h., dass es ein k ∈ Z
gibt mit n ∗ k = m).
Für jede Menge A kann die identische Relation IdA in A definiert
werden:
IdA := {(a, a) | a ∈ A}.
Analog wie für Abbildungen ist die Verkettung S ◦ R für binäre
Relationen R, S erklärt.
(b) reflexive Halbordnung(–srelation)
Eine binäre Relation R ⊆ A2 heißt genau dann eine reflexive Halbordnung in A, wenn für beliebige a, b, c ∈ A gilt:
(a, a) ∈ R
(Reflexivität)
(a, b) ∈ R ∧ (b, c) ∈ R → (a, c) ∈ R
(Transitivität)
(a, b) ∈ R ∧ (b, a) ∈ R → a = b
(Antisymmetrie)
(c) irreflexive Halbordnung(–srelation)
Eine binäre Relation R ⊆ A2 heißt genau dann eine irreflexive Halbordnung in A, wenn für beliebige a, b, c ∈ A gilt:
(a, a) ∈
/R
(Irreflexivität)
(a, b) ∈ R ∧ (b, c) ∈ R → (a, c) ∈ R
(Transitivität)
(a, b) ∈ R → (b, a) ∈
/R
(Asymmetrie)
Die gewöhnliche ≤–Relation in R ist eine reflexive Halbordnung in R,
die <–Relation dagegen eine irreflexive Halbordnung. Das geordnete
Paar (R, ≤) bzw. (R, <) wird deshalb auch als reflexiv bzw. irreflexiv halbgeordnete Menge bezeichnet.
(d) reflexive Ordnung(–srelation)
Eine binäre Relation R ⊆ A2 heißt genau dann eine reflexive Ordnung in A, wenn für beliebige a, b, c ∈ A gilt:
(a, a) ∈ R
(Reflexivität)
(a, b) ∈ R ∧ (b, c) ∈ R → (a, c) ∈ R (Transitivität)
(a, b) ∈ R ∧ (b, a) ∈ R → a = b
(Antisymmetrie)
(a, b) ∈ R ∨ (b, a) ∈ R
(Vergleichbarkeit, Linearität)
14
(e) irreflexive Ordnung(–srelation)
Eine binäre Relation R ⊆ A2 heißt genau dann eine irreflexive Ordnung in A, wenn für beliebige a, b, c ∈ A gilt:
(a, a) ∈
/R
(Irreflexivität)
(a, b) ∈ R ∧ (b, c) ∈ R → (a, c) ∈ R (Transitivität)
(a, b) ∈ R → (b, a) ∈
/R
(Asymmetrie)
(a, b) ∈ R ∨ (b, a) ∈ R ∨ a = b
(Konnexität)
Somit sind reflexive bzw. irreflexive Ordnungen spezielle reflexive bzw.
irreflexive Halbordnungen.
Die gewöhnliche ≤–Relation in R ist auch eine reflexive Ordnung in R,
die <–Relation eine irreflexive Ordnung, so dass (R, ≤) bzw. (R, <)
sogar reflexiv bzw. irreflexiv geordnete Mengen sind.
(f) Äquivalenzrelationen
Eine binäre Relation R ⊆ A2 heißt genau dann eine Äquivalenzrelation in A, wenn für beliebige a, b, c ∈ A gilt:
(a, a) ∈ R
(Reflexivität)
(a, b) ∈ R ∧ (b, c) ∈ R → (a, c) ∈ R (Transitivität)
(a, b) ∈ R → (b, a) ∈ R
(Symmetrie)
Beispiele für Äquivalenzrelationen:
ˆ in jeder Menge A die identische Relation IdA
ˆ in jeder Menge A die volle Relation A × A
ˆ in jedem Mengensystem die Gleichmächtigkeitsrelation
ˆ in Z für jedes m ∈ Z die Kongruenz modulo m:
es heißt r kongruent s modulo m (in Zeichen: r ≡ s mod m)
:↔
r − s ist ein ganzzahliges Vielfaches von m
Wenn R eine Äquivalenzrelation in A ist, so wird für jedes a ∈ A mit
[a]R := {b ∈ A | aRb} die Äquivalenzklasse (bzw. Restklasse) von
a bzgl. R bezeichnet. Die Menge A/R := {[a]R | a ∈ A} aller Äquivalenzklassen bzgl. R heißt auch der Quotient (bzw. die Faktormenge)
von A bzgl. R.
Es ist A/R ein Mengensystem mit paarweise elementfremden (disjunkten) Mengen, es ist ∅ ∈
/ A/R, und die Vereinigung aller Mengen
S
aus A/R (notiert als A/R) ist A. (Jedes Mengensystem mit diesen
drei Eigenschaften heißt auch eine Zerlegung von A.)
Äquivalenzrelationen spielen eine herausragende Rolle in der Informatik.
15
einige Begriffe und Eigenschaften in Bezug auf natürliche Zahlen
ˆ k ∈ N heißt ein Teiler von n ∈ N (symbolisch: k | n) genau dann, wenn
es ein m ∈ N gibt mit k ∗ m = n
formal:
k | n :←→ ∃m(m ∈ N ∧ k ∗ m = n)
ˆ k ∈ N heißt der größte gemeinsame Teiler von n, m ∈ N
(k = ggt(n, m) bzw. k = gcd(n, m)) genau dann, wenn gilt:
k | m ∧ k | n ∧ ∀t(t ∈ N ∧ t | m ∧ t | n −→ t | k)
ˆ Satz von der Division mit Rest:
Zu zwei beliebigen natürlichen Zahlen n, k mit k 6= 0 gibt es genau zwei
natürliche Zahlen q und r, so dass gilt:
n=q∗k+r
∧
0≤r<k
Bezeichnungen: q = n div k bzw. q = n ÷ k , r = n mod k
(Die Operationen div und mod sind sogar für ganze Zahlen n, k mit k 6= 0
erklärt, siehe Folie 12.)
ˆ Es sei m ∈ N, m 6= 0; zwei natürliche Zahlen r und s heißen genau dann
kongruent modulo m (symbolisch: r ≡ s mod m), wenn (r mod m) =
(s mod m) ist, d.h., wenn r und s bei Division durch m den gleichen Rest
haben. (Verallgemeinerung auf ganze Zahlen: s. Folie 15.)
ˆ Satz von der eindeutigen Primfaktorzerlegung :
Jede natürliche Zahl lässt sich bis auf die Reihenfolge der Faktoren auf
genau eine Weise als Produkt von Primzahlen schreiben.
ˆ Existenz eines Minimums :
Jede nichtleere Menge natürlicher Zahlen besitzt ein Minimum.
formal:
∀M(M ⊆ N ∧ M 6= ∅ → ∃n(n ∈ M ∧ ∀m(m ∈ M → n ≤ m)))
Wichtige Sachverhalte zu den Primzahlen siehe z.B. unter
www.utm.edu/research/primes
zusätzliche Literatur:
Knuth, D. E.: The Art of Computer Programming. Vol. 2: Seminumerical Algorithms. Addison Wesley
1981
Forster, O.: Algorithmische Zahlentheorie. Vieweg 1996
www.mathematik.uni-muenchen.de/∼forster/sw/aribas.html
Schroeder, M. R.: Number Theory in Science and Communication. Springer 2005
16
Bits und Bytes
Bit (binary digit): ein Bit kann genau zwei Zustände annehmen, nämlich 0 und
1;
es ist die kleinste Einheit zur Speicherung von Daten im Computer;
Byte: besteht aus 8 Bit; kleinste adressierbare Einheit in Speichern des Computers;
z.B. ist der Hauptspeicher des Computers in Bytes unterteilt, wobei jedes Byte
seine eigene Adresse (”Hausnummer”) hat, über die sein Inhalt manipuliert werden kann;
ein Byte kann 28 = 256 paarweise verschiedene Zustände annehmen
Abkürzungen zur Charakterisierung von Bit– und Byte–Mengen
ˆ K = 210 = 1 024 (Kilo)
ˆ M = 220 = 1 048 576 (Mega)
ˆ G = 230 = 1 073 741 824 (Giga)
ˆ T = 240 = 1 099 511 627 776 (Tera)
ˆ P = 250 = 1 125 899 906 842 624 (Peta)
ˆ E = 260 = 1 152 921 504 606 846 976 (Exa)
ˆ Z = 270 = 1 180 591 620 717 411 303 424 (Zetta)
ˆ Y = 280 = 1 208 925 819 614 629 174 706 176 (Yotta)
Die letzte Zahl in Worten:
Eine Quadrillion Zweihundertacht Trilliarden Neunhundertfünfundzwanzig Trillionen Achthundertneunzehn Billiarden Sechshundertvierzehn Billionen Sechshundertneunundzwanzig Milliarden Einhundertvierundsiebzig Millionen Siebenhundertsechs Tausend Einhundertsechsundsiebzig
Zur Gegenüberstellung:
Anzahl der möglichen Tipps 6 aus 49 plus Superzahl:
49
6
∗ 10 = 139838160 ≈ 1.4 ∗ 108
Alter der Erde: 109 (≈ 230 ) Jahre
Anzahl der Atome in der Erde: 1051 (≈ 2170 )
Anzahl der Atome im Universum: 1077 (≈ 2256 )
Anzahl der Primzahlen mit einer Länge bis zu 512 Bit: 3 ∗ 10151 (≈ 2512 /(512 ∗ ln(2)))
(falls n ≥ 17 ist, so gibt es mindestens n/ln(n) Primzahlen, die kleiner oder gleich n sind)
(s. B. Schneier: Angewandte Kryptographie. Pearson Studium 2006)
17
Alphabet
Ein Alphabet A ist eine endliche nichtleere Menge mit den beiden Eigenschaften
ˆ von zwei beliebig vorgegebenen Elementen aus A kann effektiv festgestellt
werden, ob sie identisch sind oder nicht
ˆ für jede (endliche) Zeichenkette (engl. string) Z mit Elementen nur aus
A und jede natürliche Zahl i kann effektiv festgestellt werden, welches
Element von A sich auf dem i–ten Platz von Z befindet
Oft ist zusätzlich noch eine Ordnung bzw. Reihenfolge der Elemente von A
gegeben.
Beispiele:
A := {|}
(ein einelementiges Alphabet)
A := {0, 1}
(Menge der Dualziffern)
A := {¬, ∧, ∨, →, ↔, ∀, ∃}
(Menge der klassischen aussagenlogischen
Funktoren und prädikatenlogischen Quantoren)
A := {0, 1, 2, 3, 4, 5, 6, 7}
(Menge der Oktalziffern)
A := {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
(Menge der Dezimalziffern)
A := {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F } (Menge der Hexadezimal–
ziffern)
A :=lateinisches Alphabet
A := {A, · · · , Z, a, · · · , z, 0, · · · , 9, +, /} := Base64–Alphabet
(hinzu kommt ’=’ als Padding– (Auffüll–)Symbol, siehe z.B.
www.ietf.org/rfc/rfc1521.txt)
A :=ASCII–Alphabet (27 Elemente)
A := U nicode–Alphabet (216 Elemente)
(www.unicode.org)
”The Unicode Standard is a character coding system designed to support the
worldwide interchange, processing, and display of the written texts of the diverse
languages and technical disciplines of the modern world. In addition, it supports
classical and historical texts of many written languages.”
Zum Beispiel haben der griechische Buchstabe µ die (hexadezimale) Codierung
03BC, das Eurozeichen ¿ die Codierung 20AC und das Unendlichzeichen ∞
die Codierung 221E.
18
ASCII–Alphabet
(American Standard Code for Information Interchange, ISO–7–Bit–Code)
Dez Hex
0
00
1
01
2
02
3
03
4
04
5
05
6
06
7
07
8
08
9
09
10
0A
11
0B
12
0C
13
0D
14
0E
15
0F
16
10
17
11
18
12
19
13
20
14
21
15
22
16
23
17
24
18
25
19
26
1A
27
1B
28
1C
29
1D
30
1E
31
1F
Ctrl–Ch
∧
@
∧
A
∧
B
∧
C
∧
D
∧
E
∧
F
∧
G
∧
H
∧
I
∧
J
∧
K
∧
L
∧
M
∧
N
∧
O
∧
P
∧
Q
∧
R
∧
S
∧
T
∧
U
∧
V
∧
W
∧
X
∧
Y
∧
Z
∧
[
∧
\
∧
]
∧∧
∧
Char
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
HT
LF
VT
FF
CR
SO
SI
DLE
DC1
DC2
DC3
DC4
NAK
SYN
LTB
CAN
EM
SUB
ESC
FS
GS
RS
US
Dez
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Hex Char
20 SPC
21
!
22
”
23
#
24
$
25
%
26
&
27
’
28
(
29
)
2A
*
2B
+
2C
,
2D
2E
.
2F
/
30
0
31
1
32
2
33
3
34
4
35
5
36
6
37
7
38
8
39
9
3A
:
3B
;
3C
<
3D
=
3E
>
3F
?
Dez
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Hex Char
40
@
41
A
42
B
43
C
44
D
45
E
46
F
47
G
48
H
49
I
4A
J
4B
K
4C
L
4D
M
4E
N
4F
O
50
P
51
Q
52
R
53
S
54
T
55
U
56
V
57
W
58
X
59
Y
5A
Z
5B
[
5C
\
5D
]
∧
5E
5F
Dez
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Hex
60
61
62
63
64
65
66
67
68
69
6A
6B
6C
6D
6E
6F
70
71
72
73
74
75
76
77
78
79
7A
7B
7C
7D
7E
7F
Char
‘
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
∼
DEL
Die 32 Zeichen der ersten Spalte und das letzte Zeichen sind Steuerzeichen und
nicht druckbar. Sie werden durch eine Tastenkombination, z.B. Strg+@ bzw.
Ctrl+@ für ∧ @, erzeugt. Einige der Steuerzeichen können in C– bzw. C++–
Quelltexten durch sogenannte Escape–Sequenzen, die mit einem Backslash
beginnen, dargestellt werden.
19
Dez
0
7
8
9
10
11
12
13
Ctrl–Ch
∧
@
∧
G
∧
H
∧
I
∧
J
∧
K
∧
L
∧
M
Esc–Seq
\0
\a
\b
\t
\n
\v
\f
\r
Bedeutung
Zeichenkettenende
Klingel, Systempiepser
Backspce, Rückwärtsschritt
Horizontaltabulator
Zeilenvorschub, neue Zeile
Vertikaltabulator
Formularvorschub
Wagenrücklauf
Bedeutung weiterer Steuerzeichen:
NUL
SOH
STX
ETX
EOT
ENQ
ACK
SO
SI
DLE
DC
NAK
SYN
ETB
CAN
EM
SUB
ESC
FS
GS
RS
US
Null, keine Operation, String–Ende
Beginn des Vorspanns, start of heading
Anfang des Textes, start of text
Ende des Textes, end of text
Ende der Übertragung, end of transmission
Antwortanforderung, enquiry
positive Rückmeldung, acknowledge
Umschaltung, shift out
Rückschaltung, shift in
Datenübertragung, data link escape
Gerätesteuerung, device control
negative Rückmeldung, negative acknowledge
Synchronisierung, synchronous idle
Ende des Datenblocks, end of transmission block
ungültig, cancel
Ende der Aufzeichnung, end of medium
Zeichensubstitution, substitute character
Umschaltung, escape
Dateitrennzeichen, file separator
Gruppentrennzeichen, group separator
Satzendezeichen, record separator
Gerätetrennzeichen, unit separator
Bei der Arbeit unter UNIX bzw. LINUX wird grundsätzlich der ASCII–Zeichensatz
verwendet, wobei die Steuerzeichen nicht immer ganz einheitlich Verwendung
finden.
Die Abarbeitung eines unter UNIX/LINUX laufenden Programmes kann durch
Eingabe von Strg+C abgebrochen werden.
Terminalausgaben lassen sich mit Strg+S stoppen (nicht abbrechen) und mit
Strg+Q wieder fortsetzen.
Als logout–Kommando kann auch Strg+D benutzt werden.
Andere Betriebssysteme verwenden einen erweiterten 8–Bit–ASCII–Zeichensatz, bei dem aber die ersten 128 Zeichen mit dem 7–Bit–ASCII–Code übereinstimmen.
20
Zeichenketten (strings)
Eine Zeichenkette bzw. ein Wort über einem Alphabet A ist eine endliche (einschließlich leere) Folge von Zeichen aus A, wobei ε die leere Zeichenkette bezeichne. Damit sind beispielsweise
”a$(KoL3x” , ”uvw=?h&&1” und ε
Zeichenketten über dem ASCII–Alphabet mit den Längen (Anzahlen der besetzten Plätze) 8, 9 bzw. 0 und
”5F3AD”, ”FF” und ε
Zeichenketten über dem Alphabet der Hexadezimalziffern mit den Längen 5, 2
bzw. 0.
Durch Verkettung (concatenation) zweier Zeichenketten, d. h. Aneinanderfügen der Zeichenketten mit Berücksichtigung der Reihenfolge, erhält man wieder eine Zeichenkette. Man kann die Menge A∗ aller Zeichenketten über einem
Alphabet A folgendermaßen induktiv definieren:
A0
:= {ε}
A∗
:=
Ai+1 := Ai ◦ A
S
i∈N
Ai
für jedes i ∈ N
(◦: Symbol für die Verkettung)
i
Es ist A die Menge aller Zeichenketten der Länge i über A.
Mit A+ wird die Menge der nichtleeren Zeichenketten über A bezeichnet, d.h.,
es ist A+ = A∗ \ {ε}.
Eine Zeichenkette Z1 ist genau dann eine Teilzeichenkette (substring) der
Zeichenkette Z2, wenn es Zeichenketten U und V gibt, so dass gilt: Z2 =
U ◦ Z1 ◦ V
Eine Zeichenkette Z1 ist genau dann ein Anfangsstück (prefix) der Zeichenkette Z2, wenn es eine Zeichenkette V gibt, so dass gilt: Z2 = Z1 ◦ V
In der Programmiersprache C werden Zeichenketten derart abgespeichert, dass
jedes Zeichen unter Einhaltung der Reihenfolge des Vorkommens in der Zeichenkette durch ein Byte entsprechend seines ASCII–Codes abgespeichert und
am Schluss stets zusätzlich ein Endekennzeichen, nämlich ’\0’, angefügt wird.
21
gerichteter Graph
Ein gerichteter Graph G ist ein geordnetes Paar (Kn, Ka), wobei Kn eine Menge
(die Menge der Knoten von G) und Ka eine binäre Relation in Kn, d.h. Ka
⊆ Kn × Kn, ist. Es heißt Ka die Kantenmenge von G.
Zwei Knoten k1 und k2 , für die (k1, k2) ∈ Ka gilt, heißen benachbart (adjazent). Sie werden bei der zeichnerischen Darstellung des Graphen G durch eine
von k1 nach k2 gerichtete Kante verbunden (gerichtete Kanten werden in der
Literatur manchmal auch als Bögen bezeichnet). Es heißt k1 ein Vorgänger
von k2 , und k2 heißt ein Nachfolger von k1.
Beispiel: Kn := {1,2,3,4}, Ka := {(1,1), (1,2), (1,4), (2,4), (3,2), (4,3)}
zeichnerische Darstellung:
1
2
3
4
zugehörige Adjazenzmatrix:








1
0
0
0
1
0
1
0
0
0
0
1
1
1
0
0








Ein Weg (k1, k2, · · · , kn) in einem gerichteten Graph ist eine Liste bzw. ein
n–Tupel von Knoten, so dass stets ki+1 ein Nachfolger von ki , 1 ≤ i ≤ n − 1,
ist. Die Länge dieses Weges ist n − 1 (Anzahl der Bögen des Weges).
Ein Zyklus eines gerichteten Graphen ist ein Weg mindestens der Länge 1, der
am selben Knoten beginnt und endet. Z.B. ist im obigen Graphen der Bogen
(1,1) ein Zyklus der Länge 1.
22
ungerichteter Graph
Ein ungerichteter Graph G ist ein geordnetes Paar (Kn, Ka), wobei Kn eine
Menge (die Menge der Knoten von G) und Ka eine Menge von Zweiermengen mit Elementen aus Kn ist. Es heißt Ka die Kantenmenge von G.
Zwei Knoten k1 und k2 , für die {k1 , k2} ∈ Ka gilt, heißen benachbart (adjazent). Sie werden bei der zeichnerischen Darstellung des Graphen G durch eine
k1 mit k2 verbindende ungerichtete Kante verbunden.
Beispiel: Kn := {1,2,3,4}, Ka := {{1}, {1,2}, {1,4}, {2,4}, {3,2}, {4,3}} (beachte: {1,1}= {1})
zeichnerische Darstellung:
1
2
3
4
die zugehörige Adjazenzmatrix ist jetzt symmetrisch:








1
1
0
1
1
0
1
1
0
1
0
1
1
1
1
0








Ein Weg in einem ungerichteten Graph ist eine Liste (bzw. n–Tupel) (k1, k2, · · · , kn)
von Knoten, so dass stets ki+1 und ki , 1 ≤ i ≤ n − 1, benachbart sind. Die Länge dieses Weges ist n − 1 (Anzahl der Kanten des Weges).
Ein Zyklus eines ungerichteten Graphen ist ein Weg mindestens der Länge 1,
der am selben Knoten beginnt und endet.
Wenn in einem (gerichteten oder ungerichteten) Graphen durch eine Funktion
f: Ka → M jeder Kante ein Element aus einer bestimmten Menge M zugeordnet
wird, so spricht man von einem kantenbewerteten Graphen.
Analog ist der Begriff knotenbewerteter Graph definiert.
23
Variablen–Begriff
Eine Variable hat in der Informatik 3 Bestandteile: ihren Namen, ihren Typ
(festgelegt durch eine Typdeklaration; damit ist auch festgelegt, welche Werte die Variable überhaupt annehmen kann) und ihre Adresse (Nummer einer
Speicherzelle desjenigen Speicherbereiches, in dem der aktuelle Wert der Variablen abgelegt ist). Manchmal wird als vierter Bestandteil einer Variablen auch
ihr aktueller Wert mit hinzugenommen.
Variable
Name Typ Adresse Wert
Der Name ist in der Regel eine Zeichenkette, die mit einem (lateinischen) Buchstaben oder einem Unterstreichungsstrich (underscore) beginnt und an den evtl.
weiteren Positionen Buchstaben, Ziffern oder den Unterstreichungsstrich hat.
Durch den Typ ist festgelegt, wieviele Bytes zur Abspeicherung des jeweiligen
Wertes der Variablen bei der Typdeklaration reserviert werden und wie die Inhalte der Bytes zu interpretieren sind.
Beispielsweise werden durch die Variablendefinition (Variablendeklaration
plus Zuweisung eines Speicherbereichs)
int i;
in einem C–Programm der Variablen mit dem Namen i vier Bytes zum Abspeichern ihres jeweils aktuellen Wertes, der im Intervall [−231, 231 − 1] liegen kann,
zugewiesen. Durch die Variablendefinition plus Initialisierung
int i=1;
erhält die Variable zusätzlich den (Anfangs–)Wert Eins (der natürlich später
im Programm geändert werden kann).
Siehe hierzu auch die Folien cprog09.pdf zur C–Programmierung.
24
(naiver bzw. intuitiver) Algorithmusbegriff
Ein Algorithmus ist ein Verfahren, das Schritt für Schritt in diskreten Zeitabschnitten (Takten) abläuft, wobei zusätzlich gilt:
ˆ der erste Schritt ist festgelegt (eindeutiger Start)
ˆ immer dann, wenn ein Schritt ausgeführt worden ist, steht fest, welches
der nächste Schritt bzw. ob das Verfahren beendet ist (Eindeutigkeit
der Reihenfolge)
ˆ das Verfahren ist durch einen endlichen Text (in einer genügend ausdrucks-
fähigen natürlichen oder künstlichen Sprache) notierbar (Endlichkeit der
Darstellbarkeit)
ˆ man kann mit seiner Hilfe alle Aufgaben eines bestimmten Typs, etwa
abhängig von Parametern, lösen (Universalität)
Von den einzelnen Schritten wird verlangt, dass sie wirklich ausführbar sind
von einem realen oder gedachten Rechenautomaten mit geeignetem Befehlsvorrat.
lokale Determiniertheit eines Algorithmus:
die in jedem Schritt auszuführende Aktion muss eindeutig sein
globale Determiniertheit eines Algorithmus:
für alle in Frage kommenden Eingabedaten (inputs) werden in eindeutiger Weise Ausgabedaten (outputs) erzeugt, oder der Algorithmus terminiert nicht
In den einzelnen Schritten werden im einfachsten Fall Variablen Werte zugewiesen, z.B. i:=1 (Pascal– bzw. Delphi–Notation) bzw. i=1 (C–, C++–, Java–
Notation); gesprochen: ”i ergibt sich zu Eins”.
25
(3n+1)–Algorithmus mit Ausgabe der Zwischenwerte und der
Anzahl der durchgeführten Iterationen
Start
E: n
n natürliche Zahl
i:=0
i zählt Iterationen
n>1
nein
A: i
i:=i+1
ja
Stop
A: n
nein
n
gerade
ja
n:=3*n+1
n:=n/2
Bis heute konnte nicht gezeigt werden, dass der Algorithmus für jeden zugelassenen Eingabewert n terminiert, d.h. die Stop–Anweisung erreicht.
(Aufpassen bei der Implementierung: Es können Zahlbereichsüberschreitungen (overflow) vorkommen, die nicht angezeigt werden.)
26
(3n+1)–Algorithmus als Struktogramm
E: n
/* n als natuerliche Zahl */
i := 0
while n > 1
n gerade
ja
n := n/2
nein
n := 3n + 1
A: n
i := i+1
A: i
/* Anzahl der durchgefuehrten Iterationen */
Andere Notationsformen für die Ein– und Ausgabeanweisungen:
statt
E: n
A: n
notiere
n
n
bzw.
n
n
27
Notation des (3n+1)–Algorithmus in einem Pseudocode (nicht
genormte semiformale Notation)
Eingabe: n; /* n als natürliche Zahl */
i := 0; /* weise i den Wert 0 zu */
while (n > 1)
if (n gerade)
n := n/2;
else
n := 3 ∗ n + 1;
end if; /* Ende der if–Anweisung */
Ausgabe: n; /* Ausgabe des Wertes von n */
i := i + 1; /* erhöhe den Wert von i um Eins */
end while; /* Ende der while–Schleife */
Ausgabe: i; /* Anzahl der durchgeführten Iterationen */
Pseudocode:
ˆ künstliche Sprache zum Entwerfen und Darstellen von Algorithmen
ˆ zur Darstellung der strukturierenden Elemente bzw. des Kontrollflus-
ses (z. B. Auswahl, Iteration, Blockbegrenzung) wird oft eine PASCAL–
oder C–ähnliche Notation verwendet
ˆ die eigentlichen Verarbeitungsschritte können verbal oder formal formu-
liert sein
28
Euklidischer Algorithmus zur Bestimmung von ggt(m, n) für m, n ∈ N
(Euklid, um 300 v. Chr.)
E: m, n /* m, n nat. Zahlen mit n > 0 */
r := m mod n
m := n
n := r
until n=0
A: m /* der ggt der urspruenglichen m, n */
wenn zusätzlich ggt(0, 0) := 0 vereinbart wird:
E: m ,n /* m, n natuerliche Zahlen */
while n = 0
r := m mod n
m := n
n := r
A: m /* der ggt der urspruenglichen m, n */
Siehe beispielsweise auch euclid.pdf unter
http://www.imn.htwk-leipzig.de/~jahn/Cprog/Alg_Inf_Jahr_pdf
Dort befinden sich viele andere grundlegende Algorithmen.
29
ein schneller Algorithmus zur Berechnung von Potenzen mit
natürlichzahligen Exponenten
Der folgende Algorithmus (square and multiply) liefert für jede reelle Zahl
x 6= 0 und jede natürliche Zahl n als Ergebnis z den Wert der Potenz xn :
x, n
z:=1
while n>0
while n ist gerade
n := n div 2
x := x * x
n := n−1
z := z * x
z
Die Anzahl der durchzuführenden Multiplikationen ist nach oben beschränkt
durch 2 ∗ ⌊log2 (n)⌋ + 1.
Bei der ”gewöhnlichen” Potenzberechnung
x, n
z:=1
for i:=1 to n
z := z * x
z
müssen dagegen n Multiplikationen durchgeführt werden.
30
Suche in Texten
Ein einfacher Algorithmus, der alle Positionen der Zeichenkette ”a0 a1 · · · an−1 ”
ausgibt, ab denen die Zeichenkette ”b0b1 · · · bm−1” dort als Teilzeichenkette vorkommt, ist der folgende:
Eingabe: n, m; /* n, m als natürliche Zahlen */
Eingabe: a0 a1 · · · an−1, b0 b1 · · · bm−1
for i:=0 to n-m do
gefunden:=1;
for j:=0 to m-1 do
if (ai+j 6= bj )
gefunden:=0;
end if;
end for;
if (gefunden)
Ausgabe: i; /* Ausgabe einer Position */
end if;
end for;
Sind beispielsweise n = 8, m = 2, ”a0 a1 · · · an−1 ”= ”adabcaab”und ”b0b1 · · · bm−1”
= ”ab”, so werden duch den Algorithmus die folgenden Werte von i ausgegeben:
2, 6.
31
String–Matching–Problem
String–Matching–Problem:
Kommt eine bestimmte Zeichenkette als Teilzeichenkette in einer anderen Zeichenkette vor? (Entscheidungsproblem)
erweitertes String–Matching–Problem:
Bestimme alle Positionen in einer Zeichenkette, ab denen eine andere Zeichenkette dort vorkommt! (Berechnungsproblem)
Beispiel für ein Entscheidungsproblem:
Es seien A ein Alphabet mit {′ M ′ ,′ S ′ } ⊆ A und S := s0 · · · sn−1 eine Zeichenkette über A.
Kommt die Zeichenkette ”MMS” als Teilzeichenkette in S vor?
Modellierung dieses Problems mit Hilfe eines Akzeptors:
’M’
A\{’M’}
z0
’M’
z1
’M’
’S’
z2
z3
A
A\{’M’}
A \{’M’,’S’}
Dieser Automat befindet sich anfangs im Zustand z0 (Anfangszustand) und
arbeitet getaktet. Als erstes Zeichen von S wird s0 eingegeben. Je nachdem,
um welches Zeichen des Alphabetes es sich handelt, geht der Automat in den
Zustand z1 über (falls s0 =′ M ′ ist), oder er bleibt im Zustand z0 (falls s0 ∈
A \ {′M ′ } ist). Im zweiten Takt wird s1 betrachtet und ein entsprechender Zustandsübergang durchgeführt usw. Ausschlaggebend ist, ob der Automat sich
unmittelbar nach Verarbeitung von sn−1 im Zustand z3 (Endzustand) befindet oder nicht. Genau dann, wenn er sich zuletzt in diesem Zustand befindet,
wird die Zeichenkette S akzeptiert, was hier bedeutet, dass sie die Zeichenkette
′′
MMS ′′ (mindestens einmal) als Teilzeichenkette enthält.
32
ein aus dem Akzeptor resultierender Algorithmus
Der folgende Programmablaufplan entstand durch Übersetzung des Akzeptors,
der genau diejenigen Zeichenketten akzeptiert, die ”MMS” als eine Teilzeichenkette von sich enthalten, in einen Algorithmus. Die Zustände des Akzeptors
werden dabei durch Werte der Variablen z repräsentiert. Eingegeben werden
hier n (die Länge der Zeichenkette) sowie die Zeichenkette ”s0s1 · · · sn−1”.
(Bezogen auf die Programmiersprache C könnte man den Test, ob i < n ist,
auch ersetzen durch den Test, ob si 6=’\0’ ist.)
START
E: n, s o ,
... , s n−1
z := 0
i := 0
i<n
and z < 3
nein
z=3
nein
ja
i := i+1
ja
z=0
A: "ZK
akzept."
nein
ja
z=1
nein
s i = ’M’
ja
z := 1
A: " ZK nicht
akzept."
nein
ja
si = ’M’
nein
ja
z := 2
s i = ’S’
z := 0
STOP
nein
ja
s i = ’M’
z := 3
nein
z := 0
33
ja
Algorithmus als Struktogramm
Das folgende Struktogramm entstand durch Übersetzung des obigen Programmablaufplanes in die Sprache der Struktogramme. Bezüglich des Tests, ob i < n
ist oder nicht, gilt die gleiche Aussage wie auf der vorhergehenden Folie.
n, so, ... , s n−1
z := 0 ; i := 0
while i<n and z < 3
z=0
j
j
s i = ’M’
n
n
z=1
j
j
s i = ’M’
n
n
s = ’S’
i
j
n
s i = ’M’
n
j
z := 1
z := 2
z := 3
z := 0
z := 0
i := i+1
z=3
j
"Zeichenkette akzeptieren"
n
"Zeichenkette nicht akzeptieren"
34
Prüfungsplanung
Es sollen Prüfungen in verschiedenen Fächern zeitlich so geplant werden, dass
kein Student mehr als eine Prüfung pro Tag hat und zusätzlich die Anzahl der
Prüfungstage möglichst klein ist.
Modellierung durch einen (ungerichteten) Fächerkonfliktgraphen: Die einzelnen zur Prüfung anstehenden Fächer werden als Knoten des Graphen dargestellt. Es werden dann alle Paare von Knoten betrachtet. Genau dann, wenn die
beiden zu einem gerade betrachteten Paar von Knoten gehörenden Prüfungen
von mindestens ein und demselben Studenten zu absolvieren sind, werden diese
beiden Knoten durch eine Kante miteinander verbunden (sie stehen in Konflikt
zueinander).
Beispiel: Es seien vier Studenten S1, · · · , S4 in fünf Fächern F 1, · · · , F 5 zu prüfen. Die folgende Tabelle gibt an, wer in welchem Fach zu prüfen ist (Markierung
durch ′′ ∗′′ ):
S1
S2
S3
S4
F1 F2 F3 F4 F5
∗
∗ ∗
∗ ∗
∗ ∗
∗
Zugehöriger Fächerkonfliktgraph:
F1
F5
F2
F3
F4
Ebenfalls durch einen Konfliktgraphen kann beispielsweise die folgende Problemstellung modelliert werden:
Ein Unternehmen benötigt zur Produktion verschiedene Chemikalien, von denen
nicht alle im gleichen Raum gelagert werden dürfen. Von je zwei Chemikalien
ist aber bekannt, ob sie gefahrlos im gleichen Raum gelagert werden können
oder nicht.
35
Prüfungsplanung auf der Grundlage des Fächerkonfliktgraphen
(Kn, Ka)
Es werden nacheinander maximale unabhängige Teilmengen der Knotenmenge Kn bestimmt, wobei jede dieser Mengen die Fächer eines weiteren
Prüfungstages festlegt.
Dabei heiße eine nichtleere Teilmenge der Knotenmenge Kn genau dann unabhängig, wenn keine zwei Knoten dieser Menge durch eine Kante aus der
Kantenmenge Ka des Graphen miteinander verbunden sind. Alle Fächer einer
unabhängigen Knotenmenge können somit an ein und demselben Tag geprüft
werden.
Eine unabhängige Teilmenge der Knotenmenge heiße genau dann maximal
unabhängig, wenn die Hinzunahme irgendeines weiteren Knotens die Unabhängigkeit zerstören würde.
Somit heißt eine Menge M genau dann maximale unabhängige Teilmenge der
Knotenmenge Kn des Graphen (Kn, Ka), wenn gilt:
M ⊆ Kn ∧ M 6= ∅ ∧
∀a∀b(a ∈ M ∧ b ∈ M ∧ a 6= b → {a, b} ∈
/ Ka) ∧
∀a(a ∈ Kn \ M → ∃b(b ∈ M ∧ {a, b} ∈ Ka))
Dieser prädikatenlogische Ausdruck in Worten:
M ist eine Teilmenge der Knotenmenge und
M ist nicht leer und
keine zwei Elemente aus M sind durch eine Kante miteinander verbunden und
das Hinzunehmen eines weiteren Knotens zu M zerstört die Unabhängigkeit
von M
Beginnt man anhand des obigen Fächerkonfliktgraphen die Prüfungsplanung
mit dem Fach F 1 am ersten Prüfungstag, so können beispielsweise auch noch
die Fächer F 3 und F 4 an diesem Tag geprüft werden, mehr allerdings nicht. Es
ist also {F 1, F 3, F 4} eine maximale unabhängige Teilmenge der Knotenmenge
Kn. Die beiden übrigbleibenden Fächer F 2 und F 5 sind abhängig voneinander,
so dass sich zwei weitere Prüfungstage mit jeweils nur einem Prüfungsfach ergeben. Somit könnten die Fächer wie folgt auf drei Prüfungstage pt(1), pt(2), pt(3)
verteilt werden:
pt(1)
pt(2) pt(3)
F 1, F 3, F 4 F 2
F5
(Die eben angegebene Verteilung der Fächer ist nicht die einzig mögliche.)
36
ein Pseudocode für die Prüfungsplanung auf der Grundlage des
Fächerkonfliktgraphen (Kn, Ka)
Sukzessive Bestimmung maximaler unabhängiger Teilmengen von Kn, wobei
diese Mengen pt(1), pt(2), · · · die Mengen der Fächer, die an paarweise verschiedenen Prüfungstagen geprüft werden sollen, sind:
Eingabe: Kn, Ka
i := 0;
while (Kn 6= ∅)
{
i := i + 1;
/* neuer Prüfungstag */
f := bel(Kn);
pt(i) := {f };
/* nimm beliebiges Element f aus Kn */
/* Fach f wird am i–ten Tag geprüft */
Kn := Kn \ {f };
/* nimm f aus der Knotenmenge heraus */
forall (s ∈ Kn)
/* überprüfe, ob s unabhängig ist vom bisherigen pt(i) */
if (∀t(t ∈ pt(i) → {s, t} 6∈ Ka))
{
}
pt(i) := pt(i) ∪ {s}; /* auch Fach s wird am i–ten Tag geprüft */
Kn := Kn \ {s};
/* die folgende geschachtelte Schleife kann auch weggelassen werden */
forall (s ∈ pt(i))
forall (e ∈ Ka)
if (s ∈ e)
}
Ka := Ka \ {e};
/* Ausgabe: */
for (j := 1; j <= i; j + +)
print(j, pt(j));
37
Zahlendarstellungen in Stellenwert– bzw. Positionssystemen
Ein Stellenwert– bzw. Positionssystem wird festgelegt durch eine Basis b als
natürliche Zahl größer als Eins und die Menge Z seiner Ziffern, wobei Z =
{0, 1, · · · , b − 1} ist.
Eine natürliche Zahl kann dann dargestellt werden als Zeichenkette über Z,
wobei üblicherweise führende Nullen weggelassen werden (außer es handelt sich
um die Zahl Null selbst). Eine solche Zeichenkette
zn zn−1 · · · z0
wird als b–adische Darstellung der natürlichen Zahl mit dem Wert
zn ∗ bn + zn−1 ∗ bn−1 + · · · + z1 ∗ b + z0
bzw.
n
X
i=0
zi ∗ bi
bezeichnet.
b = 2 : Dualsystem
(von Gottfried Wilhelm Leibniz (1646–1716) eingeführt)
b = 8 : Oktalsystem
b = 10 : Dezimalsystem
b = 16 mit Z = {0, 1, · · · , 9, A, B, C, D, E, F } : Hexadezimalsystem
Man kann aber auch als Ziffern die zehn Tetraden 0000, 0001, 0010, 0011, 0100,
0101, 0110, 0111, 1000, 1001, die Dualdarstellungen der Zahlen von Null bis
Neun sind, und als Basis b = 10 verwenden und erhält damit das BCD–System
(BCD: binary coded decimal)
Eine echt gebrochene positive reelle Zahl mit endlich vielen Ziffern in b–adischer
Darstellung wird in Festpunktschreibweise in der Gestalt 0.z−1z−2 · · · z−n
notiert und hat den Wert
−1
X
i=−n
zi ∗ bi
38
Konvertierung einer natürlichen Zahl z von ihrer
Dezimaldarstellung in ihre Darstellung zur Basis b≥2
Man geht aus von einem Ansatz z = zn ∗ bn + zn−1 ∗ bn−1 + · · · + z1 ∗ b + z0 mit
zunächst unbekannten n, zn , · · · , z0 und erkennt, dass gilt:
z0 = z mod b
z1 = ((z − z0 ) div b) mod b
z2 = (((z − z0 ) div b) − z1 ) div b mod b
usw. Durch fortgesetzte Division mit Rest erhält man also die gesuchten
Ziffern, was auf folgenden Algorithmus führt:
START
z, b natürliche Zahlen,
b>=2
E: z, b
i:=0
Position der zu berech−
nenden Ziffer
q:=z div b
r:=z mod b
r: i−te Ziffer
A: r, i
q=0
ja
nein
STOP
i:=i+1
r:=q mod b
q:=q div b
Länge der b–adischen Darstellung einer natürlichen Zahl z > 0:
⌊logb (z)⌋ + 1 bzw. ⌊log10(z)/ log10 (b)⌋ + 1
39
Konvertierung einer natürlichen Zahl zn zn−1 · · · z0 zur Basis b≥2 in
ihre Dezimaldarstellung mittels HORNER–Schema
Hier nutzt man aus, dass zn ∗ bn + zn−1 ∗ bn−1 + · · · + z1 ∗ b + z0 bzw.
auch folgendermaßen geklammert werden kann:
Pn
i=0 zi
∗ bi
(· · · (((zn ∗ b + zn−1 ) ∗ b + zn−2 ) ∗ b + zn−3) ∗ b + · · · + z1 ) ∗ b + z0
Wertet man diesen Term entsprechend seiner Klammerung von innen nach außen aus, so führt das auf das Horner–Schema, das algorithmisch wie folgt dargestellt werden kann:
START
zn , ... , z o Ziffern der
Zahl zur Basis b, b>=2
E: n, z n , ... , z o
i := n
z := z i
i>0
nein
ja
i := i−1
z := z*b + z i
A: z
STOP
40
Zahl zur
Basis 10
Konvertierung einer echt gebrochenen positiven Dezimalzahl q in
ihre Darstellung zur Basis b, b≥2
Um die Ziffern der b–adischen Darstellung von q zu erhalten, macht man den
Ansatz q = z−1 ∗ b−1 + z−2 ∗ b−2 + · · · mit zunächst unbekannten z−1, z−2 · · · und
unbekannter Anzahl der Ziffern. Man erkennt, dass gilt:
z−1 = ⌊q ∗ b⌋
z−2 = ⌊(q ∗ b − z−1 ) ∗ b⌋
usw. Dies führt auf den folgenden Algorithmus:
START
q: echt gebrochene Zahl >0
in Dezimaldarstellung
E: q, b
Position der zu bestimmenden
Ziffer nach dem Punkt
i := 1
q=0
ja
nein
q := q * b
STOP
z:=floor(q)
A: z, i
q := q − z
i := i + 1
Eine rationale Zahl hat stets eine endliche oder periodische unendliche b–adische
Darstellung.
41
Interne Darstellungen ganzer Zahlen
Falls n Bit für die interne Darstellung zur Verfügung stehen, so werden Konstanten und die Werte von Variablen von
ˆ unsigned–Typen (unsigned short, unsigned int, unsigned long und unsi-
gned long long) durch ihr duales Äquivalent intern abgespeichert, so dass
also genau die Werte von 0 bis 2n − 1 möglich sind
ˆ signed–Typen (short, int, long und long long) derart intern abgespei-
chert, dass die Werte von 0 bis 2n−1 − 1 durch ihr duales Äquivalent (genau hier hat das höchstwertige Bit den Wert 0) dargestellt und die übrigen möglichen internen Darstellungen (das sind diejenigen, bei denen das
höchstwertige Bit den Wert 1 hat) als negative Werte interpretiert werden,
deren Betrag das duale Äquivalent des Zweierkomplements der internen
Darstellung ist
(siehe dazu beispielweise auch die entsprechenden Folien von cprog09.pdf)
Das Zweierkomplement einer natürlichen Zahl k < 2n bzgl. eines Datenformats von n Bit hat den Wert 2n − k.
Es gilt für jedes k mit 0 ≤ k < 2n :
(Zweierkomplement von k bzgl. n Bit) =
(Einerkomplement von k bzgl. n Bit) + 1,
wobei das Einer– bzw. Stellenkomplement von k bzgl. n Bit als bitweise
Negation der dualen Darstellung von k, vorher durch führende Nullen auf die
Länge n ergänzt, ist.
So sind also beispielsweise als Werte von Variablen des Typs short (intern 16
Bit) die Zahlen von −215 bis 215 − 1 möglich mit folgenden internen Darstellungen:
dezimaler Wert
−32768
−32767
..
.
−2
−1
0
1
2
..
.
32767
interne Darstellung
10000000 00000000
10000000 00000001
..
.
11111111 11111110
11111111 11111111
00000000 00000000
00000000 00000001
00000000 00000010
..
.
01111111 11111111
(siehe z. B. auch die Programme int dar1.c und limit int1.c)
42
reelle Datentypen
Reelle Zahlen werden intern als Gleitpunktzahlen (Fließkommazahlen, floating point numbers) abgespeichert. Über die Tastatur werden sie als Festpunktzahlen (z. B. 3.1415) oder als Gleitpunktzahlen (z. B. 314.15e-2 oder
314.15E-2) eingegeben und dann in ihre internen Darstellungen konvertiert.
Beachte: Schon beispielsweise die Dezimalzahl 0.1 kann intern nicht exakt abgespeichert werden, da ihre duale Darstellung periodisch unendlich ist.
Von der Gleitpunktzahl 314.15e-2 ist 314.15 ihre Mantisse, e das Exponentenkennzeichen (für die Basis 10) und -2 der Exponent (zur Basis 10).
Intern werden Gleitpunktzahlen im ANSI/IEEE–Format abgespeichert, und
zwar in der Regel als normalisierte Gleitpunktzahlen, wobei anstelle des
Exponenten die Charakteristik verwendet wird.
Eine normalisiert duale Mantisse beginnt mit einer 1, gefolgt vom Dualpunkt
und weiteren Dualziffern. Dabei wird die 1 vor dem Punkt nicht mit abgespeichert, aber natürlich bei Berechnungen mit berücksichtigt.
Die folgende Tabelle zeigt für die reellen Datentypen float, double und long
double die Anzahlen der für ihre internen Darstellungen verwendeten Bytes
und wieviele Bits davon für die Mantissen (ohne das Normalisierungsbit), die
Charakteristiken und das Vorzeichen der Zahl benutzt werden:
Anz. Bytes Anz. Bits Mant. Anz. Bits Char. Anz. Bits Vorz.
float
4
23
8
1
double
8
52
11
1
long double 10 (Intel)
63
16
1
16 (Sparc)
112
15
1
(siehe insbesondere auch das Programm limit float1.c)
Je größer die Anzahl der Mantissenstellen ist, um so dichter liegen die Maschinenzahlen und umso genauer können Zahlen intern dargestellt werden.
Die Lücken zwischen benachbarten Maschinenzahlen werden nach außen hin
(von der Null weg) immer größer.
Je größer die Anzahl der Bits für die Charakteristik ist, umso größer ist die jeweils größte intern darstellbare und umso kleiner ist die kleinste positive intern
darstellbare Maschinenzahl.
Die intern darstellbaren Gleitpunktzahlen liegen symmetrisch zur Null.
43
Interne Darstellung von 4–Byte–Gleitpunktzahlen nach ANSI/IEEE
754
ANSI: American Standard Institute
IEEE: Institute of Electrical and Electronics Engineers
Vorzeichen VZ Charakteristik c Mantisse m
1 Bit
8 Bit
23 Bit
Wert einer solchen internen Darstellung:
c 6= 0000 0000 (c 6= 0) und c 6= 1111 1111 (c 6= 255):
(−1)V Z ∗ 2c−127 ∗ (1.m)2 (normalisierte Darstellung)
größte darstellbare normalisierte Zahl:
(−1)0 ∗ 2127 ∗ (1.7F F F F F )16 = 2127 ∗ (2 − 2−23) ≈ 3.4 ∗ 1038
kleinste darstellbare normalisierte positive Zahl:
(−1)0 ∗ 21−127 ∗ (1.0 · · · 0)2 = 2−126 ≈ 1.1754 ∗ 10−38
Sonderfälle:
c = 0, m = 0: 0
c = 0, m 6= 0: (−1)V Z ∗ 2−126 ∗ (0.m)2
(bei sehr kleinen Werten wird die Normalisierung aufgehoben, so dass
2−126 ∗ 2−23 = 2−149 ≈ 1.4013 ∗ 10−45
die kleinste intern darstellbare positive Zahl ist; im Falle c=0 ist -126 als zugehöriger Exponent festgelegt, diese Zahl ist auch für normalisierte interne Darstellungen der kleinstmögliche Exponent)
c = 255, m = 0: ”(−1)V Z ∗ ∞”
√
c = 255, m =
6 0: NaN (Not a Number, z.B. für ” −2”, ”0/0”, ”0 ∗ ∞”)
Beispiel: interne Darstellung der Dezimalzahl -19.625 im float–Format
Da (−19.625)10 = (−10011.101)2 = −24 ∗ (1.00111010 · · · 0)2 ist, ergibt sich
1 1000 0011 001 1101 0000 0000 0000 0000
(die ”1” vor dem Dualpunkt wird nicht mit abgespeichert).
Die internen Darstellungen von Gleitpunktzahlen behandeln z. B. die Programme int float1.c und int float2.c.
siehe dazu beispielsweise Blieberger, J., Burgstaller, B. und G.–H. Schildt: Informatik Grundlagen. Springer–Verlag Wien 2005
44
Gleitpunktarithmetik
Wenn im Computer mit Gleitpunktzahlen gerechnet wird, so werden laufend
Rundungsfehler gemacht. Diese werden nicht angezeigt, nur wenn die größte
intern darstellbare Zahl (z. B. ≈ 3.4 ∗ 1038 für den Datentyp float) überschritten
oder die kleinste (negative) intern darstellbare Zahl (z. B. ≈ −3.4 ∗ 1038 für den
Datentyp float) unterschritten werden, so werden eine overflow–Fehlermeldung
ausgegeben und die Berechnung abgebrochen.
Addition bzw. Subtraktion zweier Gleitpunktzahlen im Computer:
ˆ falls die beiden Exponenten unterschiedlich groß sind, so werden der klei-
nere der beiden Exponenten an den größeren angepasst und der Dualpunkt entsprechend verschoben; jetzt stehen die Mantissenstellen zu gleichen Zweierpotenzen untereinander
ˆ Addition bzw. Subtraktion der Mantissen
ˆ Normalisierung des Ergebnisses (falls notwendig)
ˆ Rundung auf das vorgegebene interne Format (falls Anzahl der Mantissen-
stellen zu groß)
Multiplikation bzw. Division zweier Gleitpunktzahlen im Computer:
ˆ Multiplikation bzw. Division der Mantissen
ˆ Addition bzw. Subtraktion der Exponenten
ˆ Normalisierung des Ergebnisses (falls notwendig)
ˆ Rundung auf das vorgegebene interne Format (falls Anzahl der Mantissen-
stellen zu groß)
Bezüglich dieser Gleitpunktarithmetik gelten aufgrund der Rundungsfehler manche der Rechengesetze, wie sie bei exakter Rechnung gelten, nicht mehr. Auch
ist der Test zweier Gleitpunktzahlen im Computer auf Gleichheit nur mit Vorsicht zu verwenden, da die exakten Werte i. A. nicht bekannt sind.
45
Rundungsfehler und Maschinengenauigkeit
Rundung einer normalisierten dualen Gleitpunktzahl x mit mehr als t Mantissenstellen nach dem Dualpunkt auf t Stellen nach dem Dualpunkt:
Es sei
x := 1.z1z2 · · · zt zt+1 · · · ∗ 2e
Dann sei


rd(x) := 
1.z1z2 · · · zt ∗ 2e
(1.z1z2 · · · zt zt+1 + 2−t−1) ∗ 2e
falls zt+1 = 0
falls zt+1 = 1
Damit gilt für den relativen Fehler von rd(x), falls x 6= 0 ist:
rd(x) −
x
x ≤ 2−t−1 =
1
∗ 2−t
2
Werden anstelle des Rundens die Mantissenstellen nach zt einfach abgeschnitten (”chopping”) und heißt der dabei erhaltene Wert chp(x), so gilt für dessen
relativen Fehler
chp(x) − x ≤ 2−t
(x 6= 0)
x
Diese Zahl 2−t heißt Maschinengenauigkeit und hat also beispielsweise für
den Datentyp float den Wert 2−23 (die Maschinengenauigkeiten sind in float.h
definiert und haben dort die Namen FLT EPSILON, DBL EPSILON und LDBL EPSILON, siehe auch limit float1.c und masch gen.c).
Pseudocode zur Berechnung der Maschinengenauigkeit masch eps:
masch_eps := 0.5;
x := 1.0;
while (masch_eps + x > x)
masch_eps := masch_eps * 0.5; (fortgesetzte Halbierung)
masch_eps := masch_eps * 2.0; (letzte Halbierung rueckgaengig)
Ausgabe: masch_eps
Es ist masch eps die kleinste positive Zweierpotenz mit negativem Exponenten,
so dass die Gleitpunktzahl 1.0 + masch eps im Computer gerade noch als Zahl
größer als 1.0 erkannt wird.
Zahlen x, deren exakte Werte betragsmäßig zwischen 0 und der kleinsten (nichtnormalisierten) internen Gleitpunktzahl liegen, befinden sich im underflow–
Bereich und werden auf den Wert 0 gerundet. Hier ergibt sich ein relativer
Fehler von 1 bzw. von 100%, sämtliche in x enthaltenen Informationen gehen verloren!
46
Numbercruncher
Top 3 der Supercomputer (Juni 2009) nach LINPACK-Benchmark
(Quelle: www.top500.org/lists/2009/06)
LINPACK: Numerische Programmbibliothek zum Lösen von linearen Gleichungssystemen, wird aber auch als Name für ein Programm zum Messen der Geschwindigkeit eines Computers verwendet. LINPACK-Programme sind normalerweise in Fortran verfasst.
Rang
Hersteller
Rechner
Standort
Leistung
(Petaflops)
1
IBM
Roadrunner
PowerXCell (12.8 GFlops)
Los Alamos
National Labs, USA
1.105
2
Cray Inc.
Jaguar Cray XT5
AMD x86 64 Opteron
Quad Core (9.2 GFlops)
Oak Ridge National Labs,
Oak Ridge, USA
1.059
3
IBM
JUGENE, Blue Gene/P
PowerPC 450 (3.4 GFlops)
Forschungszentrum Jülich
Deutschland
0.826
JUGENE ist der erste europäische Supercomputer mit einer Leistung von rund
einem Petaflops, also einer Billiarde Rechenoperationen pro Sekunde. Dies entspricht der Rechenleistung von mehr als 25 000 handelsüblichen PCs, vorausgesetzt, sie würden über ein genau so starkes Datennetzwerk verbunden wie die
Prozessoren in einem Supercomputer.
Er besitzt 73728 Prozessoren, die in 72 wassergekühlten Schränken untergebracht sind und hat eine Leistungsaufnahme von 2.2 Megawatt. Der Arbeitsspeicher ist rund 144 Terabyte groß.
JUGENE wird benutzt für Berechnungen und Simulationen in den Bereichen
Physik, Chemie, Biologie, Astronomie sowie Material– und Umweltwissenschaften.
Im Jahr 2016 soll die 100–Petaflops–Marke geknackt werden.
Teraflops und Rundungsfehler: Schon ein Teraflops–Computer kann in jeder Sekunde soviele Zahlen erzeugen, wie auf einen Stapel von 100 Kilometern
Höhe dünner Papierblätter passen, wenn auf jedes Blatt 1000 Zahlen geschrieben würden und 100 Blatt Papier einen Stapel von 1 cm Höhe ergeben. So
drängt sich die Frage auf, wie genau ein berechnetes Ergebnis ist, denn bei
Durchführung jeder Gleitpunktoperation werden Rundungsfehler gemacht (siehe auch die Programme double1.c bis double9.c).
47
Begriff der Grammatik
Eine Grammatik G ist ein Viertupel (T, N, P, S) mit
(a) T und N sind endliche Mengen mit T ∩ N = ∅;
T heißt Menge der Terminalsymbole, N heißt Menge der
Nichtterminalsymbole (Metasymbole)
(b) P ist eine endliche Menge von Produktionsregeln (Ableitungsregeln)
der Gestalt u → v, wobei u, v ∈ (T ∪ N )∗ sind und u wenigstens ein
Nichtterminalsymbol enthält
Anwendung einer solchen Regel: u darf in einer Ableitung durch v ersetzt
werden
(c) S ist das Startsymbol (S ∈ N )
Eine Grammatik heißt genau dann kontextfrei, falls für alle Produktionsregeln
gilt, dass die linke Seite u ein Nichtterminalsymbol ist.
Die durch eine Grammatik G erzeugte Sprache L(G) bestehe aus genau denjenigen Zeichenketten, die höchstens Terminalsymbole enthalten und aus dem
Startsymbol in endlich vielen Schritten abgeleitet werden können.
Zwei Grammatiken G1 und G2 heißen genau dann äquivalent, wenn L(G1) =
L(G2) ist.
Kontextfreie Grammatiken spielen eine herausragende Rolle bei der Definition
der Syntax von Programmen.
48
Backus–Naur–Grammatiken
Bei den Erweiterten Backus–Naur–Form–Grammatiken (EBNF–Grammatiken)
handelt es sich um eine spezielle Notationsform für kontextfreie Grammatiken.
Dabei wird anstelle von ”u → v” meist ”< u > ::= v” geschrieben, und u muss
ein Nichtterminalsymbol sein.
Weiterhin werden folgende Vereinbarungen getroffen:
ˆ die endlich vielen Regeln
< u > ::= v1, < u > ::= v2, · · · , < u > ::= vn
können zusammengefasst werden in
< u > ::= v1|v2 | · · · |vn
(Alternative)
ˆ die beiden Regeln
< u > ::= αγ, < u > ::= αβγ
können zusammengefasst werden in
< u > ::= α[β]γ
(Option)
ˆ die drei Regeln
< u > ::= αγ, < u > ::= α < u1 > γ, < u1 > ::= β | < u1 > β
können mit u als Startsymbol zusammengefasst werden in
< u > ::= αβ ∗ γ
(manchmal auch < u > ::= α{β}γ)
(Wiederholung)
ˆ die zwei Regeln
< u > ::= α < u1 > γ, < u1 > ::= β | < u1 > β
können mit u als Startsymbol zusammengefasst werden in
< u > ::= αβ + γ
(Wiederholung, mindestens einmal)
Bei dieser Notationsform muss man sicherstellen, dass die spitzen, eckigen und
geschweiften Klammern sowie der senkrechte Strich nicht zu N ∪ T gehören.
Definition der Menge aller Zeichenketten über {a, b} der Gestalt an bn mit n ∈ N:
T := {a, b},
N := {S},
P : < S > ::= ε | a < S > b
Mit Hilfe der ersten Ableitungsregel < S > ::= ε wird erreicht, dass die leere
Zeichenkette zur Sprache gehört.
Davon ausgehend können mit Hilfe der zweiten Regel nacheinander die Zeichenkette ′′ ab′′ , ′′ aabb′′ , ′′ aaabbb′′ usw. abgeleitet werden.
49
Syntax–Diagramme
EBNF–Grammatiken können auch mit Hilfe von Syntaxdiagrammen dargestellt werden. Das sind spezielle gerichtete Graphen mit je einer zusätzlichen
Eingangs– und Ausgangskante und zwei Arten von Knoten: Ein runder bzw.
ovaler Knoten enthält ein Terminalsymbol, ein rechteckiger ein Nichtterminalsymbol.
Ist α1 · · · αn eine Zeichenkette aus (T ∪ N )∗ und < u >::= α1 · · · αn eine Regel
der Grammatik, so wird dieser Regel das folgende Syntaxdiagramm zur Definition von u zugeordnet:
u:
α1
αn
Dabei ist hier und in den folgenden Diagrammen das Sechseck als ein Metasymbol zu betrachten. Je nachdem, ob der Inhalt im konkreten Fall ein
Terminal– oder ein Nichtterminalsymbol ist, ist das Sechseck durch einen Kreis
(bzw. eine Ellipse) oder durch ein Rechteck zu ersetzen. Der Ableitungsregel
< u >::= ε (aus u ist das leere Wort ableitbar) soll dabei das Sytaxdiagramm
ohne Knoten
u:
entsprechen.
Transformation der übrigen Regeln:
< u >::= v1|v2 | · · · |vn :
v1
u:
v2
vn
< u >::= α[β]γ:
u:
α
γ
β
50
< u >::= αβ ∗γ:
u:
α
γ
β
< u >::= αβ + γ:
u:
α
β
γ
Die Zeichenketten an bn mit n ∈ N können somit durch ein Syntaxdiagramm
wie folgt definiert werden:
S:
a
S
b
Um alle Zeichenketten über {a, b} zu erhalten, kann man folgendes Syntaxdiagramm verwenden:
S:
a
b
Syntaxdiagramme werden insbesondere auch zur Definition syntaktischer Konstrukte von Programmiersprachen eingesetzt. Genau diejenigen Zeichenketten,
die höchstens Terminalsymbole enthalten und die man erhält, wenn man das
Syntaxdiagramm beginnend mit der Eingangskante bis zur Ausgangskante stets
in Pfeilrichtung durchläuft, sind die Zeichenketten der durch das Diagramm definierten Sprache. Trifft man dabei ein Nichtterminalsymbol an, so darf dieses
ersetzt werden durch eine Zeichenkette, die schon vorher als aus diesem Symbol
ableitbare Zeichenkette erhalten wurde.
51
PEANOsches Axiomensystem
(Giuseppe Peano, 1858 - 1932)
Die Menge N der natürlichen Zahlen erfüllt zusammen mit der Zahl 0 und der
Nachfolgerfunktion ν die folgenden Axiome:
(a) die Zahl 0 ist eine natürliche Zahl, d.h., 0 gehört zu N
(b) ν ist eine Funktion von der Menge N in die Menge N
(c) für jede natürliche Zahl n ist ν(n) 6= 0
(d) für zwei beliebige natürliche Zahlen m und n folgt aus ν(n) = ν(m), dass
n = m ist
(e) jede Menge M, die die 0 und mit jedem n auch ν(n) enthält, umfasst die
Menge N, d.h. ist eine Obermenge von N
(Induktionsaxiom)
Die Axiome in formaler Notation:
(a) 0 ∈ N
(b) ν : N → N
(c) ∀n(n ∈ N → ν(n) 6= 0)
(d) ∀m∀n(n, m ∈ N ∧ ν(n) = ν(m) → n = m)
(e) ∀M(0 ∈ M ∧ ∀n(n ∈ M → ν(n) ∈ M) → N ⊆ M)
Bemerkung: Bei manchen Autoren ist die Zahl 0 keine natürliche Zahl, so dass
dort N = {1, 2, 3, · · ·} ist. Sie definieren meist noch eine Menge N0 mit N0 :=
N ∪ {0}.
52
Modelle der natürlichen Zahlen
Aufgrund des Peano’schen Axiomensystems kann man die natürlichen Zahlen
dadurch repräsentieren, dass man ein ausgezeichnetes Element hat, welches die
Null darstellt und weiterhin eine Nachfolgerfunktion ν, so dass die Axiome alle
erfüllt sind.
Beispiele dazu:
ˆ die natürlichen Zahlen als Zeichenketten über dem einelementigen Alpha-
bet {|}
Als Repräsentant der Zahl Null nimm die leere Zeichenkette ε und als Nachfolgerfunktion ν die Verkettung mit dem Zeichen ’|’, also ν(n) := n ◦ |.
Dann ist N = {ε, |, ||, |||, · · ·}, und alle Axiome sind erfüllt.
ˆ die natürlichen Zahlen als spezielle Mengen, konstruiert ausgehend von der
leeren Menge
Als Repräsentant der Zahl Null nimm die leere Menge ∅ und als Nachfolgerfunktion ν die Vereinigung der ursprünglichen Menge mit der Einermenge
davon: für jede Menge M sei ν(M) := M ∪ {M}.
Dann ist N = {∅, {∅}, {∅, {∅}}, {∅, {∅}, {∅, {∅}}}, · · ·}, und alle Axiome
sind ebenfalls erfüllt.
Der Prozess der Erzeugung der natürlichen Zahlen als Strichfolgen kann auch
mit Hilfe eines Syntaxdiagramms veranschaulicht werden:
nat_zahl:
nat_zahl
|
Hierbei handelt es sich um ein rekursives Syntaxdiagramm, denn das zu definierende Objekt nat zahl kommt selbst im Syntaxdiagramm vor.
Das folgende Syntaxdiagramm ist eine nicht–rekursive, iterative Variante zur
Definition von nat zahl:
nat_zahl:
|
53
induktive Beweise
Es soll eine Aussage
”für alle natürlichen Zahlen n ≥ n0 gilt A(n)”
induktiv bewiesen werden;
es soll also gezeigt werden, dass A(n) für alle n ≥ n0 gilt (oft ist n0 = 0 oder
n0 = 1).
Dann kann man folgendermaßen vorgehen (s. auch Aho/Ullman, S. 44):
1. lege die Fälle für den Induktions–Anfang fest, d.h., lege eine zweite natürliche Zahl m0 ≥ n0 fest;
2. Induktions–Anfang: beweise, dass A(n0), A(n0 + 1), · · · , A(m0) alle
gelten
(oft ist m0 = n0, so dass dann nur A(n0) zu zeigen ist);
3. Induktions–Schritt:
(a) Induktions–Annahme: nimm an, dass A(n0), A(n0 + 1), · · · , A(n) alle
für irgendein beliebiges n ≥ m0 gelten;
(b) Induktions–Schluss: zeige, dass dann A(n + 1) gilt
Anders formuliert: Es ist im Induktions–Schritt zu zeigen, dass immer
dann, wenn für irgendein n ≥ m0 alle Aussagen A(n0), A(n0 + 1), · · · ,
A(n) gelten, dann auch A(n + 1) gilt.
Wenn der Beweis gelingt, so ist gezeigt, dass A(n) für alle n ≥ n0 gilt.
Wie n0 und m0 festgelegt werden, hängt von der Problemstellung ab.
Wie A(n0), A(n0 + 1), · · · , A(m0) und im Induktions–Schritt A(n + 1) bewiesen werden können, hängt vom konkreten Problem ab (man benötigt u. a.
problemspezifisches Wissen) und kann nicht weiter schematisiert werden.
Das obige Verfahren heißt auch Prinzip der ordnungstheoretischen bzw.
verallgemeinerten vollständigen bzw. starken Induktion (strong induction).
Beim Prinzip der vollständigen Induktion ist n0 = m0 , und die Induktions–
Annahme sieht folgendermaßen aus:
nimm an, dass A(n) für irgendein beliebiges n ≥ m0 gilt
Rechtfertigen lassen sich diese Beweisprinzipien mit Hilfe des Axiomensystems
von Peano.
54
ein paar Beispiele immer wieder benötigter Aussagen, die induktiv
bewiesen werden können
1. Für alle natürlichen Zahlen n ≥ 0 hat die Potenzmenge PM einer Menge
M mit n Elementen genau 2n Elemente.
2. Für alle natürlichen Zahlen n ≥ 0 gibt es über einem Alphabet mit k > 1
Elementen genau
k n+1 − 1
k−1
Zeichenketten mit Längen von 0 bis n.
n
3. Für alle natürlichen Zahlen n ≥ 0 gibt es genau 2(2 ) n–stellige Funktionen
f: {0, 1}n → {0, 1}.
4. für alle natürlichen Zahlen n ≥ 1 ist
n−1
X i
i=0
2 = 2n − 1
5. für alle natürlichen Zahlen n ≥ 1 ist
n
X
i=
i=1
n(n + 1)
2
6. für alle natürlichen Zahlen n ≥ 1 ist
n
X
2
i =
i=1
n ∗ (n + 1) ∗ (2n + 1)
6
7. für alle natürlichen Zahlen n ≥ 1 ist
n2 ∗ (n + 1)2
i =
4
i=1
n
X
3
8. für alle natürlichen Zahlen n ≥ 0 ist
n
X
i=0
 
n
= 2n
i
 
9. für alle natürlichen Zahlen n ≥ 1 ist
n
X
(2i − 1) = n2
i=1
55
induktive bzw. rekursive Definition einer Menge M
ˆ Rekursions–Anfang
es werden explizit Objekte genannt, die zu M gehören sollen
ˆ Rekursions–Schritt
ausgehend von Objekten, von denen man bereits weiß, dass sie zu M gehören, werden nach bestimmten Vorschriften weitere Objekte konstruiert,
die zu M gehören sollen
ˆ Abschluss bzw. Minimalbedingung
nur solche Objekte sollen zu M gehören, die aufgrund des Rekursions–
Anfanges und des Rekursions–Schrittes erhalten werden können
induktiver Beweis dafür, dass alle Elemente einer rekursiv
definierten Menge M eine bestimmte Eigenschaft haben:
man zeigt, dass
ˆ Induktions–Anfang
die durch den Rekursions–Anfang definierten Elemente von M die fragliche
Eigenschaft haben
ˆ Induktions–Schritt
daraus, dass Elemente von M die Eigenschaft haben, folgt, dass die aus ihnen mittels des Rekursions–Schrittes konstruierten Elemente von M ebenfalls die Eigenschaft haben
Dieses Beweisverfahren wird auch als Methode der strukturellen Induktion
bezeichnet.
56
Signatur eines Datentyps
Ein Datentyp besteht aus einer Menge (der Trägermenge des Datentyps)
sowie darauf erklärten Funktionen.
Auf der Basis der Signatur eines Datentyps können auf die bekannte Weise
rekursiv oder durch eine EBNF–Grammatik oder durch Syntax–Diagramme die
zu dem Datentyp gehörigen Terme definiert werden.
Hier soll als Beispiel die Signatur des Datentyps int angegeben werden.
sorts: Zint (Trägermenge, d.h. {i ∈ Z | IN T MIN ≤ i ≤ IN T MAX})
(Menge der int–Konstanten bzw. der möglichen Werte von Variablen des Typs int)
ops:
INT MIN , INT MAX : → Zint
(int–Konstanten können als nullstellige Operationen in C für den Datentyp int
aufgefasst werden.)
+ , - , ++ , - - , ∼ , ! : Zint → Zint
(einstellige Operationen in C für den Datentyp int)
+ , - , * , / , % , << , >> , & , | , ∧ : Zint × Zint
(zweistellige Operationen in C für den Datentyp int)
rels:
== , != , < , <= , > , >=
(zweistellige Relationen in Zint)
→
Zint
Zint × Zint
:
Andere Variante (hier werden die zweistelligen Relationen als zweistellige Funktionen von Zint ×Zint in die Menge {true, f alse} der Wahrheitswerte aufgefasst):
sorts:
Zint
functs: INT MIN , INT MAX :
+ , - , ++ , - - , ∼ , !
:
→
Zint
Zint
→
+ , - , * , / , % , << , >> , & , | ,
== , != , < , <= , > , >=
∧
Zint
:
Zint × Zint
: Zint × Zint
→
Zint
{true, f alse}
Analog können die Signaturen anderer Datentypen angegeben werden.
57
→
int–Terme
Auf der Basis der vorhergehenden Folie wird als Beispiel eine rekursive Definition des Begriffs des int–Termes für die Programmiersprache C angegeben:
(a) Rekursions–Anfang
Jedes Element aus Zint und jede Variable vom Typ int sei ein int–Term.
Für jede Variable var vom Typ int seien
++var , - -var , +var , -var , ∼ var , !var , var++ und var- int–Terme.
(b) Rekursions–Schritt
Es seien T , T1 und T2 int–Terme;
(α) Ist f ein einstelliges Operationssymbol, das zur Signatur von int gehört
und verschieden von ”++” und von ”- -” ist, so sei auch
f (T )
ein int–Term
(besitzt T bereits ein äußeres Klammernpaar, so f T ).
(β) Ist g ein zweistelliges Operationssymbol, das zur Signatur von int gehört, so sei auch
(T1 g T2 )
ein int–Term.
(c) Minimalbedingung
Nur aufgrund von (a) und (b) sollen int–Terme erhalten werden können.
Sind also beispielsweise i, j und k Variablen vom Typ int, so sind in C u. a.
folgende int–Terme möglich:
INT MIN , 34 , i , ++i , ∼ k , -j , !i , j−− , · · · (aufgrund des Rekursions–
Anfangs)
(i+j) , ((i << j) % k) , ((k ∧ i) / (j - i)) , · · · (aufgrund des Rekursions–Schritts)
58
rekursive Definition einer Menge natürlichzahliger Terme
Es soll die Menge arith term aller derjenigen arithmetischen Terme konstruiert
werden, die an Konstanten nur natürliche Zahlen, an Variablen (für natürliche
Zahlen) nur i, j, k, m, n und an Operationssymbolen nur die zweistelligen ”+”
und ”*” enthalten dürfen; die Terme sind vollständig zu klammern.
Rekursions–Anfang:
jede natürliche Zahl gehöre zu arith term; außerdem gelte i,j,k,m,n ∈ arith term;
Rekursions–Schritt:
es seien T1 und T2 bereits vorhandene Terme, d.h. T1, T2 ∈ arith term;
dann seien auch (T1 + T2) und (T1 * T2) arithmetische Terme, d.h., (T1 +
T2), (T1 * T2) ∈ arith term;
Abschluss:
nur solche Zeichenketten sollen zu arith term gehören, die aufgrund des Rek.–
Anfangs oder Rek.–Schritts erhalten werden können;
Beispiele für Elemente von arith term:
3
,
n
,
k
,
(3+n)
,
((3+n)*k)
,
(i+((3+n)*k))
Syntaxbaum des letzten Termes:
+
i
*
+
3
k
n
Die hier definierten Terme heißen auch Terme in infix–Notation oder einfach infix–Terme, weil die binären Operationssymbole zwischen den Operanden notiert werden. Daneben können Terme auch klammernfrei in präfix– und
postfix–Notation angegeben werden.
59
Bäume (trees)
Ein Baum ist ein spezieller gerichteter Graph.
Ein gerichteter Graph B:=(Ka, Kn) heißt genau dann (gerichteter) Baum, wenn
1. es genau einen Knoten w ∈ Kn gibt, der keinen Vorgänger in B hat (dieser
Knoten heißt die Wurzel von B) oder wenn Kn = ∅ (leerer Baum) ist
2. es von der Wurzel zu jedem anderen Knoten jeweils genau einen gerichteten
Weg (in Pfeilrichtung zu durchlaufen) gibt
(Bäume im Sinne dieser Definition werden manchmal auch als Wurzelbäume
bzw. rooted trees bezeichnet.)
Somit ist ein Baum zusammenhängend und zyklenfrei.
Diejenigen Knoten, die keinen Nachfolger in B haben, heißen die Blätter von
B.
Übliche zeichnerische Darstellung bei endlichen Knotenmengen: Die Wurzel
wird normalerweise oben gezeichnet, und ein Knoten, der Nachfolger eines anderen ist, wird unterhalb seines Vorgängers angeordnet (und mit ihm verbunden).
Dadurch können die Pfeilspitzen eingespart werden.
Die Höhe eines Knotens in einem Baum ist die Länge des längsten Weges
von diesem Knoten bis zu einem Blatt.
Als Höhe des Baumes ist die Höhe der Wurzel definiert.
Die Tiefe eines Knotens ist gegeben durch die Länge des Weges von der
Wurzel bis zu diesem Knoten.
Ein Baum heißt genau dann binär, wenn jeder Knoten höchstens zwei Nachfolgerknoten hat, wobei zusätzlich zwischen dem linken und dem rechten Sohn
eines Knotens (falls vorhanden) unterschieden wird. Damit können zwei voneinander verschiedene binäre Bäume denselben Graphen darstellen.
Binäre Bäume über einer Knotenmenge Kn können auch rekursiv definiert werden:
Rekursions–Anfang: Der leere Graph, wieder mit ε bezeichnet, sei ein binärer
Baum über Kn.
Rekursions–Schritt: Sind T 1 und T 2 binäre Bäume über Kn und ist K ∈ Kn,
so sei das Tripel (K, T 1, T 2) ein binärer Baum (mit der Wurzel K, dem linken
Teilbaum T 1 und dem rechten Teilbaum T 2).
Ein binärer Baum heißt genau dann gesättigt, wenn jeder Knoten des Baumes,
der kein Blatt ist, genau zwei Nachfolgerknoten besitzt.
Ein ungerichteter, zusammenhängender und zyklenfreier Graph wird dadurch
zu einem Baum, dass man einen beliebigen Knoten des Graphen als Wurzel
festlegt.
60
binäre Bäume (binary trees)
Außer als Syntaxbäume für Terme, die an Operationssymbolen höchstens ein–
bzw. zweistellige enthalten, kommen binäre Bäume beispielsweise auch als Suchbäume vor. Dabei ist ein Suchbaum ein binärer Baum mit Knotenbewertungen
aus einer geordneten Menge, wobei für jeden Knoten kn des Baumes gilt: falls
kn einen linken Sohn hat, so ist dessen Bewertung kleiner als die von kn; falls kn
einen rechten Sohn hat, so ist dessen Bewertung größer als die von kn. Nimmt
man M := {1, 2, 3, 4, 6, 7, 8, 9, 13, 14, 17, 20} als eine solche Menge mit der gewöhnlichen kleinergleich–Relation als Ordnung, so ist zum Beispiel der folgende
Binärbaum
8
17
4
6
2
1
3
20
13
9
7
14
ein Suchbaum mit Knotenbewertungen aus M. Dieser Baum ist sogar balanciert, weil für jeden Knoten kn dieses Baumes gilt: Die Höhen des linken und
des rechten Teilbaumes von kn unterscheiden sich höchstens um 1.
Die drei wichtigsten Reihenfolgen, in denen man sämtliche Knoten eines Binärbaumes systematisch durchlaufen kann, sind der inorder–, der präorder–
und der postorder–Durchlauf. Rekursiver inorder–Durchlauf eines binären
Baumes B mit Ausgabe der Knotenbewertungen bzw. Knoteninhalte:
inorder(B):
if (B =
6 ε) /* falls der Baum nicht leer ist*/
inorder(linker Teilbaum von B)
Ausgabe: Inhalt von Wurzel(B)
inorder(rechter Teilbaum von B)
end if;
Für den obigen Baum ergibt sich bei Anwendung dieses Algorithmus’ die Ausgabereihenfolge 1,2,3,4,6,7,8,9,13,14,17,20 für die Knoteninhalte.
(siehe auch die C–Programme zur Baumverarbeitung in cprog09.pdf)
61
Kellerspeicher
Ein Kellerspeicher (stack, LIFO–Speicher) K ist eine lineare Datenstruktur,
bei der ein Zugriff auf ihre Elemente immer nur am gleichen Ende (top– bzw.
oberstes Element) erfolgen kann. Diese lineare Datenstruktur kann mit Hilfe
eines Arrays oder einer einfach verketteten Liste realisiert werden.
Zu einem Kellerspeicher gehören immer auch die folgenden fünf Funktionen:
1. push;
durch push(K, x) wird ein (dann oberstes) Element x hinzugefügt
2. pop;
durch pop(K) wird das oberste Element aus dem Keller entnommen, falls
der Keller nicht leer ist; falls vorher mindestens zwei Elemente im Keller
waren, so wird nach Ausführen von pop(K) das ursprünglich zweitoberste
zum obersten Element
3. top;
durch top(K) kann das oberste Kellerelement angesehen werden, ohne den
Kellerinhalt zu verändern
4. empty;
empty ist eine nullstellige Funktion; durch empty() wird ein leerer Kellerspeicher erzeugt
5. isempty;
durch isempty(K) kann getestet werden, ob der Keller leer ist oder nicht
Kellerspeicher werden beispielsweise benötigt, um rekursive Programmaufrufe
möglich zu machen.
62
Abstrakte Datentypen (ADT)
ˆ grundlegend für objektorientierte Programmierung
ˆ im Gegensatz zu einem konkreten Datentyp wird bei einem ADT der Typ
der Elemente der Trägermenge(n) offengelassen bzw. hängt von Typparametern ab
ˆ zusätzlich zur Signatur werden Axiome angegeben, denen die Funktionen
genügen müssen (diese Axiome sind Forderungen an mögliche Implementierungen)
ˆ Implementierungen selbst spielen bei der Spezifizierung abstrakter Daten-
typen keine Rolle
Kurzformel:
ADT = (abstrakte) Datenmenge plus (darauf erklärten) Funktionen
Beispiel: ADT stack
uses:
types boolean, T {T: Typ der Kellerelemente, nicht weiter spezifiziert}
sorts:
S
functs:
empty : → S
isempty : S → boolean
top : S 7→ T
pop : S 7→ S
push : S × T → S
(7→: partielle Funktion)
vars:
σ:
{Menge der Stacks mit Elementen vom Typ T}
S,
τ:
T
axioms: isempty(empty) = true
isempty(push(σ, τ )) = f alse
top(push(σ, τ )) = τ
pop(push(σ, τ )) = σ
top(empty), pop(empty): nicht definiert bzw. Fehlermeldung
63
rekursive Funktionen
Eine Funktion f heißt rekursiv, wenn f bei der Funktionswertberechnung sich
selbst wieder (unmittelbar oder mittelbar) aufruft.
einfaches Beispiel: Fakultätsfunktion f : N → N mit f (n) := n!
rekursive Definition von f :


f (n) := 
1
, falls n = 0 oder n = 1
n ∗ f (n − 1) , falls n > 1
direkte Umsetzung in eine rekursive C–Funktion fakrek:
unsigned int fakrek(unsigned int n)
{
if (n <= 1)
return 1; /* Rek.–Anfang */
else
return n*fakrek(n-1); /* Rek.–Schritt */
}
iterative Version als eine C–Funktion fakit:
unsigned int fakit(unsigned int n)
{
unsigned int i, fak=1;
for (i=1; i<=n; i++)
fak = fak*i;
return fak;
}
64
weitere Beispiele rekursiver Definitionen von Funktionen
1. Fibonacci–Funktion f ib : N → N (Fibonacci bzw. Leonardo von Pisa,
1180-1250)
f ib(0) := 0; f ib(1) := 1;
f ib(n) := f ib(n − 1) + f ib(n − 2) (n ≥ 2)
(es ist beispielsweise f ib(100) = 354 224 848 179 261 915 075)
2. Addition add : N × N → N
add(n, 0) := n; add(n, ν(m)) := ν(add(n, m))
3. Multiplikation
mul(n, 0) := 0;
mul : N × N → N
mul(n, ν(m)) := add(mul(n, m), n)
4. Potenzierung pot : (N \ {0}) × N → N
pot(n, 0) := 1; pot(n, ν(m)) := mul(pot(n, m), n)
5. modulo–Funktion
mod : N × (N \ {0}) → N

 m,
falls m < n
mod(m, n) := 
mod(m − n, n), falls m ≥ n
6. größter gemeinsamer
Teiler ggt : (N \ {0}) × N → N



m,
falls n = 0 ∨ m = n


ggt(m, n) :=  ggt(m − n, n), falls m > n


 ggt(n − m, m), falls n > m
m
7. Binomialkoeffizient
n
binomial
:
N
×
N
→
N



1,


m
0, n := 
 
 m−1 + m−1 ,
n
n−1
bzw. binomial(m, n);
falls n = 0 ∨ n = m
falls m < n
sonst
8. Ackermann–Funktion ack : N × N → N (Wilhelm Ackermann, 18961962)



n + 1, falls m = 0


ack(m, n) :=  ack(m − 1, 1), falls m > 0 ∧ n = 0


 ack(m − 1, ack(m, n − 1)) sonst
Es ist beispielsweise
ack(1, n) = n + 2, ack(2, n) = 2 ∗ n + 3, ack(3, n) = 2n+3 − 3,
ack(4, n) = 2ack(4,n−1)+3 − 3, ack(4, 1) = 65533, ack(4, 2) > 1019726
Diese Funktion ist nicht mit Hilfe eines loop–Programmes (siehe Folie 110)
berechenbar.
65
rekursive Definitionen von
Pm
i=n ai
und von
Qm
i=n ai
Sind an , an+1, · · · , am beliebige Zahlen, so sei
i=n


ai := 
0,
falls n > m
Pm−1
( i=n ai ) + am , falls n ≤ m
m
Y


1,
falls n > m
Qm−1
( i=n ai ) ∗ am , falls n ≤ m
m
X
und
i=n
ai := 
Umsetzung in iterative Programme zur Berechnung von n–stelliger Summe und
von n–stelligem Produkt:
n, m, a n , . . . , am
sum := 0
i := n
while i <= m
sum := sum + ai
i := i +1
sum
n, m, a n , . . . , am
prod := 1
i := n
while i <= m
prod := prod * ai
i := i + 1
prod
66
Einsatz von Zufallszahlengeneratoren
ˆ Erzeugung von Schlüsseln für die Kodierung von Nachrichten
ˆ Programmierung von Spielen
ˆ Erzeugung zufälliger Eingabedaten für Testserien
ˆ approximative Berechnungen mit Hilfe von Monte–Carlo–Methoden
ˆ Simulation von Prozessen (z. B. radioaktiver Zerfall, Brownsche Bewegung,
Eintreten von Kunden in ein Geschäft, · · ·)
ˆ Treffen von Entscheidungen in nichtdeterministischen Programmen
ˆ Einsatz in randomisierten Algorithmen
ˆ zufällige Auswahl von Stichproben, wenn aus Ressource–Gründen nicht alle
Fälle betrachtet werden können
ˆ ···
Computererzeugte Zufallszahlenfolgen sind Ausgaben von speziellen Programmen, die deshalb auch Pseudozufallszahlen–Generatoren (pseudo random number generator, PRNG) heißen.
Einer der ersten PRNG’s geht auf John v. Neumann (1903–1957) zurück und
heißt Quadratmittenmethode (middle–square method). Man erzeugt damit iterativ Pseudozufallszahlen x1, x2, · · ·, indem ein Angangswert x0 quadriert
und ein Mittelstück davon als x1 genommen wird. Dann wird x1 quadriert und
ein Mittelstück davon als x2 verwendet usw., bis man genügend viele Zahlen
erzeugt hat.
Strenge Anforderungen werden an kryptographisch sichere PRNG’s gestellt.
67
lineare Kongruenz–Generatoren zur Erzeugung von Zufallszahlen
Oft sind Pseudozufallszahlen–Generatoren als lineare Kongruenz–Generatoren
realisiert:
Es werden 3 Konstanten a, b und m > max{a,b} festgelegt;
beginnend mit einem Anfangswert x0 (”seed”) wird dann folgendermaßen eine
Pseudozufallszahlenfolge
x0 , x1 , x2 , · · ·
berechnet:
xi+1 := (a ∗ xi + b) mod m , (i ≥ 0)
Da 0 ≤ xi < m gilt für alle i, treten nach maximal m Iterationen Wiederholungen auf, die Folge wird periodisch.
Es gilt (s. z.B. Forster, O.: Algorithmische Zahlentheorie. Vieweg–Verlag 1996;
Schroeder, M. R.: Number Theory in Science and Communication. Springer–
Verlag 2005):
Genau dann ist die Folge x0, x1, x2, · · · periodisch mit der maximal möglichen
Periodenlänge m, wenn die folgenden 3 Bedingungen erfüllt sind:
1. p|(a − 1) für jeden Primteiler p von m
2. 4|(a − 1), falls 4|m
3. ggt(b,m) = 1
√
√
Der Faktor a sollte im Intervall ( m, m − m) liegen, um ein ”zufälliges” Verhalten der erzeugten Folge zu erhalten.
In der Praxis wird oft ein Modul m als eine Zweierpotenz verwendet. Dann sind
die Bedingungen 1 bis 3 leicht zu realisieren:
a ≡ 1 mod 4 und b ungerade
(siehe auch die C–Folie zu Pseudozufallszahlen–Generatoren)
68
ein randomisierter Algorithmus
Für ungerade natürliche Zahlen n ≥ 3 gilt:
1. n ist genau dann eine Primzahl, wenn (a(n−1)/2 mod n) ∈ {1, n − 1} ist für
alle a ∈ {1, 2, · · · , n − 1}
2. falls zusätzlich (n − 1)/2 ungerade (d.h. n ≡ 3 mod 4) ist, so gilt:
wenn n keine Primzahl ist, so ist (a(n−1)/2 mod n) ∈
/ {1, n − 1} für mindestens die Hälfte aller a ∈ {1, 2, · · · , n − 1}
vereinfachter Solovay–Strassen–Algorithmus zum Test auf Primzahleigenschaft für große ungerade n ∈ N mit n ≡ 3 mod 4 (s. z.B. Hromkovič, J.:
Randomisierte Algorithmen. Teubner–Verlag 2004):
n
/* n nat. Zahl,
n
3 mod 4 */
a := (Zufallszahl aus {2, ... , n−1})
ja
ggt(a,n) > 1
nein
b := a (n−1)/2 mod n
ja
b=1 or b=n−1
nein
"n ist keine
Primzahl"
"n ist Primzahl"
"n ist keine
Primzahl"
Wenn ausgegeben wird, dass n keine Primzahl ist, so ist n garantiert keine
Primzahl, weil der Algorithmus einen Zeugen (witness) dafür gefunden hat;
wird dagegen ausgegeben, dass n eine Primzahl ist, so ist n mit mindestens der
Wahrscheinlichkeit 0.5 eine Primzahl.
Wird bei einer genügend großen Anzahl von Läufen mit stets zufälligen a ∈
{2, · · · , n − 1} immer wieder ausgegeben, dass n eine Primzahl ist, so wird die
Irrtumswahrscheinlichkeit für die Aussage, dass n eine Primzahl ist, beliebig
klein.
69
asymptotische Laufzeitabschätzung
ˆ gesucht ist eine obere Schranke für die Laufzeit T (n) eines Algorithmus,
der n Eingabedaten hat (z.B. ein Array mit n Elementen; n kann aber z.B.
auch für die Anzahl der Dualstellen eines einzigen Eingabedatums stehen)
ˆ die obere Schranke soll unabhängig sein vom konkreten Rechner, von der
Programmiersprache und vom Compiler; es soll auf einen konstanten Faktor für die Ausführungszeit einer einzelnen Anweisung nicht ankommen;
konkret soll es für jedes Programm eine positive konstante Zahl c geben,
so dass die Ausführungszeiten jeder elementaren arithmetischen Operation, jeder booleschen Operation, jeder Vergleichsoperation, jeder einfachen
Wertzuweisung variable := term und jedes Aufrufs einer Ein- oder Ausgabefunktion durch c nach oben beschränkt sind
ˆ ausschlaggebend für die Einordnung von T (n) soll der für immer größer
werdendes n dominante Teil von T (n) sein
Diese Vorgaben führen auf den Begriff der asymptotischen Laufzeitkomplexität, die mit Hilfe der O–Notation (gesprochen: groß–Oh bzw. big–Oh)
angegeben wird:
Ist f : N → N oder f : N → R+ und ist T (n) die Laufzeit eines Algorithmus,
so bedeute
T (n) ∈ O(f (n))
dass es eine natürliche Zahl n0 eine eine positive reelle Zahl c gibt, so dass für
alle k ∈ N mit k ≥ n0 gilt: T (k) ≤ c ∗ f (k).
formalisiert:
T (n) ∈ O(f (n))
↔
∃n0 ∃c(n0 ∈ N ∧ c ∈ R ∧ c > 0 ∧ ∀k(k ∈ N ∧ k ≥ n0 → T (k) ≤ c ∗ f (k)))
andere übliche Schreibweisen:
statt ”T (n) ∈ O(f (n))” findet man auch ’T (n) = O(f (n))” bzw.
’T (n) ist ein O(f (n))”.
Wenn für alle n, die gößer als ein n1 sind, stets f (n) ≤ g(n) ist, und wenn
T (n) ∈ O(f (n)) gilt, so ist natürlich erst recht T (n) ∈ O(g(n)). Um die asymptotische Laufzeitkomplexität also in hoher Qualität anzugeben, ist eine Funktion f in O(f (n)) gefragt, die möglichst kleine Funktionswerte hat bzw. möglichst
langsam wächst.
Zusätzlich sollte der f beschreibende Term von einfacher Gestalt sein.
70
wichtige Eigenschaften der O–Notation
Für Funktionen f, g, h : N → R+ und Konstanten a, a0 , · · · , ak gelten die folgenden Beziehungen:
ˆ ∃c(c > 0 ∧ ∀j(j ∈ N → f (j) ≤ c))
→
f (n) ∈ O(1)
ˆ ak ∗ nk + ak−1 ∗ nk−1 + · · · + a0 ∈ O(nk )
ˆ a ∗ f (n) ∈ O(f (n))
ˆ f (n) ∈ O(g(n)) ∧ g(n) ∈ O(h(n))
→
f (n) ∈ O(h(n))
ˆ f (n) + g(n) ∈ O(max{f (n), g(n)})
ˆ f (n) ∗ g(n) ∈ O(f (n) ∗ g(n))
Für Funktionen f, g : N → R+ bedeute
f ≺g
(”f wächst asymptotisch langsamer als g”), dass
lim
n→∞
f (n)
=0
g(n)
ist.
Dann gilt für beliebige Konstanten ε, c mit 0 < ε < 1 < c und den Logarithmus
log zu irgendeiner Basis b > 1:
1 ≺ log log n ≺ log n ≺ nε ≺ n ≺ n ∗ log n ≺ nc ≺ nlog n ≺ cn ≺ n! ≺ nn ≺ c(c
n
)
Ist beispielsweise T (n) ∈ O(nc ) bzw. T (n) ∈ O(cn ), so spricht man von polynomieller bzw. exponentieller Laufzeitkomplexität.
Das Wachstumsverhalten einiger ausgewählter Funktionen zeigt, dass Algorithmen mit exponentieller Laufzeitkomplexität schon für relativ kleine n eine nicht
mehr praktikable Laufzeit haben:
n
ln(n)
√
n
n
n*ln(n)
n2
n3
2n
n!
nn
1
5
10
20
50
100
0 1.6· · · 2.3· · ·
2.9· · ·
3.9· · ·
4.6· · ·
1 2.2· · · 3.1· · ·
4.4· · ·
7.0· · ·
10
1
5
10
20
50
100
0 8.0· · · 23.0· · ·
59.9· · ·
195.6· · ·
460.5· · ·
1
25
100
400
2500
10000
1 125
1000
8000
125000
1000000
2
32
1024
1048576
1.126e15
1.267e30
1 120 3628800 2.43· · ·e18 3.04· · ·e64 9.33· · ·e157
1 3125
1e10
1.04· · ·e26 8.88· · ·e84
1e200
71
typische asymptotische Laufzeiten
ˆ O(1) (konstante Laufzeit)
Die Auswertung eines arithmetischen oder booleschen Termes, der nur elementare Operationssymbole und keine Funktionsaufrufe enthält, ist in konstanter asymptotischer Laufzeit möglich. Gleiches gilt für die Laufzeit eines
Programmes ohne Schleifen und ohne weitere Funktionsaufrufe. (Das Adjektiv ”asymptotisch” ist hier ohne Bedeutung.)
ˆ O(log n) (logarithmische Laufzeit bzw. Komplexität)
Hat ein Programm mit n Eingabedaten (bzw. mit n als Eingabedatum)
diese Laufzeit, so verdoppelt sich diese erst bei n2 Eingabewerten (bzw. n
als Eingabedatum). Dies ist ein günstiges Laufzeitverhalten.
Beispiele: binäre Suche in einem sortierten Array der Länge n; schnelle
Berechnung von xn mittels square and multiply nach Folie 30.
ˆ O(n) (lineare Komplexität):
Günstige Laufzeit, beispielsweise bei der Suche in einem unsortierten Array oder einer Liste der Länge n, bei der Berechnung von xn nach der
”gewöhnlichen” Methode (unteres Struktogramm von Folie 30) oder bei
der Summen– bzw. Produktberechnung von n Werten nach Folie 66.
ˆ O(n ∗ log n):
Auch noch günstige Laufzeit, beispielsweise haben schnellste Sortieralgorithmen zum Sortieren von n Werten diese Laufzeitkomplexität.
ˆ O(n2 ) (quadratische Komplexität):
Nicht mehr so günstig, denn eine Verdopplung des Wertes von n bewirkt
eine Vervierfachung der Laufzeit. Einfache Sortieralgorithmen (siehe die
Folien zur C–Programmierung) und die Multiplikation einer (n×n)–Matrix
mit einem Vektor der Länge n haben eine solche Laufzeit.
ˆ O(n3 ) (kubische Komplexität):
Tritt beispielsweise bei der Multiplikation zweier (n × n)–Matrizen nach
der ”gewöhnlichen” Methode auf.
ˆ O(2n ) (exponentielle Komplexität): Katastrophales Laufzeitverhalten, denn
eine Verdopplung des Wertes von n zieht ein Quadrieren der Laufzeit nach
sich.
Probleme, für deren Lösung nur Algorithmen mit exponentieller oder höherer Laufzeit bekannt sind, heißen auch schwer handhabbare Probleme
(intractable problems), siehe nächste Folie.
72
Beispiele für schwer handhabbare bzw. lösbare Probleme
1. Existenz eines Hamilton–Kreises (Hamiltonian circuit problem)
Ein Hamilton–Kreis in einem ungerichteten Graphen mit n Knoten ist ein
n–Tupel (k1, · · · , kn ) aller Knoten des Graphen derart, dass alle Zweiermengen {ki , ki+1} mit 1 ≤ i < n und {kn , k1} Kanten des Graphen sind.
Es gibt also eine Rundreise in dem Graphen, bei der jeder Knoten genau
einmal besucht wird (und Anfangs– gleich Endknoten ist).
Wie kann man feststellen, ob der Graph einen Hamilton–Kreis besitzt (und
dann einen solchen bestimmen) oder nicht ?
2. Problem des Handlungsreisenden (travelling salesman problem;
auch: Rundreiseproblem)
Ein Vertreter muss n Städte besuchen, deren Entfernungen untereinander bekannt sind. Er besucht jede nur einmal und kehrt am Schluss zum
Ausgangsort zurück. In welcher Reihenfolge muss er die Städte besuchen,
damit der gesamte von ihm zurückgelegte Weg minimal ist?
3. Erfüllbarkeit Boolescher Terme (SAT; satisfiability of Boolean
expressions)
Es sei B ein beliebiger Boolescher Term in den Variablen x1 , · · · , xn. Ist B
erfüllbar?
4. Rucksackproblem (knapsack problem)
Es seien n Gegenstände mit unterschiedlichen Werten und Gewichten gegeben. Ein Rucksack soll damit derart gefüllt werden, dass ein zulässiges
Gesamtgewicht nicht überschritten wird und gleichzeitig der Gesamtwert
der Gegenstände im Rucksack möglichst groß ist. Wie ist der Rucksack zu
füllen?
5. Zerlegungsproblem (partitioning problem)
Gegeben sei ein n–Tupel (a1 , · · · , an ) natürlicher Zahlen. Gibt es dann eine
Zerlegung der Menge M := {1, · · · , n} in zwei Teilmengen M1 und M2 , so
dass gilt
P
P
?
=
i∈M2 ai
i∈M1 ai
Für alle diese Probleme sind bis heute keine Lösungsalgorithmen mit geringerer
als exponentieller Laufzeit bekannt. Algorithmen mit höherer als polynomieller
Laufzeit werden auch als ineffiziente Algorithmen bezeichnet.
73
Halteproblem
Gesucht ist ein Algorithmus Alg, der, angewandt auf ein beliebiges Programm
P und eine beliebige zugelassene Eingabe E für P , stets entscheidet, ob P bei
dieser Eingabe terminiert oder nicht.
P
E
Alg
ja
nein
Zugelassene Eingabe für P : Enthält P an Variablen beispielsweise genau x1 , · · · , xn
als Variablen für natürliche Zahlen, so sei genau jedes n-Tupel i1, · · · , in natürlicher Zahlen eine zugelassene Eingabe für P (xj wird mit ij initialisiert).
(Anstelle von ”Programm”hätte auch ”Turing–Maschine”oder ”while–Programm”
(s. u.) oder auch ”partiell–rekursive zahlentheoretische Funktion”notiert werden
können. Eine zugelassene Eingabe für die Turing–Maschine wäre eine beliebige
anfängliche Bandbeschriftung, wobei nur endlich viele Zellen beschriftet sein
dürfen.)
Äquivalenzproblem für Programme
Gesucht ist ein Algorithmus Alg, der, angewandt auf ein beliebiges Paar (P1 , P2 )
von Programmen P1 und P2 , stets entscheidet, ob P1 und P2 äquivalent sind
oder nicht.
Dabei heißen zwei Programme genau dann äquivalent, wenn beide Programme
bei gleichen Eingaben sich stets gleich verhalten: Entweder beide terminieren
und liefern die gleichen Resultate oder beide terminieren nicht.
Sowohl das Halteproblem als auch das Äquivalenzproblem sind nicht lösbar, d.
h., es gibt keine obigen Algorithmen Alg.
74
POSTsches Korrespondenzproblem
Emil Leon Post (1897 - 1954)
ˆ gegeben:
ein beliebiges Alphabet A und eine beliebige endliche Folge
((v1, w1), · · · , (vk , wk )) von Wortpaaren (vi, wi) mit vi, wi ∈ A+ für alle i
mit 1 ≤ i ≤ k
ˆ gesucht:
eine Folge (i1, i2 , · · · , in ) von Indizes mit n ≥ 1, 1 ≤ i1 , · · · , in ≤ k, so dass
gilt
v i1 ◦ v i2 ◦ · · · ◦ v in = wi1 ◦ wi2 ◦ · · · ◦ win
Eine solche Folge (i1, i2, · · · , in ), falls sie existiert, heißt eine Lösung des Korrespondenzproblems ((v1, w1), · · · , (vk , wk )).
Beispiel:
A := {0, 1}, KP := ((1, 101), (10, 00), (011, 11))
Dann besitzt das Korrespondenzproblem KP beispielsweise die Lösung (1, 3, 2, 3).
Zehntes HILBERTsches Problem
David Hilbert (1862 - 1943)
Gesucht ist ein Algorithmus, der, angewandt auf eine beliebige diophantische
Gleichung, aussagt, ob diese lösbar ist oder nicht.
Y. V. Matijasevic̆ zeigte 1970, dass es keinen solchen Algorithmus gibt.
diophantische Gleichung:
P (x1, · · · , xn) = 0
wobei P (x1 , · · · , xn) ein Polynom mit ganzzahligen Koeffizienten in den Variablen x1, · · · , xn ist. Als Lösungen sind nur n–Tupel ganzer Zahlen zugelassen.
Beispiel:
Die diophantische Gleichung
x31 + 2x1x2 − x23 + x2 − 4 = 0
ist lösbar, denn beispielsweise (1,1,0) ist eine Lösung.
Auch diese beiden Probleme sind nicht algorithmisch lösbar.
75
Gödelisierung
Kurt Gödel (1906 - 1978)
Den Zeichen eines Alphabetes A := {a1, · · · , an } sowie den nichtleeren Zeichenketten und den endlichen Folgen von Zeichenketten über diesem Alphabet
werden effektiv und eineindeutig natürliche Zahlen, ihre Gödel–Nummern,
zugeordnet.
ˆ G(a1 ) := 1, G(a2 ) := 3, · · · , G(an ) := 2 ∗ n − 1
ˆ w := ai1 · · · aik ∈ A+ ; dann sei
G(ai1 )
G(w) := p1
G(ai2 )
∗ p2
G(aik )
∗ · · · ∗ pk
wobei pi die i–te Primzahl sei
ˆ W := (w(1) , · · · , w(r) ) ∈ (A+ )r ; dann sei
G(w(1) )
G(W ) := p1
G(w(2) )
∗ p2
∗ · · · ∗ pG(w
r
(r)
)
Dabei sind p1, p2, · · · mit p1 := 2, p2 := 3, p3 := 5, · · · die ersten Primzahlen mit
pi < pi+1 für alle i ≥ 1.
Von jeder natürlichen Zahl ist effektiv entscheidbar, ob sie die Gödel–Nummer
eines Zeichens, einer Zeichenkette oder einer Folge von Zeichenketten über A
ist oder nicht. Hierbei spielt der Satz von der eindeutigen Primfaktorzerlegung
(siehe Folie 16) eine tragende Rolle.
Falls eine natürliche Zahl eine Gödel–Nummer ist, so kann ihr Urbild bzgl. G
effektiv bestimmt werden.
76
generelle Fragen, die zusammen mit einem Problemlösungsprozess
auftreten
Nach der Formulierung eines Problems stellen sich folgende Fragen bzw. müssen
folgende weitere Probleme bearbeitet werden:
ˆ Ist das Problem überhaupt lösbar?
ˆ Wenn es lösbar ist, gibt es genau eine oder gibt es mehrere Lösungen?
ˆ Wenn es eine Lösung gibt, ist diese oder sind alle Lösungen dann algorith-
misch berechenbar? (Es gibt auch reine Existenzsätze!)
ˆ Wenn es eine algorithmisch berechenbare Lösung gibt, wie groß ist dann
der Mindestaufwand, eine oder auch alle Lösungen zu berechnen?
ˆ Wenn das Problem algorithmisch lösbar ist, so finde einen möglichst laufzeit–
(und/oder speicherplatz–) optimalen Algorithmus zur Bestimmung einer
oder einiger oder aller Lösungen!
ˆ Wenn möglich, so beweise die Korrektheit des Algorithmus oder zumindest
von ausschlaggebenden Teilen davon!
ˆ Welche Programmiersprache ist geeignet zur Implementierung des Algo-
rithmus?
ˆ Welche Auswirkungen haben die begrenzten Ressourcen, z. B. Darstellun-
gen von Daten in festen Formaten (→ Rundungsfehler, under– und overflow) sowie Beschränktheit der Speicherkapazität und der Rechenzeit auf
die Genauigkeit der Ergebnisse und die Praktikabilität des Algorithmus?
77
Aussagen
Aussagen sind sprachliche Gebilde, für die es sinnvoll ist zu fragen, ob sie wahr
oder falsch sind. Sie können in einer natürlichen oder künstlichen Sprache formuliert sein.
Eine wahre Aussage hat den Wahrheitswert wahr (auch: W bzw. true bzw. T
bzw. 1), eine falsche Aussage den Wahrheitswert f alsch (auch: F bzw. f alse
bzw. 0).
Beispiele:
ˆ ”Die Zahl 5 ist eine Primzahl.” (W )
ˆ ”Der November hat 31 Tage.” (F )
√
ˆ ” 2 ist eine rationale Zahl.” (F )
ˆ ”Es gibt unendlich viele Primzahen.” (W )
ˆ ”Es gibt unendlich viele Primzahlzwillinge.” (?)
ˆ ”Jede gerade natürliche Zahl, die größer oder gleich 4 ist, lässt sich als
Summe zweier Primzahlen darstellen.” (?)
(Goldbachsche Vermutung von 1742)
ˆ ”Es gibt unendlich viele pythagoreische Tripel (a, b, c).” (W )
ˆ ”Für jede natürliche Zahl n ≥ 3 und beliebige natürliche Zahlen a, b, c
ungleich Null ist stets an + bn 6= cn .” (W )
(Großer Satz von Fermat, Pierre de Fermat 1601–1655;
der Satz konnte erst 1993 bewiesen werden, und zwar von Andrew Wiles)
78
klassische (zweiwertige) Aussagenlogik
Die klassische Aussagenlogik gründet sich auf den beiden folgenden Prinzipien:
ˆ Prinzip vom ausgeschlossenen Dritten:
Jede Aussage ist nichts als wahr oder falsch.
ˆ Prinzip vom ausgeschlossenen Widerspruch:
Es gibt keine Aussage, die sowohl wahr als auch falsch ist.
Verknüpfungen von Aussagen:
Aussagen können negiert und mit Hilfe von ”und”, ”oder”, ”wenn · · · dann
· · ·”, ”· · · genau dann, wenn · · ·”, ”entweder · · · oder · · ·”, ”weder · · · noch
· · ·” und weiteren Verknüpfungen zu zusammengesetzten Aussagen verbunden
werden.
elementare bzw. atomare Aussagen: Das sind Aussagen, die nicht auf die
eben genannte Art aus einfacheren Aussagen zusammengesetzt sind. (Beispiele
dazu: s. vorhergehende Folie)
ˆ Prinzip der Extensionalität:
Der Wahrheitswert einer zusammengesetzten Aussage hängt nur ab von
den Wahrheitswerten der darin vorkommenden atomaren Aussagen und
der Art ihrer Verknüpfung.
Es spielt also keine Rolle, ob irgendwelche inhaltlichen Zusammenhänge
zwischen den Teilaussagen bestehen oder nicht.
79
Formalisierung zusammengesetzter Aussagen
Es seien p bzw. q die beiden folgenden Aussagen:
p:
2 ist ein Teiler von 3.
q:
13 ist eine Primzahl.
Dann sind ¬p, p ∧ q, p ∨ q, p → q bzw. p ↔ q Formalisierungen der folgenden
Aussagen:
ˆ ¬p:
Es ist nicht so, dass 2 ein Teiler von 3 ist.
(Auch: 2 ist nicht Teiler von 3.) (W )
ˆ p ∧ q:
2 ist ein Teiler von 3, und 13 ist eine Primzahl. (F )
ˆ p ∨ q:
2 ist ein Teiler von 3, oder 13 ist eine Primzahl. (W )
ˆ p → q:
Wenn 2 ein Teiler von 3 ist, so ist 13 eine Primzahl. (W )
ˆ p ↔ q:
2 ist genau dann ein Teiler von 3, wenn 13 eine Primzahl ist. (F )
Sei ferner
r:
6 ist eine vollkommene Zahl.
Dann entsprechen sich die folgenden Zeichenketten und verbal formulierten Aussagen:
ˆ p → (¬q ∧ ¬r):
Wenn 2 ein Teiler von 3 ist, so ist weder 13 eine Primzahl noch 6 eine
vollkommene Zahl. (W )
ˆ ¬p ∧ ¬q ∧ ¬r:
Es ist weder 2 ein Teiler von 3 noch ist 13 eine Primzahl noch ist 6 eine
vollkommene Zahl. (F )
80
BOOLEsche Terme (aussagenlogische Ausdrücke)
(George Boole, 1815 - 1864)
Es seien p, q, r, p1, p2, · · · Variablen, die nur die Werte true bzw. f alse (oder: 1
bzw. 0) annehmen können.
Mit Hilfe dieser Aussagen–Variablen und der Wahrheitswerte können auf
folgende Weise die booleschen Terme definiert werden:
(a) Rekursions–Anfang
Die Variablen p, q, r, p1, p2, · · · sowie die Konstanten true und f alse seien
boolesche Terme.
(b) Rekursions–Schritt
Falls A und B boolesche Terme sind, so seien auch
¬A, (A ∧ B), (A ∨ B), (A −→ B) und (A ←→ B)
boolesche Terme.
(c) Minimalbedingung
Nur aufgrund von (a) und (b) sollen boolesche Terme erhalten werden
können.
Damit können boolesche Terme als spezielle Zeichenketten über dem Alphabet
A := {true, f alse, p, q, r, |, ¬, ∧, ∨, →, ↔, (, )} aufgefasst werden (ersetze ”p1”
durch ”p|”, ”p2” durch ”p||”, usw.).
Klammereinsparungsregeln:
Ein äußeres Klammernpaar darf weggelassen werden. Weiterhin soll jedes der
Symbole ”¬”, ”∧”,”∨”,”→” und ”↔” stärker binden als alle in dieser Reihenfolge
rechts neben ihm stehenden.
Bemerkung:
Man kann die booleschen Terme auch zunächst ohne ”−→” und ohne ”←→”
einführen und dann definieren (s. auch die Folie 84 zu den semantischen Äquivalenzen):
”A −→ B” stehe für ”¬A ∨ B”
”A ←→ B” stehe für ”(A −→ B) ∧ (B −→ A)” bzw. für ”(¬A ∨ B) ∧ (¬B ∨ A)”
81
eine EBNF–Grammatik zur Erzeugung der Booleschen Terme
Die rekursive Definition boolescher Terme kann auch auf folgende Weise mit
Hilfe einer EBNF–Grammatik erfolgen:
T := {false, true, p, q, r, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ¬, ∧, ∨, →, ↔, (, ) }
N := {bool term , variable , konstante , ziffer}
S := bool term
<konstante> ::= false | true
<variable> ::= p{<ziffer>} | q | r
<ziffer> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<bool term> ::= <konstante> | <variable> | ¬ <bool term> |
(<bool term> ∧ <bool term>) |
(<bool term> ∨ <bool term>) |
(<bool term> → <bool term>) |
(<bool term> ↔ <bool term>)
Die booleschen Terme lassen sich natürlich auch leicht mit Hilfe eines Syntaxdiagrammes erzeugen.
82
Semantik boolescher Terme
Es sei f: {p, q, r, p1 , p2 , · · · } −→ {false, true}. (Die Funktion f heißt dann eine
Belegung der Aussagenvariablen mit Wahrheitswerten.)
Dann sei der Wahrheitswert Ww(C,f) eines Booleschen Termes C bei der
Belegung f wie folgt definiert:
ˆ Rekursions–Anfang (C ist eine Konstante oder Variable)
Ww(true,f) := true, Ww(false,f) := false
Ww(p,f) := f(p), Ww(q,f) := f(q), Ww(r,f) := f(r),
Ww(p1,f) := f(p1), · · ·
ˆ Rekursions–Schritt (C ist ein zusammengesetzter Term)
Ww(¬A,f)


true , falls Ww(A,f)=false
false sonst


true , falls Ww(A,f)=Ww(B,f)=true
false sonst


false , falls Ww(A,f)=Ww(B,f)=false
true sonst
:= 
Ww((A ∧ B),f) := 
Ww((A ∨ B),f) := 





Ww((A → B),f) := 





Ww((A ↔ B),f) := 
false , falls Ww(A,f)=true
und Ww(B,f)=false
true sonst
true , falls Ww(A,f)=Ww(B,f)
false sonst
(s. auch die entsprechende Folie von cprog09.pdf)
83
semantische Äquivalenz und Folgerungsbegriff für boolesche Terme
Es seien A und B boolesche Terme.
ˆ A und B heißen semantisch äquivalent (in Zeichen: A ≡ B oder A ⇔ B)
genau dann, wenn
Ww(A,f) = Ww(B,f) ist für jede Belegung f der Aussagenvariablen mit
Wahrheitswerten
ˆ B folgt aus A (in Zeichen: A |= B oder A ⇒ B) genau dann, wenn gilt:
für jede Belegung f, für die Ww(A,f) = true ist, ist auch Ww(B,f) = true
Dass B aus A folgt, kann äquivalent zu obiger Definition auch auf jede der
beiden folgenden Weisen definiert werden:
ˆ für jede Belegung f, für die Ww(B,f) = false ist, ist auch Ww(A,f) = false
ˆ es gibt keine Belegung f mit Ww(A,f) = true und Ww(B,f) = false
Beispiele:
A ∨ ¬A ≡ true, A ∧ ¬A ≡ f alse
A ∨ A ≡ A, A ∨ true ≡ true, A ∨ f alse ≡ A
A ∧ A ≡ A, A ∧ true ≡ A, A ∧ f alse ≡ f alse
A → B ≡ ¬A ∨ B, A → B ≡ ¬B → ¬A
A ↔ B ≡ (¬A ∨ B) ∧ (A ∨ ¬B)
A ⊕ B ≡ (A ∨ B) ∧ ¬(A ∧ B) (exklusives oder bzw. xor)
A ∨ (A ∧ B) ≡ A, A ∧ (A ∨ B) ≡ A
A ∨ (Ā ∧ B) ≡ A ∨ B, A ∧ (Ā ∨ B) ≡ A ∧ B
A ∧ (A → B) ⇒ B
Man kann auch durch jede der beiden folgenden Redeweisen ausdrücken, dass
B aus A folgt:
ˆ A ist hinreichend für B
ˆ B ist notwendig für A
84
Ersetzbarkeitstheorem
Es seien A, B, C drei boolesche Terme mit B ≡ C. Dann gilt: Kommt an
irgendeiner Stelle in A der Term B als Teilzeichenkette vor und wird dieses
Vorkommen von B durch den Term C ersetzt, so ist die dabei aus A entstehende
Zeichenkette A′ wieder ein boolescher Term, und außerdem ist A ≡ A′ .
Verallgemeinerung des Folgerungsbegriffs auf mehrere Prämissen
A1 , · · · , An
ˆ B folgt aus A1 , · · · , An (in Zeichen: A1 , · · · , An |= B oder A1 , · · · , An ⇒ B)
genau dann, wenn gilt:
für jede Belegung f, für die Ww(A1,f) = · · · = Ww(An,f) = true ist, ist
auch Ww(B,f) = true
Weitere grundlegende Begriffe für boolesche Terme
ˆ A heißt eine Tautologie genau dann, wenn
Ww(A,f) = true ist für jede Belegung f
ˆ A heißt eine Kontradiktion genau dann, wenn
Ww(A,f) = false ist für jede Belegung f
ˆ A heißt erfüllbar genau dann, wenn
Ww(A,f) = true ist für wenigstens eine Belegung f
Es gilt:
Genau dann, wenn A ≡ B ist, ist A ↔ B eine Tautologie;
genau dann, wenn A1, · · · , An ⇒ B ist, ist A1 ∧ · · · ∧ An → B eine Tautologie;
genau dann, wenn A1, · · · , An ⇒ B ist, ist A1 ∧· · ·∧An ∧¬B eine Kontradiktion
85
Gesetze einer BOOLEschen Algebra
(B, 0, 1, ¯, ∧, ∨)
(z.B. B = {true, false}, 0=false, 1=true,¯= ¬)
Es ist 0, 1 ∈ B mit 0 6= 1,
und für alle x, y, z ∈ B gilt:
¯: B −→ B,
∧, ∨ : B × B −→ B,
1. x ∧ y ≡ y ∧ x , x ∨ y ≡ y ∨ x
(Kommutativgesetze)
2. x ∧ (y ∧ z) ≡ (x ∧ y) ∧ z
(Assoziativgesetze)
,
x ∨ (y ∨ z) ≡ (x ∨ y) ∨ z
3. x ∧ (x ∨ y) ≡ x , x ∨ (x ∧ y) ≡ x
(Absorptions– bzw. Verschmelzungsgesetze)
4. x ∧ (y ∨ z) ≡ (x ∧ y) ∨ (x ∧ z)
x ∨ (y ∧ z) ≡ (x ∨ y) ∧ (x ∨ z)
(Distributivgesetze)
5. x ∧ 0 ≡ 0 , x ∧ 1 ≡ x
(Existenz von Null– und Einselement (neutrale Elemente))
6. x ∧ x̄ ≡ 0 , x ∨ x̄ ≡ 1
(Existenz des Komplements)
In einer Booleschen Algebra gilt weiterhin für alle x, y ∈ B:
ˆ x∨0≡x
,
x∨1≡1
ˆ x ∧ y ≡ x̄ ∨ ȳ
, x ∨ y ≡ x̄ ∧ ȳ
(De MORGANsche Gesetze)
ˆ x∧x≡x
, x∨x≡x
(Idempotenz)
¯≡x
ˆ x̄
(Doppelkomplement– bzw. Doppelnegationsgesetz)
ˆ 0̄ ≡ 1
, 1̄ ≡ 0
(Komplementarität der neutralen Elemente)
ˆ gilt T1 ≡ T2 für zwei Terme einer Booleschen Algebra und ersetzt man in
T1 und in T2 simultan alle Vorkommen von ”∨” durch ”∧”, von ”∧” durch
”∨”, von ”0” durch ”1” und von ”1” durch ”0”, so erhält man wieder eine
Äquivalenz.
(Dualitätsprinzip der Booleschen Algebra)
86
Verifikation eines Programmes zur Bestimmung von
q := n div m und von r := n mod m
für nat. Zahlen n, m mit m 6= 0
Zugrunde liegt der Satz von der Division mit Rest (siehe auch Folie 16):
Zu zwei beliebig vorgegebenen natürlichen Zahlen n, m mit m 6= 0 gibt es genau
zwei natürliche Zahlen q und r, für die gilt:
n = m ∗ q + r und 0 ≤ r < m
Bezeichnung für diese Zahlen:
q = n div m (ganzer Teil des Quotienten bei der Division von n durch m);
r = n mod m (Rest bei der Division von n durch m)
Pseudocode zur Bestimmung von q und r:
Eingabe: m, n ∈ N mit m 6= 0
/* Vorbedingung: n, m ∈ N ∧ 0 < m */
r = n; q = 0;
/* Schleifeninvariante: 0 ≤ r ∧ 0 < m ∧ n = m ∗ q + r */
while (r >= m)
{
r = r − m; q = q + 1;
}
/* Nachbedingung: 0 ≤ r ∧ 0 < m ∧ r < m ∧ n = m ∗ q + r */
Ausgabe: q, r
87
Schleifeninvariante (loop invariant)
logischer Ausdruck, der unmittelbar vor Eintritt in die Schleife wahr ist und
dessen Wahrheitswert sich bei einem Schleifendurchlauf nicht ändert (falls die
Schleifenbedingung erfüllt war); dass dieser Ausdruck immer dann wahr ist, ist
induktiv zu beweisen, wobei der Parameter, nach dem der Induktions–Beweis
durchgeführt wird, unterschiedliche Bedeutungen haben kann:
ˆ er kann angeben, das wievielte Mal der Test der Schleifenbedingung erreicht
wurde
ˆ er kann die Laufvariable einer for–Schleife sein
ˆ er kann den Wert eines arithmetischen Terms, der von den Werten der
Variablen des Programms abhängt und bei jedem Schleifendurchlauf um 1
wächst, haben
Falls dann die Schleife terminiert, so gelten unmittelbar nach Verlassen
der Schleife sowohl die Schleifeninvariante als auch die Negation der Schleifenbedingung, woraus sich durch semantisch äquivalentes Umformen oder durch
Folgern Eigenschaften des betrachteten Algorithmus beweisen lassen.
88
Struktur indirekter Beweise
Es soll indirekt gezeigt werden, dass B aus A1, · · · , An folgt. Dazu kann jede
der drei folgenden semantischen Äquivalenzen benutzt werden:
1. A1 ∧ · · · ∧ An → B
≡
A1 ∧ · · · ∧ An ∧ ¬B → ¬Ai
2. A1 ∧ · · · ∧ An → B
≡
A1 ∧ · · · ∧ An ∧ ¬B → B
3. A1 ∧ · · · ∧ An → B
≡
A1 ∧ · · · ∧ An ∧ ¬B → F
(1 ≤ i ≤ n)
Es kann also die Negation ¬B von B mit zu den Prämissen hinzugenommen
werden, und wenn es dann gelingt, zu zeigen, dass einer der folgenden Ausdrücke
1. ¬Ai
(1 ≤ i ≤ n)
2. B
3. F
bzw.
C ∧ ¬C
für einen Ausdruck C
aus diesen um ¬B erweiterten Prämissen folgt, so hat man gezeigt, dass B aus
A1 , · · · , An folgt.
Im ersten Fall hätte man einen Widerspruch zu einer Voraussetzung Ai ,
im zweiten Fall einen Widerspruch zur Annahme B und im dritten Fall
einen logischen Widerspruch erhalten.
Spezialfälle:
1. A1 → B ≡ A1 ∧ ¬B → ¬A1
A1 → B ≡ ¬B → ¬A1 (n = 1)
Man hat demnach indirekt gezeigt, dass B aus A1 folgt, wenn man gezeigt
hat, dass ¬A1 aus A1 und ¬B folgt oder dass ¬A1 aus ¬B folgt.
2. T → B ≡ ¬B → B bzw.
B ≡ ¬B → B
(n = 1 und A1 = T )
Man hat also indirekt gezeigt, dass B zutrifft, wenn man gezeigt hat, dass
B aus ¬B folgt.
3. T → B ≡ ¬B → F bzw.
B ≡ ¬B → F
(n = 1 und A1 = T )
Man hat also indirekt gezeigt, dass B zutrifft, wenn man gezeigt hat, dass
aus ¬B ein logischer Widerspruch folgt.
Eine weitere Möglichkeit, indirekt zu zeigen, dass B zutrifft, erhält man daraus,
dass
A ∧ (¬B → ¬A) → B
eine Tautologie ist. Man hat demnach gezeigt, dass B zutrifft, wenn man gezeigt
hat, dass A zutrifft und dass ¬A aus ¬B folgt.
89
prädikatenlogische Terme
zu den aussagenlogischen Symbolen kommen die folgenden hinzu:
ˆ (Individuen–)Konstanten:
ˆ (Individuen–)Variablen:
ˆ Prädikatensymbole:
ˆ Funktionssymbole:
a1 , a2 , · · ·
x1 , x2 , · · ·
Pik mit i, k = 1, 2, · · ·
ϕki mit i, k = 1, 2, · · ·
i: Unterscheidungsindex; k: Stelligkeit
Dann können auf folgende Weise die prädikatenlogischen Terme definiert werden:
(a) Rekursions–Anfang
Jede Konstante und jede Variable sei ein Term.
(b) Rekursions–Schritt
Falls ϕ ein k–stelliges Funktionssymbol ist und t1 , · · · , tk prädikatenlogische
Terme sind, so sei auch ϕ(t1, · · · , tk ) ein prädikatenlogischer Term
(c) Minimalbedingung
Nur aufgrund von (a) und (b) sollen prädikatenlogische Terme erhalten
werden können.
(Manchmal werden in der Literatur nullstellige Funktionssymbole anstelle der
Konstanten verwendet.)
90
prädikatenlogische Ausdrücke
Mit Hilfe der prädikatenlogischen Terme können auf folgende Weise die prädikatenlogischen Ausdrücke definiert werden:
(a) Rekursions–Anfang
Falls P ein k–stelliges Prädikatensymbol ist und t1 , · · · , tk prädikatenlogische Terme sind, so sei
P (t1 , · · · , tk )
ein prädikatenlogischer Ausdruck.
(Diese prädikatenlogischen Ausdrücke heißen auch atomare prädikatenlogische Ausdrücke.)
(b) Rekursions–Schritt
Falls A und B prädikatenlogische Ausdrücke sind, so seien auch
¬A, (A ∧ B), (A ∨ B), (A −→ B) und (A ←→ B)
prädikatenlogische Ausdrücke;
falls x eine Variable ist und A ein prädikatenlogischer Ausdruck, so seien
auch
∀xA und ∃xA
prädikatenlogische Ausdrücke.
(c) Minimalbedingung
Nur aufgrund von (a) und (b) sollen prädikatenlogische Ausdrücke erhalten
werden können.
Jedes Vorkommen einer Variablen in einem prädikatenlogischen Ausdruck ist
entweder ein freies oder ein gebundenes:
Ein Vorkommen von x in A heißt genau dann gebundenes Vorkommen, wenn
dieses x in einem Teilausdruck von A der Gestalt ∀xB oder ∃xB vorkommt;
sonst heiße ein Vorkommen von x freies Vorkommen
Ein prädikatenlogischer Ausdruck ohne freie Vorkommen von Variablen heißt
auch geschlossener Ausdruck bzw. Aussage.
91
Semantik der Prädikatenlogik
1. Termwertbestimmung
Um den Termen und Ausdrücken eine Bedeutung zuordnen zu können, benötigt
man zunächst eine nichtleere Menge IB (den Individuenbereich) sowie eine
Funktion F mit
Db(F ) := {ai |i ≥ 1} ∪ {Pik |i, k ≥ 1} ∪ {ϕki |i, k ≥ 1},
so dass gilt:
ˆ F (ai ) ist ein Element von IB (d.h. F (ai ) ∈ IB)
ˆ F (Pik ) ist eine k–stellige Relation in IB (d.h. F (Pik ) ⊆ IB k )
ˆ F (ϕki ) ist eine k–stellige Funktion von IB in IB (d.h. F (ϕki ) : IB k → IB)
(Kommt unter den zweistelligen Prädikatensymbolen das Gleichheitszeichen
vor, so ist es stets durch die identische Relation in IB zu interpretieren.)
Durch eine solche Interpretation (IB, F ) wird zusammen mit einer Belegung
f der Individuen–Variablen mit Individuen (d.h., f : {xi|i ≥ 1} → IB) jedem
Term T ein Wert (Individuum) W (T, F, f ) zugeordnet:
nämlich
ˆ W (ai , F, f ) := F (ai) für jede Konstante ai
ˆ W (xi, F, f ) := f (xi) für jede Variable xi
ˆ W (ϕ(t1 , · · · , tk ), F, f ) := F (ϕ)(W (t1, F, f ), · · · , W (tk , F, f )) für jedes k–
stellige Funktionssymbol ϕ und Terme t1 , · · · , tk
(natürlich reicht es für einen vorgegebenen Term aus, nur die Interpretation
bzw. Belegung der wirklich in ihm vorkommenden Symbole zu kennen, um ihm
einen Wert zuordnen zu können).
92
2. Interpretation der Ausdrücke
Jetzt kann mittels (IB, F ) und f jedem prädikatenlogischen Ausdruck A ein
Wahrheitswert zugeordnet werden (abhängig von (IB, F ) und von f ):
1. falls A = P (t1 , · · · , tk ) ist für ein k–stelliges Prädikatensymbol P und Terme t1 , · · · , tk , so 
sei
 true,
falls ((W (t1, F, f ), · · · , W (tk , F, f )) ∈ F (P )
W w(A, F, f ) := 
f alse, sonst
2. A = ¬B:


true, falls W w(B, F, f ) = f alse
f alse, sonst


true, falls W w(B, F, f ) = true und W w(C, F, f ) = true
f alse, sonst


f alse, falls W w(B, F, f ) = f alse und W w(C, F, f ) = f alse
true, sonst


f alse, falls W w(B, F, f ) = true und W w(C, F, f ) = f alse
true, sonst


true, falls W w(B, F, f ) = W w(C, F, f )
f alse, sonst


true, falls für alle i ∈ IB gilt: W w(B[x/i], F, f ) = true
f alse, sonst


true, falls es ein i ∈ IB gibt mit W w(B[x/i], F, f ) = true
f alse, sonst
W w(A, F, f ) := 
A = (B ∧ C):
W w(A, F, f ) := 
A = (B ∨ C):
W w(A, F, f ) := 
A = (B → C):
W w(A, F, f ) := 
A = (B ↔ C):
W w(A, F, f ) := 
3. A = ∀xB:
W w(A, F, f ) := 
A = ∃xB:
W w(A, F, f ) := 
Dabei sei B[x/i] derjenige Ausdruck, den man aus B dadurch erhält, dass alle
freien Vorkommen von ”x” in B simultan durch das Individuum i ∈ IB ersetzt
werden.
Kommt in B die Variable x nicht frei vor, so ist
W w(∀xB, F, f ) = W w(∃xB, F, f ) = W w(B, F, f ).
Insbesondere gilt für jeden Ausdruck A ohne freie Vorkommen von Variablen
(d.h. für jede Aussage A):
Der Wahrheitswert von A hängt nur von der Interpretation (IB, F ) ab, nicht
aber von Belegungen f der Individuen–Variablen mit Individuen.
93
Modellbegriff, Erfüllbarkeit, Allgemeingültigkeit, Folgerungsbegriff,
semantische Äquivalenz
ˆ Eine Interpretation I = (IB, F ) ist zusammen mit einer Belegung f genau
dann ein Modell für A (bzw. A gilt bzgl. I, f ), wenn W w(A, F, f ) =
true ist.
ˆ Es heißt A genau dann allgemeingültig, symbolisch |= A, falls A bzgl.
jeder Interpretation und jeder zugehörigen Belegung gilt.
ˆ Es heißt A genau dann erfüllbar, wenn es ein Modell für A gibt.
ˆ Ein prädikatenlogischer Ausdruck B folgt genau dann aus einer Men-
ge M von prädikatenlogischen Ausdrücken, symbolisch M |= B, wenn bei
jeder Interpretation und jeder zugehörigen Belegung, bei denen alle Ausdrücke aus M true sind, auch B true ist (d.h., jedes Modell aller Ausdrücke
aus M ist auch ein Modell für B);
B folgt aus A, symbolisch A |= B, wenn bei jeder Interpretation und
jeder zugehörigen Belegung, bei denen A true ist, auch B true ist (d.h.,
jedes Modell für A ist auch ein Modell für B).
ˆ Zwei prädikatenlogische Ausdrücke A und B heißen genau dann seman-
tisch äquivalent, symbolisch A ≡ B, wenn jedes Modell für A auch ein
Modell für B ist und umgekehrt.
Beziehungen zu entsprechenden aussagenlogischen Begriffen:
Falls A eine aussagenlogische Tautologie ist und man für jede in A vorkommende Aussagenvariable einen prädikatenlogischen Ausdruck einsetzt (für gleiche
Variablen natürlich gleiche Ausdrücke), so erhält man einen allgemeingültigen
prädikatenlogischen Ausdruck. (Auf diese Weise lassen sich jedoch nicht alle
allgemeingültigen prädikatenlogischen Ausdrücke konstruieren.)
Analoges gilt bezüglich des Folgerungsbegriffs und bezüglich des Begriffs der
semantischen Äquivalenz.
94
ein paar wichtige Eigenschaften der semantischen Begriffe
Für prädikatenlogische Ausdrücke A, B, C und Mengen M solcher Ausdrücke
gilt:
ˆ Negationsregeln
¬∀x A
¬∃x A
≡
≡
∃x ¬A
∀x ¬A
ˆ Vertauschungsregeln:
∀x∀y A
∃x∃y A
≡
≡
∀y∀x A
∃y∃x A
ˆ Ausklammerungsregeln:
(∀x A) ∧ (∀x B)
(∃x A) ∨ (∃x B)
≡
≡
∀x(A ∧ B)
∃x(A ∨ B)
ˆ (∀x A) ∨ (∀x B)
|= ∀x(A ∨ B)
(aber nicht umgekehrt)
ˆ ∃x(A ∧ B)
|= (∃x A) ∧ (∃x B)
(aber nicht umgekehrt)
ˆ ∃x∀y A
|= ∀y∃x A
(aber nicht umgekehrt)
ˆ falls A |= B gilt und A abgeschlossen ist, so ist (A → B) allgemeingültig
ˆ es ist A genau dann allgemeingültig, wenn ¬A nicht erfüllbar ist
ˆ falls A |= B und B |= C gilt, so ist A |= C
ˆ falls A allgemeingültig ist, so ist stets M |= A
ˆ falls M |= A und M |= A → B gilt, so gilt M |= B
ˆ falls M nur allgemeingültige Ausdrücke enthält und M |= A gilt, so ist A
allgemeingültig
ˆ mögen in A genau die Variablen x1 , · · · , xn frei vorkommen; dann gilt:
A ist genau dann allgemeingültig, wenn ∀x1 · · · ∀xn A allgemeingültig ist;
A ist genau dann erfüllbar, wenn ∃x1 · · · ∃xn A erfüllbar ist
95
programmiertechnische Umsetzung
Pseudocodes für die programmiertechnische Realisierung zweier prädikatenlogischer Ausdrücke, wenn dabei ein endlicher Individuenbereich M vorgegeben
ist:
ˆ ∀x(x ∈ M → P (x))
Pseudocode:
flag := true;
forall x ∈ M
if (¬P (x))
{
flag := false;
break;
}
return flag;
ˆ ∃x(x ∈ M ∧ P (x))
Pseudocode:
flag := false;
forall x ∈ M
if (P (x))
{
flag := true;
break;
}
return flag;
Je nach der Art der Abspeicherung der Elemente von M sind die entsprechenden
Schleifenkonstrukte zur Simulation von
forall x ∈ M
heranzuziehen.
96
Deterministischer endlicher Automat A ohne Ausgabe
(deterministischer endlicher Akzeptor)
A = (E, Z, f, z0, F )
wobei
ˆ E
Eingabealphabet
ˆ Z
Zustandsmenge
ˆ f :Z×E →Z
(Zustands–)Überführungsfunktion
ˆ z0 ∈ Z
ˆ F ⊆Z
Startzustand
Menge der Endzustände
E, Z: endliche Mengen
Akzeptanz einer Zeichenkette w ∈ E ∗ durch A:
w wird genau dann akzeptiert, wenn der Automat unmittelbar vor der Verarbeitung von w im Startzustand z0 ist und sich unmittelbar nach dem Verarbeiten
von w in einen Endzustand befindet. (Es spielt dabei keine Rolle, ob der Automat zwischenzeitlich schon ein– oder mehrmals in einem Endzustand war.)
Nichtdeterministischer endlicher Automat A ohne Ausgabe
(nichtdeterministischer endlicher Akzeptor)
A = (E, Z, f, Z0, F )
wobei
ˆ E
Eingabealphabet
ˆ Z
Zustandsmenge
ˆ f : Z × E → PZ
(Zustands–)Überführungsfunktion
(PZ: Potenzmenge von Z)
ˆ Z0 ⊆ Z
ˆ F ⊆Z
Menge der Startzustände
Menge der Endzustände
E, Z: endliche Mengen
Akzeptanz einer Zeichenkette w ∈ E ∗ durch A:
Der Automat befinde sich anfangs in irgendeinem Startzustand z0 ∈ Z0. Genau
dann, wenn es möglich ist (wenn also f es zulässt), dass der Automat sich
unmittelbar nach Verarbeitung von w in einem Endzustand befindet, akzeptiert
er w.
97
Nichtdeterministischer endlicher Akzeptor A mit
Epsilon–Übergängen
A = (E, Z, f, Z0, F )
wobei
ˆ E
Eingabealphabet
ˆ Z
Zustandsmenge
ˆ f : Z × (E ∪ {ε}) → PZ
ˆ Z0 ⊆ Z
ˆ F ⊆Z
(Zustands–)Überführungsfunktion
Menge der Startzustände
Menge der Endzustände
E, Z: endliche Mengen
Interpretation der Epsilon–Übergänge:
Falls f (z, ε) = Z1 ist für z ∈ Z, Z1 ⊆ Z, so soll der Automat, falls er sich in
einem bestimmten Takt im Zustand z befindet, spontan in irgendeinen Zustand
z ′ ∈ Z1 übergehen können, ohne dass die Position des Lesekopfes auf dem Eingabeband geändert wird (es wird in einer solchen Situation kein Eingabesymbol
gelesen bzw. verarbeitet).
Es gilt für jede Sprache L ⊆ E ∗:
es gibt einen deterministischen endlichen Akzeptor mit E als
Eingabealphabet, der L akzeptiert
←→
es gibt einen nichtdeterministischen endlichen Akzeptor mit E als
Eingabealphabet, der L akzeptiert
←→
es gibt einen nichtdeterministischen endlichen Akzeptor mit
Epsilon–Übergängen und mit E als Eingabealphabet, der L akzeptiert
98
Reguläre Ausdrücke (regular expressions)
Die Menge der regulären Ausdrücke zur Charakterisierung der regulären
Sprachen über einem endlichen Alphabet E ist rekursiv wie folgt definiert:
(a) Rekursions–Anfang
∅, ε und jedes a ∈ E seien reguläre Ausdrücke.
(b) Rekursions–Schritt
Falls α und β reguläre Ausdrücke sind, so seien auch
(α | β), (α ◦ β) und (α∗) reguläre Ausdrücke.
(c) Minimalbedingung
Nur aufgrund von (a) und (b) sollen reguläre Ausdrücke zur Charakterisierung regulärer Sprachen über E erhalten werden können.
Vorrangregeln, auf deren Grundlage Klammern eingespart werden können:
Von den drei Operatoren soll ’|’ am stärksten trennen, dann ’◦’, dann ’∗’, und
ein äußeres Klammernpaar darf weggelassen werden.
Außerdem wird der Operator ’◦’ auch manchmal als Punkt notiert oder ganz
weggelassen.
Beispiel: Der reguläre Ausdruck
(a | ((b ◦ (c∗ )) ◦ d))
über dem Alphabet {a, b, c, d} kann somit auch folgendermaßen notiert werden:
a | bc∗ d
Parallel zur rekursiven Definition der regulären Ausdrücke wird, ebenfalls rekursiv, jedem solchen Ausdruck α eine Sprache L(α) über dem Alphabet E
zugeordnet:
(a) Rekursions–Anfang
Es seien L(∅) := ∅ (die leere Sprache), L(ε) := {ε} (Einermenge leeres
Wort) und für jedes a ∈ E sei L(a) := {a} (Einermenge von a, wobei a
hier als Zeichenkette der Länge 1 interpretiert wird).
(b) Rekursions–Schritt
Falls α und β reguläre Ausdrücke sind, so sei
L(α | β) := L(α) ∪ L(β) (Vereinigung von L(α)und L(β)),
L(αβ) := L(α)L(β) (Verkettung bzw. Produkt der Sprachen L(α) und
L(β)),
L(α∗) := (L(α))∗ (Menge aller endlichen Verkettungen von Zeichenketten
aus L(α); Sternoperation, KLEENE’sche Hülle).
99
Reguläre Ausdrücke in UNIX–Notation
Die UNIX–Kommandos grep, fgrep, egrep (grep: globally search for regular expression and print), awk (awk: Aho/Weinberger/Kernighan) und lex benutzen
reguläre Ausdrücke als Argumente, um Textzeilen in Dateien nach Zeichenketten zu durchsuchen, die bestimmte Muster haben (grep, fgrep, egrep), um
darüberhinausgehend Textdateien zu formatieren und zu transformieren (awk)
und um lexikalische Analysen von Programmtexten durchzuführen (lex).
Dabei gilt für Textsuchmuster zunächst die Regel:
ˆ Kein Suchmuster (d.h. regulärer Ausdruck) wirkt über eine Zeile hinaus.
Beispiele:
ˆ grep ’^[0-9][0-9]*$’ datei.txt
Es werden alle Zeilen von datei.txt ausgegeben, die nur Dezimalziffern
(mindestens eine) enthalten.
Dabei kennzeichnen ’∧’ den Zeilenanfang und ’$’ das Zeilenende.
ˆ grep ’^[sS]’ datei.txt
Es werden alle Zeilen von datei.txt ausgegeben, die mit ’s’ oder mit ’S’
beginnen.
ˆ grep ’a.c’ datei.txt
Es werden alle Zeilen von datei.txt ausgegeben, die eine Teilzeichenkette
der Länge drei haben mit erstem Zeichen ’a’, beliebigem zweiten Zeichen
und drittem Zeichen ’c’. Der Punkt hat also eine wild card–Funktion.
ˆ egrep ’ab?c’ datei.txt
Es werden alle Zeilen von datei.txt ausgegeben, die eine Teilzeichenkette
der Gestalt ”ac” oder ”abc” enthalten. Das Fragezeichen stellt also das
Vorkommen von ’b’ in Frage.
ˆ egrep ’[0-9]+\.[0-9]* | \.[0-9]+’ datei.txt
Es werden alle Zeilen von datei.txt ausgegeben, die eine dezimale Gleitpunktzahl x.y enthalten, wobei x aus mindestens einer Ziffer besteht und
y leer sein kann, oder x ist leer und y besteht aus mindestens einer Ziffer.
100
Chomsky–Hierarchie von Grammatiken
(Noam Chomsky, *1928)
Ausgangspunkt ist der Begriff der Grammatik G = (T, N, P, S).
Definition:
1. Jede Grammatik ist vom Typ 0.
2. Eine Grammatik ist genau dann vom Typ 1 oder kontextsensitiv, wenn
für alle Regeln u → v aus P gilt:
length(u) ≤ length(v)
3. Eine Grammatik ist genau dann vom Typ 2 oder kontextfrei, falls sie
vom Typ 1 ist und zusätzlich für alle Regeln u → v aus P gilt:
u ist ein Metasymbol
4. Eine Grammatik ist genau dann vom Typ 3 oder regulär, falls sie vom
Typ 2 ist und zusätzlich für alle Regeln u → v aus P gilt:
v = ε oder v ist ein einzelnes Terminalsymbol
oder v ist ein Terminalsymbol gefolgt von einem Metasymbol.
Eine solche Grammatik heißt auch rechtslinear.
Eine Sprache L über dem Alphabet T , d.h. L ⊆ T ∗, heiße genau dann vom Typ
0 bzw. 1 bzw. 2 bzw. 3, falls es eine Typ–0– bzw. Typ–1– bzw. Typ–2– bzw.
Typ–3–Grammatik G gibt, so dass L = L(G) ist.
kontextsensitiv: Es sind Regeln der Gestalt ”u1Au2 → u1xu2”mit A ∈ N erlaubt,
und eine solche Regel besagt, dass ’A’ zwischen ’u1’ und ’u2’, also im Kontext
von ’u1’ und ’u2’, durch ’x’ ersetzt werden darf.
Bemerkungen:
ˆ Bei Typ–1–Grammatiken soll bei Bedarf die Ableitungsregel ”S → ε” zu-
gelassen sein, dann darf ’S’ aber nicht auf der rechten Seite einer Ableitungsregel vorkommen.
ˆ Bei kontextfreien Grammatiken darf man beliebig Ableitungsregeln der
Gestalt ”A → ε” mit A ∈ N verwenden, also auch ”S → ε” für das Startsymbol ’S’, falls man ε ∈ L(G) haben möchte.
101
Pumping–Lemma
Zunächst kann man beweisen, dass für jede Sprache L ⊆ E ∗ gilt:
es gibt einen (deterministischen oder nichtdeterministischen) endlichen
Akzeptor mit E als Eingabealphabet, der L akzeptiert
←→
es gibt einen regulären Ausdruck α über dem Alphabet E mit L = L(α)
←→
es gibt eine reguläre Grammatik G mit E als Terminalalphabet, so dass
L = L(G) ist
Um zeigen zu können, dass eine bestimmte Sprache nicht regulär ist, ist oft das
Pumping–Lemma hilfreich.
Pumping–Lemma:
Wenn L eine reguläre Sprache ist, so gibt es eine natürliche Zahl n, so dass sich
alle Wörter w ∈ L mit length(w) ≥ n zerlegen lassen in w = w1w2w3 , wobei
length(w2 ) ≥ 1, length(w1w2 ) ≤ n und w1w2i w3 ∈ L gilt für alle i ∈ N.
Mit Hilfe des Pumping–Lemmas kann beispielsweise bewiesen werden, dass jede
der drei folgenden Sprachen L1, L2 und L3 nicht regulär ist:
L1 := {an bn | n ≥ 1}
L2 := {0n | n ist eine Quadratzahl}
L3 := {0p | p ist eine Primzahl}
102
Deterministischer endlicher Automat A mit Ausgabe
(Mealy–Automat)
A = (E, A, Z, f, g, z0)
wobei
ˆ E
Eingabealphabet
ˆ A
Ausgabealphabet
ˆ Z
Zustandsmenge
ˆ f :Z×E →Z
Überführungsfunktion
ˆ g : Z × E → A Ausgabefunktion
ˆ z0 ∈ Z
Startzustand
E, A, Z: endliche Mengen
103
Nichtdeterministischer endlicher Kellerautomat A
(nondeterministic finite pushdown automaton)
A = (E, Z, K, f, z0, k0, F )
wobei
ˆ E
Eingabealphabet
ˆ Z
Zustandsmenge
ˆ K
Menge der Kellersymbole
ˆ f : Z × (E ∪ {ε}) × K → P(Z × K ∗ ) Überführungsfunktion
ˆ z0 ∈ Z
Startzustand
ˆ k0 ∈ K:
Kellerstartsymbol
ˆ F ⊆Z
Menge der Endzustände
E, Z, K: endliche Mengen
Arbeitsweise:
Anfangs befindet sich der Automat im Startzustand z0 , im Keller befindet sich
nur das Kellerstartsymbol k0 und das Eingabewort befindet sich auf dem Eingabeband, wobei der Lesekopf unter dem ersten Symbol des Eingabewortes steht,
falls dieses nicht leer ist.
Der Automat arbeitet wieder getaktet (wie alle Automaten), und sein Verhalten in den folgenden Takten wird durch die Überführungsfunktion f bestimmt: Befindet sich der Automat gerade im Zustand z, ist k das oberste
Kellersymbol und ist a das aktuelle Eingabesymbol, so wird ein Paar (z ′ , w) ∈
(f (z, ε, k) ∪ f (z, a, k)) zufällig ausgewählt, und im Folgetakt befindet sich der
Automat im Zustand z ′ , das vorher oberste Kellersymbol ist durch die Zeichenkette w von Kellersymbolen ersetzt worden (so dass jetzt das erste Zeichen von
w oberstes Kellersymbol ist). Dabei ist der Lesekopf des Eingabebandes nur
dann um einen Schritt nach rechts gerückt worden, wenn (z ′ , w) ∈ f (z, a, k)
galt.
Falls w die leere Zeichenkette war, so wurde also bzgl. des Kellers eine pop–
Operation durchgeführt.
Ist ein (z ′ , w) ∈ f (z, ε, k) gewählt worden, so dass also der Lesekopf des Eingabewortes sich in diesem Takt nicht weiter bewegt, so spricht man wieder von
einem Epsilon–Übergang.
104
Akzeptanz von Sprachen durch nichtdeterministische endliche
Kellerautomaten
Es gibt hier zwei Arten der Akzeptanz:
ˆ Akzeptanz durch Endzustand:
Ein Eingabewort wird hier genau dan akzeptiert, wenn sich der Automat
unmittelbar nach Verarbeitung des Wortes in einem Endzustand befindet.
Der Inhalt des Stacks zu diesem Zeitpunkt ist völlig irrelevant, so dass man
durch Hinzufügen geeigneter Epsilon–Übergänge auch erreichen könnte,
dass sich im Keller nur noch das Kellerstartsymbol befindet oder dass der
Keller leer ist.
ˆ Akzeptanz durch leeren Keller:
Ein Eingabewort wird hier genau dan akzeptiert, wenn der Stack des Automaten unmittelbar nach Verarbeitung des Wortes leer ist (zwischenzeitlich
darf er natürlich nicht leer sein, weil dann ein Weiterarbeiten des Automaten nicht möglich wäre). Der Zustand des Automaten unmittelbar nach
Verarbeitung des Wortes ist dabei irrelevant.
Es gilt für eine beliebige Sprache L ⊆ E ∗ :
es gibt einen nichtdeterministischen Kellerautomaten
(E, Z, K, f, z0, k0, F )
der L per Akzeptanz durch Endzustand akzeptiert
←→
es gibt einen nichtdeterministischen Kellerautomaten
(E, Z ′, K ′, f ′, z0′ , k0′ , F ′)
der L per Akzeptanz durch leeren Keller akzeptiert
Genau dann, wenn L auf eine dieser Arten akzeptiert wird, ist L eine kontextfreie Sprache über E.
105
Deterministischer endlicher Kellerautomat A
Ein deterministischer Kellerautomat A = (E, Z, K, f, z0, k0, F ) ist ein spezieller
nichtdeterministischer Kellerautomat, für den zusätzlich gilt:
ˆ für alle (z, a, k) ∈ Z × (E ∪ {ε}) × K ist card(f (z, a, k)) ≤ 1
ˆ wenn f (z, a, k) 6= ∅ ist für ein a ∈ E, so muss f (z, ε, k) = ∅ sein
Die Sprache L ⊆ E ∗ eines solchen Kellerautomaten bestehe aus genau denjenigen Zeichenketten, die von dem Automaten durch Akzeptanz durch Endzustand
akzeptiert werden.
Jede solche Sprache heiße deterministisch kontextfrei.
Es gilt für jedes Alphabet E:
Jede reguläre Sprache über E ist auch eine deterministisch kontextfreie Sprache
über E.
Jede deterministisch kontextfreie Sprache über E ist auch eine kontextfreie
Sprache über E.
106
Deterministische Turing–Maschine T
Alan Turing (1911 - 1954)
T = (Z, E, Γ, f, z0, 2, F )
wobei
ˆ Z
Zustandsmenge
ˆ E
Eingabealphabet
ˆ Γ
Menge der Bandsymbole mit E ⊂ Γ
ˆ f : Z × Γ → Z × Γ × {L, R, N }
Überführungsfunktion
ˆ z0 ∈ Z
Startzustand
ˆ 2
Blank– bzw. Trennsymbol mit 2 ∈ Γ \ E
ˆ F ⊆Z
Menge der Endzustände
Z, Γ: endliche Mengen
Falls beispielsweise f (z, a) = (z ′ , b, L) ist und die Turing–Maschine sich im
Takt t im Zustand z befindet sowie der Lese/Schreib–Kopf auf dem Bandsymbol a steht, so geht sie in den Zustand z ′ über, überschreibt a mit b und der
Lese/Schreib–Kopf rückt um eine Position nach links. Das ist dann die Ausgangssituation im Takt t+1.
Akzeptanz eines Wortes w ∈ E ∗ durch T :
Ausgangssituation: Die Turing–Maschine befindet sich im Startzustand z0 , w
befindet sich auf dem Band, beidseitig durch je mindestens ein Blank begrenzt,
und der L/S–Kopf befindet sich unmittelbar unter dem ersten Zeichen von w
(oder, äquivalent dazu, unmittelbar links von w). Wie durch die Funktion f
gegeben, nimmt die Maschine getaktet ihre Arbeit auf. Genau dann, wenn sie
dabei (nach endlich vielen Takten) in einen Endzustand kommt, wird w akzeptiert, und die Maschine beendet ihre Arbeit. (Dabei muss w nicht unbedingt
vollständig inspiziert worden sein.)
Es gilt dann für jedes Alphabet E und jede Sprache L ⊆ E ∗ :
L ist vom Typ 0
←→
es gibt eine (deterministische) Turingmaschine mit dem Eingabealphabet E, die
genau die Zeichenketten aus L akzeptiert.
(Analoges gilt für nichtdeterministische Turing–Maschinen.)
107
Turing–Berechenbarkeit
Turing–Maschinen können nicht nur als Akzeptoren benutzt werden, sondern
sie sind auch einsetzbar zur Berechnung von Zeichenketten.
Konfiguration bzw. Momentaufnahme einer deterministische Turing–Maschine
T:
(γ1, z, γ2) ∈ Γ∗ × Z × Γ∗
wobei z der aktuelle Zustand ist, der L/S–Kopf sich unter dem ersten Symbol
von γ2 befindet (bzw. unmittelbar rechts von γ1 , falls γ2 = ε) , γ2 sich unmittelbar rechts an γ1 anschließt und links von γ1 und rechts von γ2 auf dem Band
nur Blank–Symbole stehen.
Anfangskonfiguration bzw. Startkonfiguration von T für ein Eingabewort w :=
e1 · · · en ∈ E ∗:
(ε, z0, w) bzw. (ε, z0, e1 · · · en )
Außer w stehen auf dem Band nur Blanks.
Übergangsrelation ⊢ in der Menge der Konfigurationen:
es sei genau dann (α, z, β) ⊢ (α′ , z ′ , β ′), wenn die Konfiguration (α, z, β)
durch genau einen Rechenschritt (genau eine Anwendung von f ) in die
Konfiguration (α′ , z ′ , β ′) übergeführt wird
erweiterte Übergangsrelation ⊢∗ in der Menge der Konfigurationen:
es sei genau dann (α, z, β) ⊢∗ (α′ , z ′ , β ′), wenn es ein n ∈ N
und Konfigurationen (αi , ζi, βi) mit 0 ≤ i ≤ n und (α, z, β) = (α0 , ζ0, β0),
(αn , ζn, βn ) = (α′, z ′ , β ′) gibt, so dass gilt
(α0 , ζ0, β0) ⊢ (α1 , ζ1, β1) ⊢ · · · ⊢ (αn , ζn, βn )
Eine Berechnung mit dem Eingabewort w ∈ E ∗ ist eine Folge
(ε, z0, w) ⊢ (α1, z1 , β1) ⊢ (α2 , z2, β2) ⊢ · · ·
von Konfigurationen mit folgender Eigenschaft:
Die Berechnung wird beim ersten Erreichen eines Endzustandes gestoppt; das
Ergebnis steht dann auf dem Eingabeband ab der Position des L/S–Kopfes nach
rechts bis unmittelbar vor dem ersten Blank. Falls nie ein Endzustand erreicht
wird, so wird kein Ergebnis berechnet (Realisierung einer partiellen Funktion
f ).
108
Turing–Programm zur Addition zweier durch Strichfolgen
gegebener positiver natürlicher Zahlen
ˆ Ausgangsposition (”Standardlage”) des L/S–Kopfes:
unter dem ersten Zeichen des ersten Operanden (entspricht dem Startzustand zo )
ˆ Die zu verarbeitenden Zahlen seien durch genau ein Feld mit dem Inhalt
’#’ (# ∈ Γ \ E) voneinander und durch je mindestens ein Feld mit dem
Inhalt ’2’ von ihrer Umgebung getrennt.
ˆ Endposition des L/S–Kopfes:
unter dem ersten Zeichen des Ergebnisses
while (<Arbeitsfeld> = ’|’)
R;
write(’|’) ;
while (<Arbeitsfeld> = ’|’)
L;
R;
write(’2’) ;
R;
These von Church (1936) (Alonzo Church, 1903–1995)
Genau die im intuitiven Sinne berechenbaren zahlentheoretischen Funktionen
(bzw. Wortfunktionen) sind die Turing–berechenbaren zahlentheoretischen Funktionen (bzw. Wortfunktionen).
(”Turing–berechenbar” wird mit ”algorithmisch berechenbar” gleichgesetzt)
Mit Hilfe einer Gödelisierung kann jeder Wortfunktion eineindeutig und effektiv eine zahlentheoretische Funktion zugeordnet werden. Es sind dann entweder
beide berechenbar oder beide nicht berechenbar.
109
Loop– und While–Berechenbarkeit
Loop–Programm:
Es seien x0, x1, · · · Variablen für natürliche Zahlen und c eine natürlichzahlige
Konstante. Dann seien loop–Programme wie folgt rekursiv definiert:
(a) jede Wertzuweisung
xi := xj + c
bzw.
xi := xj − c
sei ein loop–Programm (i, j ∈ N)
(b) falls P, P1 , P2 bereits loop–Programme sind, so seien auch
P1 ; P2
und
loop xi do P end
loop–Programme (i ∈ N)
(c) Nur aufgrund von (a) und (b) sollen loop–Programme erhalten werden
können.
Loop–Berechenbarkeit:
Eine Funktion f : Nk → N heiße genau dann loop–berechenbar, wenn es ein
loop–Programm P gibt, das, gestartet mit den Werten n1 , · · · , nk in den Variablen x1, · · · , xk (und 0 in den anderen Variablen), nach endlich vielen Schritten
stoppt mit dem Wert f (n1, · · · , nk ) in der Variablen x0.
Dabei habe
n−m
für den Fall m > n den Wert 0 und werde sonst durch die übliche Subtraktion
interpretiert,
während in
loop xi do P end
das Programm P genau so oft ausgeführt werden möge, wie es der Wert von xi
beim Eintritt in diese Schleife angibt (unabhängig davon, ob der Wert von xi
innerhalb der Schleife geändert wird oder nicht).
110
Definitionen: Für beliebige i, j, r ∈ N werde vereinbart
ˆ xi := xj
bedeute
xi := xj + 0
ˆ xi := c
bedeute
xi := xj + c
für eine sonst nicht benutzte Variable xj (die also den Wert 0 hat)
ˆ if xi = 0 then P end
bedeute
xj := 1; loop xi do xj := 0 end;
wobei i 6= j sei
loop xj do P end
ˆ xr := xi + xj
bedeute
xr := xi; loop xj do xr := xr + 1 end
wobei r =
6 j sei
ˆ xr := xi ∗ xj
bedeute
xr := 0; loop xj do xr := xr + xi end
wobei r 6= i und r 6= j sei
Es existieren loop–Programme für die Berechnungen der Werte weiterer bekannter zahlentheoretischer Funktionen wie div, mod, ggt, kgV , min, max,
Potenz mit natürlichzahliger Basis und natürlichzahligem Exponenten, Betrag
der Differenz, Fakultätsfunktion, Anzahl der Primzahlen kleinergleich einer vorgegebenen Zahl, i–te Primzahl für ein vorgegebenes i ∈ N usw.
Nicht durch ein loop–Programm lässt sich die Ackermann–Funktion ack von
Folie 65 simulieren.
Die übrigen Funktionen von Folie 65 sind loop–berechenbar.
111
While–Programm:
(a) jedes loop–Programm sei auch ein while–Programm
(b) falls P ein while–Programme ist, so sei auch
while xi 6= 0 do P end
ein while–Programm (i ∈ N)
(c) Nur aufgrund von (a) und (b) sollen while–Programme erhalten werden
können.
Nachträglich könnte die loop–Schleife wieder eliminiert werden, denn
loop xi do P end
kann simuliert werden durch
xj := xi ;
while xj 6= 0 do xj := xj − 1; P end
mit i 6= j, xj kommt nicht in P vor
While–Berechenbarkeit:
Eine partielle Funktion f : Nk 7→ N heiße genau dann while–berechenbar,
wenn es ein while–Programm P gibt, das, gestartet mit den Werten n1, · · · , nk
in den Variablen x1, · · · , xk (und 0 in den anderen Variablen), nach endlich vielen Schritten stoppt mit dem Wert f (n1, · · · , nk ) in der Variablen x0, sofern
f (n1, · · · , nk ) definiert ist; sonst soll P nicht stoppen.
Damit ist jede loop–berechenbare Funktion auch while–berechenbar.
Es gibt while–berechenbare Funktionen, die nicht loop–berechenbar sind, beispielsweise die Ackermann–Funktion.
Es gilt:
Eine partielle Funktion f : Nk 7→ N ist genau dann while–berechenbar, wenn
es eine (deterministische oder nichtdeterministische) Turing–Maschine gibt, die
den Funktionswert f (x1, · · · , xk ) berechnet, falls er existiert, und die sonst bei
der Eingabe von (x1, · · · , xk ) nicht anhält.
112
Herunterladen